linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/3] ASoC: stm32: add S/PDIF support to SAI
@ 2018-02-19 15:00 Olivier Moysan
  2018-02-19 15:00 ` [RFC PATCH 1/3] ASoC: stm32: Add S/PDIF to SAI bindings Olivier Moysan
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Olivier Moysan @ 2018-02-19 15:00 UTC (permalink / raw)
  To: lgirdwood, broonie, perex, tiwai, mcoquelin.stm32,
	alexandre.torgue, alsa-devel, robh, mark.rutland, devicetree,
	linux-arm-kernel, kernel, linux-kernel, olivier.moysan
  Cc: arnaud.pouliquen, benjamin.gaignard

This patch-set adds S/PDIF IEC6958 protocol support to STM32 SAI.
Only S/PDIF playback is supported here, as SAI peripheral does not support S/PDIF capture.

SAI peripheral does not take as input full IEC60958 frames as it generates preamble and parity bit.
However, it cannot handle raw PCM data, as it is not designed to insert channel status and user data
in the generated IEC frames.

Moreover, SAI data register format does not match exactly IEC60958 subframe format.
(see figure below). Channel status (C) and User data (U) are at 26-25 bits position,
in data register, instead of 30-29 bits position.
    
IEC60958 subframe bits:
31-28                       27-4                         3-0
P    C    U    V            data (16|24 bits)            preamble

SAI data register format:
27-24                        23-0						
P     C    U    V            data (16|24 bits)

The impact in software is that the data have to be processed before DMA transfer.
These constraints should be managed at driver level to minimize the impact on application.
This means that a callback is necessary to perform data processing (shift and channel status insertion)

This patch-set introduces a callback to allow processing on samples.
The implementation is based on previous discussions available here:
https://patchwork.kernel.org/patch/9570255/

BRs
Olivier

Olivier Moysan (3):
  ASoC: stm32: Add S/PDIF to SAI bindings
  ASoC: dmaengine_pcm: add processing support
  ASoC: stm32: sai: Add support of S/PDIF playback

 .../devicetree/bindings/sound/st,stm32-sai.txt     |   6 +
 include/sound/dmaengine_pcm.h                      |   3 +
 sound/soc/soc-generic-dmaengine-pcm.c              |  62 ++++++++-
 sound/soc/stm/stm32_sai.c                          |   2 +
 sound/soc/stm/stm32_sai.h                          |   2 +
 sound/soc/stm/stm32_sai_sub.c                      | 153 +++++++++++++++++----
 6 files changed, 202 insertions(+), 26 deletions(-)

-- 
1.9.1

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

* [RFC PATCH 1/3] ASoC: stm32: Add S/PDIF to SAI bindings
  2018-02-19 15:00 [RFC PATCH 0/3] ASoC: stm32: add S/PDIF support to SAI Olivier Moysan
@ 2018-02-19 15:00 ` Olivier Moysan
  2018-02-26 11:20   ` Applied "ASoC: stm32: Add S/PDIF to SAI bindings" to the asoc tree Mark Brown
  2018-02-19 15:00 ` [RFC PATCH 2/3] ASoC: dmaengine_pcm: add processing support Olivier Moysan
  2018-02-19 15:00 ` [RFC PATCH 3/3] ASoC: stm32: sai: Add support of S/PDIF playback Olivier Moysan
  2 siblings, 1 reply; 6+ messages in thread
From: Olivier Moysan @ 2018-02-19 15:00 UTC (permalink / raw)
  To: lgirdwood, broonie, perex, tiwai, mcoquelin.stm32,
	alexandre.torgue, alsa-devel, robh, mark.rutland, devicetree,
	linux-arm-kernel, kernel, linux-kernel, olivier.moysan
  Cc: arnaud.pouliquen, benjamin.gaignard

Add S/PDIF IEC6958 protocol support to STM32 SAI bindings.

Signed-off-by: olivier moysan <olivier.moysan@st.com>
---
 Documentation/devicetree/bindings/sound/st,stm32-sai.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
index b1acc1a..f301cdf 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -45,6 +45,12 @@ SAI subnodes Optional properties:
 	This property sets SAI sub-block as slave of another SAI sub-block.
 	Must contain the phandle and index of the sai sub-block providing
 	the synchronization.
+  - st,iec60958: support S/PDIF IEC6958 protocol for playback
+	IEC60958 protocol is not available for capture.
+	By default, custom protocol is assumed, meaning that protocol is
+	configured according to protocol defined in related DAI link node,
+	such as i2s, left justified, right justified, dsp and pdm protocols.
+	Note: ac97 protocol is not supported by SAI driver
 
 The device node should contain one 'port' child node with one child 'endpoint'
 node, according to the bindings defined in Documentation/devicetree/bindings/
-- 
1.9.1

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

* [RFC PATCH 2/3] ASoC: dmaengine_pcm: add processing support
  2018-02-19 15:00 [RFC PATCH 0/3] ASoC: stm32: add S/PDIF support to SAI Olivier Moysan
  2018-02-19 15:00 ` [RFC PATCH 1/3] ASoC: stm32: Add S/PDIF to SAI bindings Olivier Moysan
@ 2018-02-19 15:00 ` Olivier Moysan
  2018-02-19 15:00 ` [RFC PATCH 3/3] ASoC: stm32: sai: Add support of S/PDIF playback Olivier Moysan
  2 siblings, 0 replies; 6+ messages in thread
From: Olivier Moysan @ 2018-02-19 15:00 UTC (permalink / raw)
  To: lgirdwood, broonie, perex, tiwai, mcoquelin.stm32,
	alexandre.torgue, alsa-devel, robh, mark.rutland, devicetree,
	linux-arm-kernel, kernel, linux-kernel, olivier.moysan
  Cc: arnaud.pouliquen, benjamin.gaignard

Allow dmaengine client to optionally register a processing callback.
This callback is intended to apply processing
on samples in buffer copied from/to user space, before/after DMA transfer.

Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
---
 include/sound/dmaengine_pcm.h         |  3 ++
 sound/soc/soc-generic-dmaengine-pcm.c | 62 +++++++++++++++++++++++++++++++++--
 2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index 8a5a840..47ef486 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -140,6 +140,9 @@ struct snd_dmaengine_pcm_config {
 	struct dma_chan *(*compat_request_channel)(
 			struct snd_soc_pcm_runtime *rtd,
 			struct snd_pcm_substream *substream);
+	int (*process)(struct snd_pcm_substream *substream,
+		       int channel, unsigned long hwoff,
+		       void *buf, unsigned long bytes);
 	dma_filter_fn compat_filter_fn;
 	struct device *dma_dev;
 	const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index c07d5c7..1c1d838 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -340,6 +340,41 @@ static snd_pcm_uframes_t dmaengine_pcm_pointer(
 		return snd_dmaengine_pcm_pointer(substream);
 }
 
+static int dmaengine_copy_user(struct snd_pcm_substream *substream,
+			       int channel, unsigned long hwoff,
+			       void *buf, unsigned long bytes)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_component *component =
+		snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_PCM_DRV_NAME);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct dmaengine_pcm *pcm = soc_component_to_pcm(component);
+	int (*process)(struct snd_pcm_substream *substream,
+		       int channel, unsigned long hwoff,
+		       void *buf, unsigned long bytes) = pcm->config->process;
+	bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+	void *dma_ptr = runtime->dma_area + hwoff +
+			channel * (runtime->dma_bytes / runtime->channels);
+	int ret;
+
+	if (is_playback)
+		if (copy_from_user(dma_ptr, (void __user *)buf, bytes))
+			return -EFAULT;
+
+	if (process) {
+		ret = process(substream, channel, hwoff,
+			      (void __user *)buf, bytes);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (!is_playback)
+		if (copy_to_user((void __user *)buf, dma_ptr, bytes))
+			return -EFAULT;
+
+	return 0;
+}
+
 static const struct snd_pcm_ops dmaengine_pcm_ops = {
 	.open		= dmaengine_pcm_open,
 	.close		= snd_dmaengine_pcm_close,
@@ -350,6 +385,17 @@ static snd_pcm_uframes_t dmaengine_pcm_pointer(
 	.pointer	= dmaengine_pcm_pointer,
 };
 
+static const struct snd_pcm_ops dmaengine_pcm_process_ops = {
+	.open		= dmaengine_pcm_open,
+	.close		= snd_dmaengine_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= dmaengine_pcm_hw_params,
+	.hw_free	= snd_pcm_lib_free_pages,
+	.trigger	= snd_dmaengine_pcm_trigger,
+	.pointer	= dmaengine_pcm_pointer,
+	.copy_user	= dmaengine_copy_user,
+};
+
 static const struct snd_soc_component_driver dmaengine_pcm_component = {
 	.name		= SND_DMAENGINE_PCM_DRV_NAME,
 	.probe_order	= SND_SOC_COMP_ORDER_LATE,
@@ -357,6 +403,13 @@ static snd_pcm_uframes_t dmaengine_pcm_pointer(
 	.pcm_new	= dmaengine_pcm_new,
 };
 
+static const struct snd_soc_component_driver dmaengine_pcm_component_process = {
+	.name		= SND_DMAENGINE_PCM_DRV_NAME,
+	.probe_order	= SND_SOC_COMP_ORDER_LATE,
+	.ops		= &dmaengine_pcm_process_ops,
+	.pcm_new	= dmaengine_pcm_new,
+};
+
 static const char * const dmaengine_pcm_dma_channel_names[] = {
 	[SNDRV_PCM_STREAM_PLAYBACK] = "tx",
 	[SNDRV_PCM_STREAM_CAPTURE] = "rx",
@@ -449,8 +502,13 @@ int snd_dmaengine_pcm_register(struct device *dev,
 	if (ret)
 		goto err_free_dma;
 
-	ret = snd_soc_add_component(dev, &pcm->component,
-				    &dmaengine_pcm_component, NULL, 0);
+	if (config && config->process)
+		ret = snd_soc_add_component(dev, &pcm->component,
+					    &dmaengine_pcm_component_process,
+					    NULL, 0);
+	else
+		ret = snd_soc_add_component(dev, &pcm->component,
+					    &dmaengine_pcm_component, NULL, 0);
 	if (ret)
 		goto err_free_dma;
 
-- 
1.9.1

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

* [RFC PATCH 3/3] ASoC: stm32: sai: Add support of S/PDIF playback
  2018-02-19 15:00 [RFC PATCH 0/3] ASoC: stm32: add S/PDIF support to SAI Olivier Moysan
  2018-02-19 15:00 ` [RFC PATCH 1/3] ASoC: stm32: Add S/PDIF to SAI bindings Olivier Moysan
  2018-02-19 15:00 ` [RFC PATCH 2/3] ASoC: dmaengine_pcm: add processing support Olivier Moysan
@ 2018-02-19 15:00 ` Olivier Moysan
  2018-02-26 11:20   ` Applied "ASoC: stm32: sai: Add support of S/PDIF playback" to the asoc tree Mark Brown
  2 siblings, 1 reply; 6+ messages in thread
From: Olivier Moysan @ 2018-02-19 15:00 UTC (permalink / raw)
  To: lgirdwood, broonie, perex, tiwai, mcoquelin.stm32,
	alexandre.torgue, alsa-devel, robh, mark.rutland, devicetree,
	linux-arm-kernel, kernel, linux-kernel, olivier.moysan
  Cc: arnaud.pouliquen, benjamin.gaignard

Add support of S/PDIF iec60958 playback on STM32 SAI.

Signed-off-by: olivier moysan <olivier.moysan@st.com>
---
 sound/soc/stm/stm32_sai.c     |   2 +
 sound/soc/stm/stm32_sai.h     |   2 +
 sound/soc/stm/stm32_sai_sub.c | 153 +++++++++++++++++++++++++++++++++++-------
 3 files changed, 133 insertions(+), 24 deletions(-)

diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index d743b7d..f226542 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -30,10 +30,12 @@
 
 static const struct stm32_sai_conf stm32_sai_conf_f4 = {
 	.version = SAI_STM32F4,
+	.has_spdif = false,
 };
 
 static const struct stm32_sai_conf stm32_sai_conf_h7 = {
 	.version = SAI_STM32H7,
+	.has_spdif = true,
 };
 
 static const struct of_device_id stm32_sai_ids[] = {
diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h
index bb062e7..f254221 100644
--- a/sound/soc/stm/stm32_sai.h
+++ b/sound/soc/stm/stm32_sai.h
@@ -248,9 +248,11 @@ enum stm32_sai_version {
 /**
  * struct stm32_sai_conf - SAI configuration
  * @version: SAI version
+ * @has_spdif: SAI S/PDIF support flag
  */
 struct stm32_sai_conf {
 	int version;
+	bool has_spdif;
 };
 
 /**
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 08583b9..cfeb219 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -23,6 +23,7 @@
 #include <linux/of_platform.h>
 #include <linux/regmap.h>
 
+#include <sound/asoundef.h>
 #include <sound/core.h>
 #include <sound/dmaengine_pcm.h>
 #include <sound/pcm_params.h>
@@ -30,6 +31,7 @@
 #include "stm32_sai.h"
 
 #define SAI_FREE_PROTOCOL	0x0
+#define SAI_SPDIF_PROTOCOL	0x1
 
 #define SAI_SLOT_SIZE_AUTO	0x0
 #define SAI_SLOT_SIZE_16	0x1
@@ -59,8 +61,13 @@
 #define SAI_SYNC_INTERNAL	0x1
 #define SAI_SYNC_EXTERNAL	0x2
 
+#define STM_SAI_PROTOCOL_IS_SPDIF(ip)	((ip)->spdif)
+#define STM_SAI_HAS_SPDIF(x)	((x)->pdata->conf->has_spdif)
 #define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4(sai->pdata))
 
+#define SAI_IEC60958_BLOCK_FRAMES	192
+#define SAI_IEC60958_STATUS_BYTES	24
+
 /**
  * struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
  * @pdev: device data pointer
@@ -78,6 +85,7 @@
  * @id: SAI sub block id corresponding to sub-block A or B
  * @dir: SAI block direction (playback or capture). set at init
  * @master: SAI block mode flag. (true=master, false=slave) set at init
+ * @spdif: SAI S/PDIF iec60958 mode flag. set at init
  * @fmt: SAI block format. relevant only for custom protocols. set at init
  * @sync: SAI block synchronization mode. (none, internal or external)
  * @synco: SAI block ext sync source (provider setting). (none, sub-block A/B)
@@ -87,6 +95,8 @@
  * @slot_width: rx or tx slot width in bits
  * @slot_mask: rx or tx active slots mask. set at init or at runtime
  * @data_size: PCM data width. corresponds to PCM substream width.
+ * @spdif_frm_cnt: S/PDIF playback frame counter
+ * @spdif_status_bits: S/PDIF status bits
  */
 struct stm32_sai_sub_data {
 	struct platform_device *pdev;
@@ -104,6 +114,7 @@ struct stm32_sai_sub_data {
 	unsigned int id;
 	int dir;
 	bool master;
+	bool spdif;
 	int fmt;
 	int sync;
 	int synco;
@@ -113,6 +124,8 @@ struct stm32_sai_sub_data {
 	int slot_width;
 	int slot_mask;
 	int data_size;
+	unsigned int spdif_frm_cnt;
+	unsigned char spdif_status_bits[SAI_IEC60958_STATUS_BYTES];
 };
 
 enum stm32_sai_fifo_th {
@@ -171,6 +184,10 @@ static bool stm32_sai_sub_writeable_reg(struct device *dev, unsigned int reg)
 	}
 }
 
+static const unsigned char default_status_bits[SAI_IEC60958_STATUS_BYTES] = {
+	0, 0, 0, IEC958_AES3_CON_FS_48000,
+};
+
 static const struct regmap_config stm32_sai_sub_regmap_config_f4 = {
 	.reg_bits = 32,
 	.reg_stride = 4,
@@ -277,6 +294,11 @@ static int stm32_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
 	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
 	int slotr, slotr_mask, slot_size;
 
+	if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+		dev_warn(cpu_dai->dev, "Slot setting relevant only for TDM\n");
+		return 0;
+	}
+
 	dev_dbg(cpu_dai->dev, "Masks tx/rx:%#x/%#x, slots:%d, width:%d\n",
 		tx_mask, rx_mask, slots, slot_width);
 
@@ -326,8 +348,17 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 
 	dev_dbg(cpu_dai->dev, "fmt %x\n", fmt);
 
-	cr1_mask = SAI_XCR1_PRTCFG_MASK;
-	cr1 = SAI_XCR1_PRTCFG_SET(SAI_FREE_PROTOCOL);
+	/* Do not generate master by default */
+	cr1 = SAI_XCR1_NODIV;
+	cr1_mask = SAI_XCR1_NODIV;
+
+	cr1_mask |= SAI_XCR1_PRTCFG_MASK;
+	if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+		cr1 |= SAI_XCR1_PRTCFG_SET(SAI_SPDIF_PROTOCOL);
+		goto conf_update;
+	}
+
+	cr1 |= SAI_XCR1_PRTCFG_SET(SAI_FREE_PROTOCOL);
 
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	/* SCK active high for all protocols */
@@ -409,10 +440,7 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 
 	cr1_mask |= SAI_XCR1_SLAVE;
 
-	/* do not generate master by default */
-	cr1 |= SAI_XCR1_NODIV;
-	cr1_mask |= SAI_XCR1_NODIV;
-
+conf_update:
 	ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1);
 	if (ret < 0) {
 		dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
@@ -478,6 +506,12 @@ static int stm32_sai_set_config(struct snd_soc_dai *cpu_dai,
 			   SAI_XCR2_FFLUSH |
 			   SAI_XCR2_FTH_SET(STM_SAI_FIFO_TH_HALF));
 
+	/* DS bits in CR1 not set for SPDIF (size forced to 24 bits).*/
+	if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+		sai->spdif_frm_cnt = 0;
+		return 0;
+	}
+
 	/* Mode, data format and channel config */
 	cr1_mask = SAI_XCR1_DS_MASK;
 	switch (params_format(params)) {
@@ -592,13 +626,14 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
 	int cr1, mask, div = 0;
 	int sai_clk_rate, mclk_ratio, den, ret;
 	int version = sai->pdata->conf->version;
+	unsigned int rate = params_rate(params);
 
 	if (!sai->mclk_rate) {
 		dev_err(cpu_dai->dev, "Mclk rate is null\n");
 		return -EINVAL;
 	}
 
-	if (!(params_rate(params) % 11025))
+	if (!(rate % 11025))
 		clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k);
 	else
 		clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k);
@@ -623,24 +658,28 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
 		 *      MCKDIV = sai_ck / (frl x ws)	(NOMCK=1)
 		 * Note: NOMCK/NODIV correspond to same bit.
 		 */
-		if (sai->mclk_rate) {
-			mclk_ratio = sai->mclk_rate / params_rate(params);
-			if (mclk_ratio != 256) {
+		if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+			div = DIV_ROUND_CLOSEST(sai_clk_rate,
+						(params_rate(params) * 128));
+		} else {
+			if (sai->mclk_rate) {
+				mclk_ratio = sai->mclk_rate / rate;
 				if (mclk_ratio == 512) {
 					mask = SAI_XCR1_OSR;
 					cr1 = SAI_XCR1_OSR;
-				} else {
+				} else if (mclk_ratio != 256) {
 					dev_err(cpu_dai->dev,
 						"Wrong mclk ratio %d\n",
 						mclk_ratio);
 					return -EINVAL;
 				}
+				div = DIV_ROUND_CLOSEST(sai_clk_rate,
+							sai->mclk_rate);
+			} else {
+				/* mclk-fs not set, master clock not active */
+				den = sai->fs_length * params_rate(params);
+				div = DIV_ROUND_CLOSEST(sai_clk_rate, den);
 			}
-			div = DIV_ROUND_CLOSEST(sai_clk_rate, sai->mclk_rate);
-		} else {
-			/* mclk-fs not set, master clock not active. NOMCK=1 */
-			den = sai->fs_length * params_rate(params);
-			div = DIV_ROUND_CLOSEST(sai_clk_rate, den);
 		}
 	}
 
@@ -670,10 +709,12 @@ static int stm32_sai_hw_params(struct snd_pcm_substream *substream,
 
 	sai->data_size = params_width(params);
 
-	ret = stm32_sai_set_slots(cpu_dai);
-	if (ret < 0)
-		return ret;
-	stm32_sai_set_frame(cpu_dai);
+	if (!STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+		ret = stm32_sai_set_slots(cpu_dai);
+		if (ret < 0)
+			return ret;
+		stm32_sai_set_frame(cpu_dai);
+	}
 
 	ret = stm32_sai_set_config(cpu_dai, substream, params);
 	if (ret)
@@ -723,6 +764,9 @@ static int stm32_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 					 (unsigned int)~SAI_XCR1_DMAEN);
 		if (ret < 0)
 			dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
+
+		if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+			sai->spdif_frm_cnt = 0;
 		break;
 	default:
 		return -EINVAL;
@@ -776,6 +820,10 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
 				     sai->synco, sai->synci);
 	}
 
+	if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+		memcpy(sai->spdif_status_bits, default_status_bits,
+		       sizeof(default_status_bits));
+
 	cr1_mask |= SAI_XCR1_SYNCEN_MASK;
 	cr1 |= SAI_XCR1_SYNCEN_SET(sai->sync);
 
@@ -792,6 +840,42 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
 	.shutdown	= stm32_sai_shutdown,
 };
 
+static int stm32_sai_pcm_process_spdif(struct snd_pcm_substream *substream,
+				       int channel, unsigned long hwoff,
+				       void *buf, unsigned long bytes)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
+	int *ptr = (int *)(runtime->dma_area + hwoff +
+			   channel * (runtime->dma_bytes / runtime->channels));
+	ssize_t cnt = bytes_to_samples(runtime, bytes);
+	unsigned int frm_cnt = sai->spdif_frm_cnt;
+	unsigned int byte;
+	unsigned int mask;
+
+	do {
+		*ptr = ((*ptr >> 8) & 0x00ffffff);
+
+		/* Set channel status bit */
+		byte = frm_cnt >> 3;
+		mask = 1 << (frm_cnt - (byte << 3));
+		if (sai->spdif_status_bits[byte] & mask)
+			*ptr |= 0x04000000;
+		ptr++;
+
+		if (!(cnt % 2))
+			frm_cnt++;
+
+		if (frm_cnt == SAI_IEC60958_BLOCK_FRAMES)
+			frm_cnt = 0;
+	} while (--cnt);
+	sai->spdif_frm_cnt = frm_cnt;
+
+	return 0;
+}
+
 static const struct snd_pcm_hardware stm32_sai_pcm_hw = {
 	.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP,
 	.buffer_bytes_max = 8 * PAGE_SIZE,
@@ -842,8 +926,14 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
 };
 
 static const struct snd_dmaengine_pcm_config stm32_sai_pcm_config = {
-	.pcm_hardware	= &stm32_sai_pcm_hw,
-	.prepare_slave_config	= snd_dmaengine_pcm_prepare_slave_config,
+	.pcm_hardware = &stm32_sai_pcm_hw,
+	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+};
+
+static const struct snd_dmaengine_pcm_config stm32_sai_pcm_config_spdif = {
+	.pcm_hardware = &stm32_sai_pcm_hw,
+	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+	.process = stm32_sai_pcm_process_spdif,
 };
 
 static const struct snd_soc_component_driver stm32_component = {
@@ -900,6 +990,18 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
 		return -EINVAL;
 	}
 
+	/* Get spdif iec60958 property */
+	sai->spdif = false;
+	if (of_get_property(np, "st,iec60958", NULL)) {
+		if (!STM_SAI_HAS_SPDIF(sai) ||
+		    sai->dir == SNDRV_PCM_STREAM_CAPTURE) {
+			dev_err(&pdev->dev, "S/PDIF IEC60958 not supported\n");
+			return -EINVAL;
+		}
+		sai->spdif = true;
+		sai->master = true;
+	}
+
 	/* Get synchronization property */
 	args.np = NULL;
 	ret = of_parse_phandle_with_fixed_args(np, "st,sync", 1, 0, &args);
@@ -999,6 +1101,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
 {
 	struct stm32_sai_sub_data *sai;
 	const struct of_device_id *of_id;
+	const struct snd_dmaengine_pcm_config *conf = &stm32_sai_pcm_config;
 	int ret;
 
 	sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
@@ -1039,8 +1142,10 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
-					      &stm32_sai_pcm_config, 0);
+	if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+		conf = &stm32_sai_pcm_config_spdif;
+
+	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register pcm dma\n");
 		return ret;
-- 
1.9.1

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

* Applied "ASoC: stm32: sai: Add support of S/PDIF playback" to the asoc tree
  2018-02-19 15:00 ` [RFC PATCH 3/3] ASoC: stm32: sai: Add support of S/PDIF playback Olivier Moysan
@ 2018-02-26 11:20   ` Mark Brown
  0 siblings, 0 replies; 6+ messages in thread
From: Mark Brown @ 2018-02-26 11:20 UTC (permalink / raw)
  To: Olivier Moysan
  Cc: olivier moysan, Mark Brown, lgirdwood, broonie, perex, tiwai,
	mcoquelin.stm32, alexandre.torgue, alsa-devel, robh,
	mark.rutland, devicetree, linux-arm-kernel, kernel, linux-kernel,
	olivier.moysan, arnaud.pouliquen, benjamin.gaignard, alsa-devel

The patch

   ASoC: stm32: sai: Add support of S/PDIF playback

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 6eb17d70932b5fbe25d9e7fc6d45d29d7a6cdf94 Mon Sep 17 00:00:00 2001
From: Olivier Moysan <olivier.moysan@st.com>
Date: Mon, 19 Feb 2018 16:00:37 +0100
Subject: [PATCH] ASoC: stm32: sai: Add support of S/PDIF playback

Add support of S/PDIF iec60958 playback on STM32 SAI.

Signed-off-by: olivier moysan <olivier.moysan@st.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/stm/stm32_sai.c     |   2 +
 sound/soc/stm/stm32_sai.h     |   2 +
 sound/soc/stm/stm32_sai_sub.c | 153 +++++++++++++++++++++++++++++++++++-------
 3 files changed, 133 insertions(+), 24 deletions(-)

diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index d743b7dd52fb..f22654253c43 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -30,10 +30,12 @@
 
 static const struct stm32_sai_conf stm32_sai_conf_f4 = {
 	.version = SAI_STM32F4,
+	.has_spdif = false,
 };
 
 static const struct stm32_sai_conf stm32_sai_conf_h7 = {
 	.version = SAI_STM32H7,
+	.has_spdif = true,
 };
 
 static const struct of_device_id stm32_sai_ids[] = {
diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h
index bb062e70de63..f25422174909 100644
--- a/sound/soc/stm/stm32_sai.h
+++ b/sound/soc/stm/stm32_sai.h
@@ -248,9 +248,11 @@ enum stm32_sai_version {
 /**
  * struct stm32_sai_conf - SAI configuration
  * @version: SAI version
+ * @has_spdif: SAI S/PDIF support flag
  */
 struct stm32_sai_conf {
 	int version;
+	bool has_spdif;
 };
 
 /**
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 08583b958430..cfeb219e1d78 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -23,6 +23,7 @@
 #include <linux/of_platform.h>
 #include <linux/regmap.h>
 
+#include <sound/asoundef.h>
 #include <sound/core.h>
 #include <sound/dmaengine_pcm.h>
 #include <sound/pcm_params.h>
@@ -30,6 +31,7 @@
 #include "stm32_sai.h"
 
 #define SAI_FREE_PROTOCOL	0x0
+#define SAI_SPDIF_PROTOCOL	0x1
 
 #define SAI_SLOT_SIZE_AUTO	0x0
 #define SAI_SLOT_SIZE_16	0x1
@@ -59,8 +61,13 @@
 #define SAI_SYNC_INTERNAL	0x1
 #define SAI_SYNC_EXTERNAL	0x2
 
+#define STM_SAI_PROTOCOL_IS_SPDIF(ip)	((ip)->spdif)
+#define STM_SAI_HAS_SPDIF(x)	((x)->pdata->conf->has_spdif)
 #define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4(sai->pdata))
 
+#define SAI_IEC60958_BLOCK_FRAMES	192
+#define SAI_IEC60958_STATUS_BYTES	24
+
 /**
  * struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
  * @pdev: device data pointer
@@ -78,6 +85,7 @@
  * @id: SAI sub block id corresponding to sub-block A or B
  * @dir: SAI block direction (playback or capture). set at init
  * @master: SAI block mode flag. (true=master, false=slave) set at init
+ * @spdif: SAI S/PDIF iec60958 mode flag. set at init
  * @fmt: SAI block format. relevant only for custom protocols. set at init
  * @sync: SAI block synchronization mode. (none, internal or external)
  * @synco: SAI block ext sync source (provider setting). (none, sub-block A/B)
@@ -87,6 +95,8 @@
  * @slot_width: rx or tx slot width in bits
  * @slot_mask: rx or tx active slots mask. set at init or at runtime
  * @data_size: PCM data width. corresponds to PCM substream width.
+ * @spdif_frm_cnt: S/PDIF playback frame counter
+ * @spdif_status_bits: S/PDIF status bits
  */
 struct stm32_sai_sub_data {
 	struct platform_device *pdev;
@@ -104,6 +114,7 @@ struct stm32_sai_sub_data {
 	unsigned int id;
 	int dir;
 	bool master;
+	bool spdif;
 	int fmt;
 	int sync;
 	int synco;
@@ -113,6 +124,8 @@ struct stm32_sai_sub_data {
 	int slot_width;
 	int slot_mask;
 	int data_size;
+	unsigned int spdif_frm_cnt;
+	unsigned char spdif_status_bits[SAI_IEC60958_STATUS_BYTES];
 };
 
 enum stm32_sai_fifo_th {
@@ -171,6 +184,10 @@ static bool stm32_sai_sub_writeable_reg(struct device *dev, unsigned int reg)
 	}
 }
 
+static const unsigned char default_status_bits[SAI_IEC60958_STATUS_BYTES] = {
+	0, 0, 0, IEC958_AES3_CON_FS_48000,
+};
+
 static const struct regmap_config stm32_sai_sub_regmap_config_f4 = {
 	.reg_bits = 32,
 	.reg_stride = 4,
@@ -277,6 +294,11 @@ static int stm32_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
 	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
 	int slotr, slotr_mask, slot_size;
 
+	if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+		dev_warn(cpu_dai->dev, "Slot setting relevant only for TDM\n");
+		return 0;
+	}
+
 	dev_dbg(cpu_dai->dev, "Masks tx/rx:%#x/%#x, slots:%d, width:%d\n",
 		tx_mask, rx_mask, slots, slot_width);
 
@@ -326,8 +348,17 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 
 	dev_dbg(cpu_dai->dev, "fmt %x\n", fmt);
 
-	cr1_mask = SAI_XCR1_PRTCFG_MASK;
-	cr1 = SAI_XCR1_PRTCFG_SET(SAI_FREE_PROTOCOL);
+	/* Do not generate master by default */
+	cr1 = SAI_XCR1_NODIV;
+	cr1_mask = SAI_XCR1_NODIV;
+
+	cr1_mask |= SAI_XCR1_PRTCFG_MASK;
+	if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+		cr1 |= SAI_XCR1_PRTCFG_SET(SAI_SPDIF_PROTOCOL);
+		goto conf_update;
+	}
+
+	cr1 |= SAI_XCR1_PRTCFG_SET(SAI_FREE_PROTOCOL);
 
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	/* SCK active high for all protocols */
@@ -409,10 +440,7 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 
 	cr1_mask |= SAI_XCR1_SLAVE;
 
-	/* do not generate master by default */
-	cr1 |= SAI_XCR1_NODIV;
-	cr1_mask |= SAI_XCR1_NODIV;
-
+conf_update:
 	ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1);
 	if (ret < 0) {
 		dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
@@ -478,6 +506,12 @@ static int stm32_sai_set_config(struct snd_soc_dai *cpu_dai,
 			   SAI_XCR2_FFLUSH |
 			   SAI_XCR2_FTH_SET(STM_SAI_FIFO_TH_HALF));
 
+	/* DS bits in CR1 not set for SPDIF (size forced to 24 bits).*/
+	if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+		sai->spdif_frm_cnt = 0;
+		return 0;
+	}
+
 	/* Mode, data format and channel config */
 	cr1_mask = SAI_XCR1_DS_MASK;
 	switch (params_format(params)) {
@@ -592,13 +626,14 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
 	int cr1, mask, div = 0;
 	int sai_clk_rate, mclk_ratio, den, ret;
 	int version = sai->pdata->conf->version;
+	unsigned int rate = params_rate(params);
 
 	if (!sai->mclk_rate) {
 		dev_err(cpu_dai->dev, "Mclk rate is null\n");
 		return -EINVAL;
 	}
 
-	if (!(params_rate(params) % 11025))
+	if (!(rate % 11025))
 		clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k);
 	else
 		clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k);
@@ -623,24 +658,28 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
 		 *      MCKDIV = sai_ck / (frl x ws)	(NOMCK=1)
 		 * Note: NOMCK/NODIV correspond to same bit.
 		 */
-		if (sai->mclk_rate) {
-			mclk_ratio = sai->mclk_rate / params_rate(params);
-			if (mclk_ratio != 256) {
+		if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+			div = DIV_ROUND_CLOSEST(sai_clk_rate,
+						(params_rate(params) * 128));
+		} else {
+			if (sai->mclk_rate) {
+				mclk_ratio = sai->mclk_rate / rate;
 				if (mclk_ratio == 512) {
 					mask = SAI_XCR1_OSR;
 					cr1 = SAI_XCR1_OSR;
-				} else {
+				} else if (mclk_ratio != 256) {
 					dev_err(cpu_dai->dev,
 						"Wrong mclk ratio %d\n",
 						mclk_ratio);
 					return -EINVAL;
 				}
+				div = DIV_ROUND_CLOSEST(sai_clk_rate,
+							sai->mclk_rate);
+			} else {
+				/* mclk-fs not set, master clock not active */
+				den = sai->fs_length * params_rate(params);
+				div = DIV_ROUND_CLOSEST(sai_clk_rate, den);
 			}
-			div = DIV_ROUND_CLOSEST(sai_clk_rate, sai->mclk_rate);
-		} else {
-			/* mclk-fs not set, master clock not active. NOMCK=1 */
-			den = sai->fs_length * params_rate(params);
-			div = DIV_ROUND_CLOSEST(sai_clk_rate, den);
 		}
 	}
 
@@ -670,10 +709,12 @@ static int stm32_sai_hw_params(struct snd_pcm_substream *substream,
 
 	sai->data_size = params_width(params);
 
-	ret = stm32_sai_set_slots(cpu_dai);
-	if (ret < 0)
-		return ret;
-	stm32_sai_set_frame(cpu_dai);
+	if (!STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+		ret = stm32_sai_set_slots(cpu_dai);
+		if (ret < 0)
+			return ret;
+		stm32_sai_set_frame(cpu_dai);
+	}
 
 	ret = stm32_sai_set_config(cpu_dai, substream, params);
 	if (ret)
@@ -723,6 +764,9 @@ static int stm32_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 					 (unsigned int)~SAI_XCR1_DMAEN);
 		if (ret < 0)
 			dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
+
+		if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+			sai->spdif_frm_cnt = 0;
 		break;
 	default:
 		return -EINVAL;
@@ -776,6 +820,10 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
 				     sai->synco, sai->synci);
 	}
 
+	if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+		memcpy(sai->spdif_status_bits, default_status_bits,
+		       sizeof(default_status_bits));
+
 	cr1_mask |= SAI_XCR1_SYNCEN_MASK;
 	cr1 |= SAI_XCR1_SYNCEN_SET(sai->sync);
 
@@ -792,6 +840,42 @@ static const struct snd_soc_dai_ops stm32_sai_pcm_dai_ops = {
 	.shutdown	= stm32_sai_shutdown,
 };
 
+static int stm32_sai_pcm_process_spdif(struct snd_pcm_substream *substream,
+				       int channel, unsigned long hwoff,
+				       void *buf, unsigned long bytes)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
+	int *ptr = (int *)(runtime->dma_area + hwoff +
+			   channel * (runtime->dma_bytes / runtime->channels));
+	ssize_t cnt = bytes_to_samples(runtime, bytes);
+	unsigned int frm_cnt = sai->spdif_frm_cnt;
+	unsigned int byte;
+	unsigned int mask;
+
+	do {
+		*ptr = ((*ptr >> 8) & 0x00ffffff);
+
+		/* Set channel status bit */
+		byte = frm_cnt >> 3;
+		mask = 1 << (frm_cnt - (byte << 3));
+		if (sai->spdif_status_bits[byte] & mask)
+			*ptr |= 0x04000000;
+		ptr++;
+
+		if (!(cnt % 2))
+			frm_cnt++;
+
+		if (frm_cnt == SAI_IEC60958_BLOCK_FRAMES)
+			frm_cnt = 0;
+	} while (--cnt);
+	sai->spdif_frm_cnt = frm_cnt;
+
+	return 0;
+}
+
 static const struct snd_pcm_hardware stm32_sai_pcm_hw = {
 	.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP,
 	.buffer_bytes_max = 8 * PAGE_SIZE,
@@ -842,8 +926,14 @@ static struct snd_soc_dai_driver stm32_sai_capture_dai[] = {
 };
 
 static const struct snd_dmaengine_pcm_config stm32_sai_pcm_config = {
-	.pcm_hardware	= &stm32_sai_pcm_hw,
-	.prepare_slave_config	= snd_dmaengine_pcm_prepare_slave_config,
+	.pcm_hardware = &stm32_sai_pcm_hw,
+	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+};
+
+static const struct snd_dmaengine_pcm_config stm32_sai_pcm_config_spdif = {
+	.pcm_hardware = &stm32_sai_pcm_hw,
+	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+	.process = stm32_sai_pcm_process_spdif,
 };
 
 static const struct snd_soc_component_driver stm32_component = {
@@ -900,6 +990,18 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
 		return -EINVAL;
 	}
 
+	/* Get spdif iec60958 property */
+	sai->spdif = false;
+	if (of_get_property(np, "st,iec60958", NULL)) {
+		if (!STM_SAI_HAS_SPDIF(sai) ||
+		    sai->dir == SNDRV_PCM_STREAM_CAPTURE) {
+			dev_err(&pdev->dev, "S/PDIF IEC60958 not supported\n");
+			return -EINVAL;
+		}
+		sai->spdif = true;
+		sai->master = true;
+	}
+
 	/* Get synchronization property */
 	args.np = NULL;
 	ret = of_parse_phandle_with_fixed_args(np, "st,sync", 1, 0, &args);
@@ -999,6 +1101,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
 {
 	struct stm32_sai_sub_data *sai;
 	const struct of_device_id *of_id;
+	const struct snd_dmaengine_pcm_config *conf = &stm32_sai_pcm_config;
 	int ret;
 
 	sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
@@ -1039,8 +1142,10 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
-					      &stm32_sai_pcm_config, 0);
+	if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+		conf = &stm32_sai_pcm_config_spdif;
+
+	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register pcm dma\n");
 		return ret;
-- 
2.16.1

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

* Applied "ASoC: stm32: Add S/PDIF to SAI bindings" to the asoc tree
  2018-02-19 15:00 ` [RFC PATCH 1/3] ASoC: stm32: Add S/PDIF to SAI bindings Olivier Moysan
@ 2018-02-26 11:20   ` Mark Brown
  0 siblings, 0 replies; 6+ messages in thread
From: Mark Brown @ 2018-02-26 11:20 UTC (permalink / raw)
  To: Olivier Moysan
  Cc: olivier moysan, Mark Brown, lgirdwood, broonie, perex, tiwai,
	mcoquelin.stm32, alexandre.torgue, alsa-devel, robh,
	mark.rutland, devicetree, linux-arm-kernel, kernel, linux-kernel,
	olivier.moysan, arnaud.pouliquen, benjamin.gaignard, alsa-devel

The patch

   ASoC: stm32: Add S/PDIF to SAI bindings

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 994f46610bafd75a5881544bce9dd3acdbe3626a Mon Sep 17 00:00:00 2001
From: Olivier Moysan <olivier.moysan@st.com>
Date: Mon, 19 Feb 2018 16:00:35 +0100
Subject: [PATCH] ASoC: stm32: Add S/PDIF to SAI bindings

Add S/PDIF IEC6958 protocol support to STM32 SAI bindings.

Signed-off-by: olivier moysan <olivier.moysan@st.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 Documentation/devicetree/bindings/sound/st,stm32-sai.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
index b1acc1a256ba..f301cdf0b7e6 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -45,6 +45,12 @@ SAI subnodes Optional properties:
 	This property sets SAI sub-block as slave of another SAI sub-block.
 	Must contain the phandle and index of the sai sub-block providing
 	the synchronization.
+  - st,iec60958: support S/PDIF IEC6958 protocol for playback
+	IEC60958 protocol is not available for capture.
+	By default, custom protocol is assumed, meaning that protocol is
+	configured according to protocol defined in related DAI link node,
+	such as i2s, left justified, right justified, dsp and pdm protocols.
+	Note: ac97 protocol is not supported by SAI driver
 
 The device node should contain one 'port' child node with one child 'endpoint'
 node, according to the bindings defined in Documentation/devicetree/bindings/
-- 
2.16.1

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

end of thread, other threads:[~2018-02-26 11:21 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-19 15:00 [RFC PATCH 0/3] ASoC: stm32: add S/PDIF support to SAI Olivier Moysan
2018-02-19 15:00 ` [RFC PATCH 1/3] ASoC: stm32: Add S/PDIF to SAI bindings Olivier Moysan
2018-02-26 11:20   ` Applied "ASoC: stm32: Add S/PDIF to SAI bindings" to the asoc tree Mark Brown
2018-02-19 15:00 ` [RFC PATCH 2/3] ASoC: dmaengine_pcm: add processing support Olivier Moysan
2018-02-19 15:00 ` [RFC PATCH 3/3] ASoC: stm32: sai: Add support of S/PDIF playback Olivier Moysan
2018-02-26 11:20   ` Applied "ASoC: stm32: sai: Add support of S/PDIF playback" to the asoc tree Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).