[PATCH v3 1/2] ASoC: stm32: add bindings for SAI

2017-04-10 Thread olivier moysan
This patch adds documentation of device tree bindings for the
STM32 SAI ASoC driver.

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

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
new file mode 100644
index 000..c59a3d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -0,0 +1,89 @@
+STMicroelectronics STM32 Serial Audio Interface (SAI).
+
+The SAI interface (Serial Audio Interface) offers a wide set of audio protocols
+as I2S standards, LSB or MSB-justified, PCM/DSP, TDM, and AC'97.
+The SAI contains two independent audio sub-blocks. Each sub-block has
+its own clock generator and I/O lines controller.
+
+Required properties:
+  - compatible: Should be "st,stm32f4-sai"
+  - reg: Base address and size of SAI common register set.
+  - clocks: Must contain phandle and clock specifier pairs for each entry
+   in clock-names.
+  - clock-names: Must contain "x8k" and "x11k"
+   "x8k": SAI parent clock for sampling rates multiple of 8kHz.
+   "x11k": SAI parent clock for sampling rates multiple of 11.025kHz.
+  - interrupts: cpu DAI interrupt line shared by SAI sub-blocks
+
+Optional properties:
+  - resets: Reference to a reset controller asserting the SAI
+
+SAI subnodes:
+Two subnodes corresponding to SAI sub-block instances A et B can be defined.
+Subnode can be omitted for unsused sub-block.
+
+SAI subnodes required properties:
+  - compatible: Should be "st,stm32-sai-sub-a" or "st,stm32-sai-sub-b"
+   for SAI sub-block A or B respectively.
+  - reg: Base address and size of SAI sub-block register set.
+  - clocks: Must contain one phandle and clock specifier pair
+   for sai_ck which feeds the internal clock generator.
+  - clock-names: Must contain "sai_ck".
+  - dmas: see Documentation/devicetree/bindings/dma/stm32-dma.txt
+  - dma-names: identifier string for each DMA request line
+   "tx": if sai sub-block is configured as playback DAI
+   "rx": if sai sub-block is configured as capture DAI
+  - pinctrl-names: should contain only value "default"
+  - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
+
+Example:
+sound_card {
+   compatible = "audio-graph-card";
+   dais = <_port>;
+};
+
+sai1: sai1@40015800 {
+   compatible = "st,stm32f4-sai";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+   reg = <0x40015800 0x4>;
+   clocks = < 1 CLK_SAIQ_PDIV>, < 1 CLK_I2SQ_PDIV>;
+   clock-names = "x8k", "x11k";
+   interrupts = <87>;
+
+   sai1b: audio-controller@40015824 {
+   #sound-dai-cells = <0>;
+   compatible = "st,stm32-sai-sub-b";
+   reg = <0x40015824 0x1C>;
+   clocks = < 1 CLK_SAI2>;
+   clock-names = "sai_ck";
+   dmas = < 5 0 0x400 0x0>;
+   dma-names = "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_sai1b>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   sai1b_port: port@0 {
+   reg = <0>;
+   cpu_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   audio-graph-card,format = "i2s";
+   audio-graph-card,bitclock-master = 
<_endpoint>;
+   audio-graph-card,frame-master = 
<_endpoint>;
+   };
+   };
+   };
+   };
+};
+
+audio-codec {
+   codec_port: port {
+   codec_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   };
+   };
+};
-- 
1.9.1



[PATCH v3 2/2] ASoC: stm32: add SAI driver

2017-04-10 Thread olivier moysan
This patch implements SAI ASoC driver for STM32.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/Kconfig |   1 +
 sound/soc/Makefile|   1 +
 sound/soc/stm/Kconfig |   8 +
 sound/soc/stm/Makefile|   6 +
 sound/soc/stm/stm32_sai.c | 115 ++
 sound/soc/stm/stm32_sai.h | 200 ++
 sound/soc/stm/stm32_sai_sub.c | 884 ++
 7 files changed, 1215 insertions(+)
 create mode 100644 sound/soc/stm/Kconfig
 create mode 100644 sound/soc/stm/Makefile
 create mode 100644 sound/soc/stm/stm32_sai.c
 create mode 100644 sound/soc/stm/stm32_sai.h
 create mode 100644 sound/soc/stm/stm32_sai_sub.c

diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 182d92e..3836ebe 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -63,6 +63,7 @@ source "sound/soc/sh/Kconfig"
 source "sound/soc/sirf/Kconfig"
 source "sound/soc/spear/Kconfig"
 source "sound/soc/sti/Kconfig"
+source "sound/soc/stm/Kconfig"
 source "sound/soc/sunxi/Kconfig"
 source "sound/soc/tegra/Kconfig"
 source "sound/soc/txx9/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 9a30f21..5440cf7 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_SND_SOC) += sh/
 obj-$(CONFIG_SND_SOC)  += sirf/
 obj-$(CONFIG_SND_SOC)  += spear/
 obj-$(CONFIG_SND_SOC)  += sti/
+obj-$(CONFIG_SND_SOC)  += stm/
 obj-$(CONFIG_SND_SOC)  += sunxi/
 obj-$(CONFIG_SND_SOC)  += tegra/
 obj-$(CONFIG_SND_SOC)  += txx9/
diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
new file mode 100644
index 000..972970f
--- /dev/null
+++ b/sound/soc/stm/Kconfig
@@ -0,0 +1,8 @@
+menuconfig SND_SOC_STM32
+   tristate "STMicroelectronics STM32 SOC audio support"
+   depends on ARCH_STM32 || COMPILE_TEST
+   depends on SND_SOC
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   help
+ Say Y if you want to enable ASoC-support for STM32
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
new file mode 100644
index 000..e466a47
--- /dev/null
+++ b/sound/soc/stm/Makefile
@@ -0,0 +1,6 @@
+# SAI
+snd-soc-stm32-sai-sub-objs := stm32_sai_sub.o
+obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o
+
+snd-soc-stm32-sai-objs := stm32_sai.o
+obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
new file mode 100644
index 000..2a27a26
--- /dev/null
+++ b/sound/soc/stm/stm32_sai.c
@@ -0,0 +1,115 @@
+/*
+ * STM32 ALSA SoC Digital Audio Interface (SAI) driver.
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author(s): Olivier Moysan <olivier.moy...@st.com> for STMicroelectronics.
+ *
+ * License terms: GPL V2.0.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
more
+ * details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "stm32_sai.h"
+
+static const struct of_device_id stm32_sai_ids[] = {
+   { .compatible = "st,stm32f4-sai", .data = (void *)SAI_STM32F4 },
+   {}
+};
+
+static int stm32_sai_probe(struct platform_device *pdev)
+{
+   struct device_node *np = pdev->dev.of_node;
+   struct stm32_sai_data *sai;
+   struct reset_control *rst;
+   struct resource *res;
+   void __iomem *base;
+   const struct of_device_id *of_id;
+
+   sai = devm_kzalloc(>dev, sizeof(*sai), GFP_KERNEL);
+   if (!sai)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   of_id = of_match_device(stm32_sai_ids, >dev);
+   if (of_id)
+   sai->version = (enum stm32_sai_version)of_id->data;
+   else
+   return -EINVAL;
+
+   sai->clk_x8k = devm_clk_get(>dev, "x8k");
+   if (IS_ERR(sai->clk_x8k)) {
+   dev_err(>dev, "missing x8k parent clock\n");
+   return PTR_ERR(sai->clk_x8k);
+   }
+
+   sai->clk_x11k = devm_clk_get(>dev, "x11k");
+   if (IS_ERR(sai->clk_x11k)) {
+   dev_err(>dev, "missing x11k parent clock\n");
+   return PTR_ERR(sai->clk_x11k);
+   }
+
+   /* init irqs */
+   sai->irq = platform_get_irq(pdev, 0);
+   if (sai->irq < 0) {
+   dev_er

[PATCH v3 0/2] Add STM32 SAI support

2017-04-10 Thread olivier moysan
This patch-set handles the Serial Audio Interface (SAI) IP on STM32 platforms.

The SAI IP is composed of two Sub-block A and B. (see the figure below)
Each sub-block makes use of individual and shared resources.

Shared resources:
- Reset line. Reset common and sub-block registers.
- Bus interface clocks. This clock is not exposed in device
as it it managed by clock driver, according to kernel clocks gating.
- Common register. SAI IP exhibits a common configuration register
to manage synchronization modes. NB: These modes are not yet implemented
in this version of the SAI driver.
- Interrupt. Sub-blocks have their own interrupt status registers but 
they 
share the same interrupt line.

Individual resources:
- Register set
- DMA request line.
- Communication interface. 
Each sub-block has its own GPIOs and associated bus lines.
- Kernel clock. 
Each sub-block has its own dedicated clock for its communication 
interface.

To reflect this architecture Sub-block A and B are handled by 2 child devices.
Sub-block A and B devices can be configured independently either as transmitter
or receiver. A PCM device is associated to each sub-block.

A sub-block has to select the appropriated parent clock at runtime, 
depending on the audio stream sampling rate to be played or captured.
Two parent clocks must be provided to support sampling rates multiples
of 8 kHz or 11.025kHz.

 Interface clock  ++
+---> | SAI IP |
 Reset| +-+|
+---> | |common registers ||
  | +-+|
  ||
  |+--+|
  || Sub-block A  ||
 Kernel clock A   ||  || Bus A
+> | ++   +>
  || |A registers |   ||
  || ++   ||
  |+--+|
  ||
  |+--+|
  || Sub-block B  ||
 Kernel clock B   ||  || Bus B
+> | ++   +->
  || |B registers |   ||
  || ++   ||
  |+--+|
  ||
  ++

v3: correct DT bindings
- remove aliases
- use audio graph card

olivier moysan (2):
  ASoC: stm32: add bindings for SAI
  ASoC: stm32: add SAI driver

 .../devicetree/bindings/sound/st,stm32-sai.txt |  89 +++
 sound/soc/Kconfig  |   1 +
 sound/soc/Makefile |   1 +
 sound/soc/stm/Kconfig  |   8 +
 sound/soc/stm/Makefile |   6 +
 sound/soc/stm/stm32_sai.c  | 115 +++
 sound/soc/stm/stm32_sai.h  | 200 +
 sound/soc/stm/stm32_sai_sub.c  | 884 +
 8 files changed, 1304 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-sai.txt
 create mode 100644 sound/soc/stm/Kconfig
 create mode 100644 sound/soc/stm/Makefile
 create mode 100644 sound/soc/stm/stm32_sai.c
 create mode 100644 sound/soc/stm/stm32_sai.h
 create mode 100644 sound/soc/stm/stm32_sai_sub.c

-- 
1.9.1



[PATCH v4 2/2] ASoC: stm32: add SAI driver

2017-04-11 Thread olivier moysan
This patch implements SAI ASoC driver for STM32.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/Kconfig |   1 +
 sound/soc/Makefile|   1 +
 sound/soc/stm/Kconfig |   8 +
 sound/soc/stm/Makefile|   6 +
 sound/soc/stm/stm32_sai.c | 115 ++
 sound/soc/stm/stm32_sai.h | 199 ++
 sound/soc/stm/stm32_sai_sub.c | 881 ++
 7 files changed, 1211 insertions(+)
 create mode 100644 sound/soc/stm/Kconfig
 create mode 100644 sound/soc/stm/Makefile
 create mode 100644 sound/soc/stm/stm32_sai.c
 create mode 100644 sound/soc/stm/stm32_sai.h
 create mode 100644 sound/soc/stm/stm32_sai_sub.c

diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 9df9658..c0abad2 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -64,6 +64,7 @@ source "sound/soc/sh/Kconfig"
 source "sound/soc/sirf/Kconfig"
 source "sound/soc/spear/Kconfig"
 source "sound/soc/sti/Kconfig"
+source "sound/soc/stm/Kconfig"
 source "sound/soc/sunxi/Kconfig"
 source "sound/soc/tegra/Kconfig"
 source "sound/soc/txx9/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 2f6aabb..39c27a5 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SND_SOC) += sh/
 obj-$(CONFIG_SND_SOC)  += sirf/
 obj-$(CONFIG_SND_SOC)  += spear/
 obj-$(CONFIG_SND_SOC)  += sti/
+obj-$(CONFIG_SND_SOC)  += stm/
 obj-$(CONFIG_SND_SOC)  += sunxi/
 obj-$(CONFIG_SND_SOC)  += tegra/
 obj-$(CONFIG_SND_SOC)  += txx9/
diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
new file mode 100644
index 000..a6372de
--- /dev/null
+++ b/sound/soc/stm/Kconfig
@@ -0,0 +1,8 @@
+menuconfig SND_SOC_STM32
+   tristate "STMicroelectronics STM32 SOC audio support"
+   depends on ARCH_STM32 || COMPILE_TEST
+   depends on SND_SOC
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   help
+ Say Y if you want to enable ASoC support for STM32
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
new file mode 100644
index 000..e466a47
--- /dev/null
+++ b/sound/soc/stm/Makefile
@@ -0,0 +1,6 @@
+# SAI
+snd-soc-stm32-sai-sub-objs := stm32_sai_sub.o
+obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o
+
+snd-soc-stm32-sai-objs := stm32_sai.o
+obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
new file mode 100644
index 000..6159d66
--- /dev/null
+++ b/sound/soc/stm/stm32_sai.c
@@ -0,0 +1,115 @@
+/*
+ * STM32 ALSA SoC Digital Audio Interface (SAI) driver.
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author(s): Olivier Moysan <olivier.moy...@st.com> for STMicroelectronics.
+ *
+ * License terms: GPL V2.0.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
more
+ * details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "stm32_sai.h"
+
+static const struct of_device_id stm32_sai_ids[] = {
+   { .compatible = "st,stm32f4-sai", .data = (void *)SAI_STM32F4 },
+   {}
+};
+
+static int stm32_sai_probe(struct platform_device *pdev)
+{
+   struct device_node *np = pdev->dev.of_node;
+   struct stm32_sai_data *sai;
+   struct reset_control *rst;
+   struct resource *res;
+   void __iomem *base;
+   const struct of_device_id *of_id;
+
+   sai = devm_kzalloc(>dev, sizeof(*sai), GFP_KERNEL);
+   if (!sai)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   of_id = of_match_device(stm32_sai_ids, >dev);
+   if (of_id)
+   sai->version = (enum stm32_sai_version)of_id->data;
+   else
+   return -EINVAL;
+
+   sai->clk_x8k = devm_clk_get(>dev, "x8k");
+   if (IS_ERR(sai->clk_x8k)) {
+   dev_err(>dev, "missing x8k parent clock\n");
+   return PTR_ERR(sai->clk_x8k);
+   }
+
+   sai->clk_x11k = devm_clk_get(>dev, "x11k");
+   if (IS_ERR(sai->clk_x11k)) {
+   dev_err(>dev, "missing x11k parent clock\n");
+   return PTR_ERR(sai->clk_x11k);
+   }
+
+   /* init irqs */
+   sai->irq = platform_get_irq(pdev, 0);
+   if (sai->irq < 0) {
+   dev_er

[PATCH v4 1/2] ASoC: stm32: add bindings for SAI

2017-04-11 Thread olivier moysan
This patch adds documentation of device tree bindings for the
STM32 SAI ASoC driver.

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

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
new file mode 100644
index 000..c59a3d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -0,0 +1,89 @@
+STMicroelectronics STM32 Serial Audio Interface (SAI).
+
+The SAI interface (Serial Audio Interface) offers a wide set of audio protocols
+as I2S standards, LSB or MSB-justified, PCM/DSP, TDM, and AC'97.
+The SAI contains two independent audio sub-blocks. Each sub-block has
+its own clock generator and I/O lines controller.
+
+Required properties:
+  - compatible: Should be "st,stm32f4-sai"
+  - reg: Base address and size of SAI common register set.
+  - clocks: Must contain phandle and clock specifier pairs for each entry
+   in clock-names.
+  - clock-names: Must contain "x8k" and "x11k"
+   "x8k": SAI parent clock for sampling rates multiple of 8kHz.
+   "x11k": SAI parent clock for sampling rates multiple of 11.025kHz.
+  - interrupts: cpu DAI interrupt line shared by SAI sub-blocks
+
+Optional properties:
+  - resets: Reference to a reset controller asserting the SAI
+
+SAI subnodes:
+Two subnodes corresponding to SAI sub-block instances A et B can be defined.
+Subnode can be omitted for unsused sub-block.
+
+SAI subnodes required properties:
+  - compatible: Should be "st,stm32-sai-sub-a" or "st,stm32-sai-sub-b"
+   for SAI sub-block A or B respectively.
+  - reg: Base address and size of SAI sub-block register set.
+  - clocks: Must contain one phandle and clock specifier pair
+   for sai_ck which feeds the internal clock generator.
+  - clock-names: Must contain "sai_ck".
+  - dmas: see Documentation/devicetree/bindings/dma/stm32-dma.txt
+  - dma-names: identifier string for each DMA request line
+   "tx": if sai sub-block is configured as playback DAI
+   "rx": if sai sub-block is configured as capture DAI
+  - pinctrl-names: should contain only value "default"
+  - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
+
+Example:
+sound_card {
+   compatible = "audio-graph-card";
+   dais = <_port>;
+};
+
+sai1: sai1@40015800 {
+   compatible = "st,stm32f4-sai";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+   reg = <0x40015800 0x4>;
+   clocks = < 1 CLK_SAIQ_PDIV>, < 1 CLK_I2SQ_PDIV>;
+   clock-names = "x8k", "x11k";
+   interrupts = <87>;
+
+   sai1b: audio-controller@40015824 {
+   #sound-dai-cells = <0>;
+   compatible = "st,stm32-sai-sub-b";
+   reg = <0x40015824 0x1C>;
+   clocks = < 1 CLK_SAI2>;
+   clock-names = "sai_ck";
+   dmas = < 5 0 0x400 0x0>;
+   dma-names = "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_sai1b>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   sai1b_port: port@0 {
+   reg = <0>;
+   cpu_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   audio-graph-card,format = "i2s";
+   audio-graph-card,bitclock-master = 
<_endpoint>;
+   audio-graph-card,frame-master = 
<_endpoint>;
+   };
+   };
+   };
+   };
+};
+
+audio-codec {
+   codec_port: port {
+   codec_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   };
+   };
+};
-- 
1.9.1



[PATCH v4 0/2] Add STM32 SAI support

2017-04-11 Thread olivier moysan
This patch-set handles the Serial Audio Interface (SAI) IP on STM32 platforms.

The SAI IP is composed of two Sub-block A and B. (see the figure below)
Each sub-block makes use of individual and shared resources.

Shared resources:
- Reset line. Reset common and sub-block registers.
- Bus interface clocks. This clock is not exposed in device
as it it managed by clock driver, according to kernel clocks gating.
- Common register. SAI IP exhibits a common configuration register
to manage synchronization modes. NB: These modes are not yet implemented
in this version of the SAI driver.
- Interrupt. Sub-blocks have their own interrupt status registers but 
they 
share the same interrupt line.

Individual resources:
- Register set
- DMA request line.
- Communication interface. 
Each sub-block has its own GPIOs and associated bus lines.
- Kernel clock. 
Each sub-block has its own dedicated clock for its communication 
interface.

To reflect this architecture Sub-block A and B are handled by 2 child devices.
Sub-block A and B devices can be configured independently either as transmitter
or receiver. A PCM device is associated to each sub-block.

A sub-block has to select the appropriated parent clock at runtime, 
depending on the audio stream sampling rate to be played or captured.
Two parent clocks must be provided to support sampling rates multiples
of 8 kHz or 11.025kHz.

 Interface clock  ++
+---> | SAI IP |
 Reset| +-+|
+---> | |common registers ||
  | +-+|
  ||
  |+--+|
  || Sub-block A  ||
 Kernel clock A   ||  || Bus A
+> | ++   +>
  || |A registers |   ||
  || ++   ||
  |+--+|
  ||
  |+--+|
  || Sub-block B  ||
 Kernel clock B   ||  || Bus B
+> | ++   +->
  || |B registers |   ||
  || ++   ||
  |+--+|
  ||
  ++

v3 -> v4
Apply minor changes from Peter review

olivier moysan (2):
  ASoC: stm32: add bindings for SAI
  ASoC: stm32: add SAI driver

 .../devicetree/bindings/sound/st,stm32-sai.txt |  89 +++
 sound/soc/Kconfig  |   1 +
 sound/soc/Makefile |   1 +
 sound/soc/stm/Kconfig  |   8 +
 sound/soc/stm/Makefile |   6 +
 sound/soc/stm/stm32_sai.c  | 115 +++
 sound/soc/stm/stm32_sai.h  | 199 +
 sound/soc/stm/stm32_sai_sub.c  | 881 +
 8 files changed, 1300 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-sai.txt
 create mode 100644 sound/soc/stm/Kconfig
 create mode 100644 sound/soc/stm/Makefile
 create mode 100644 sound/soc/stm/stm32_sai.c
 create mode 100644 sound/soc/stm/stm32_sai.h
 create mode 100644 sound/soc/stm/stm32_sai_sub.c

-- 
1.9.1



[PATCH v3 2/3] ASoC: stm32: Add I2S driver

2017-05-11 Thread olivier moysan
Add I2S ASoC driver for STM32.
This version of the driver supports only
exclusive playback and capture interface.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/Kconfig |   2 +-
 sound/soc/stm/Makefile|   4 +
 sound/soc/stm/stm32_i2s.c | 941 ++
 3 files changed, 946 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/stm/stm32_i2s.c

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 972970f..a6372de 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -5,4 +5,4 @@ menuconfig SND_SOC_STM32
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
help
- Say Y if you want to enable ASoC-support for STM32
+ Say Y if you want to enable ASoC support for STM32
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
index e466a47..8251931 100644
--- a/sound/soc/stm/Makefile
+++ b/sound/soc/stm/Makefile
@@ -4,3 +4,7 @@ obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o
 
 snd-soc-stm32-sai-objs := stm32_sai.o
 obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o
+
+# I2S
+snd-soc-stm32-i2s-objs := stm32_i2s.o
+obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-i2s.o
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
new file mode 100644
index 000..22152a1
--- /dev/null
+++ b/sound/soc/stm/stm32_i2s.c
@@ -0,0 +1,941 @@
+/*
+ *  STM32 ALSA SoC Digital Audio Interface (I2S) driver.
+ *
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Olivier Moysan <olivier.moy...@st.com> for STMicroelectronics.
+ *
+ * License terms: GPL V2.0.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
more
+ * details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define STM32_I2S_CR1_REG  0x0
+#define STM32_I2S_CFG1_REG 0x08
+#define STM32_I2S_CFG2_REG 0x0C
+#define STM32_I2S_IER_REG  0x10
+#define STM32_I2S_SR_REG   0x14
+#define STM32_I2S_IFCR_REG 0x18
+#define STM32_I2S_TXDR_REG 0X20
+#define STM32_I2S_RXDR_REG 0x30
+#define STM32_I2S_CGFR_REG 0X50
+
+/* Bit definition for SPI2S_CR1 register */
+#define I2S_CR1_SPEBIT(0)
+#define I2S_CR1_CSTART BIT(9)
+#define I2S_CR1_CSUSP  BIT(10)
+#define I2S_CR1_HDDIR  BIT(11)
+#define I2S_CR1_SSIBIT(12)
+#define I2S_CR1_CRC33_17   BIT(13)
+#define I2S_CR1_RCRCI  BIT(14)
+#define I2S_CR1_TCRCI  BIT(15)
+
+/* Bit definition for SPI_CFG2 register */
+#define I2S_CFG2_IOSWP_SHIFT   15
+#define I2S_CFG2_IOSWP BIT(I2S_CFG2_IOSWP_SHIFT)
+#define I2S_CFG2_LSBFRST   BIT(23)
+#define I2S_CFG2_AFCNTRBIT(31)
+
+/* Bit definition for SPI_CFG1 register */
+#define I2S_CFG1_FTHVL_SHIFT   5
+#define I2S_CFG1_FTHVL_MASKGENMASK(8, I2S_CFG1_FTHVL_SHIFT)
+#define I2S_CFG1_FTHVL_SET(x)  ((x) << I2S_CFG1_FTHVL_SHIFT)
+
+#define I2S_CFG1_TXDMAEN   BIT(15)
+#define I2S_CFG1_RXDMAEN   BIT(14)
+
+/* Bit definition for SPI2S_IER register */
+#define I2S_IER_RXPIE  BIT(0)
+#define I2S_IER_TXPIE  BIT(1)
+#define I2S_IER_DPXPIE BIT(2)
+#define I2S_IER_EOTIE  BIT(3)
+#define I2S_IER_TXTFIE BIT(4)
+#define I2S_IER_UDRIE  BIT(5)
+#define I2S_IER_OVRIE  BIT(6)
+#define I2S_IER_CRCEIE BIT(7)
+#define I2S_IER_TIFREIEBIT(8)
+#define I2S_IER_MODFIE BIT(9)
+#define I2S_IER_TSERFIEBIT(10)
+
+/* Bit definition for SPI2S_SR register */
+#define I2S_SR_RXP BIT(0)
+#define I2S_SR_TXP BIT(1)
+#define I2S_SR_DPXPBIT(2)
+#define I2S_SR_EOT BIT(3)
+#define I2S_SR_TXTFBIT(4)
+#define I2S_SR_UDR BIT(5)
+#define I2S_SR_OVR BIT(6)
+#define I2S_SR_CRCERR  BIT(7)
+#define I2S_SR_TIFRE   BIT(8)
+#define I2S_SR_MODFBIT(9)
+#define I2S_SR_TSERF   BIT(10)
+#define I2S_SR_SUSPBIT(11)
+#define I2S_SR_TXC BIT(12)
+#define I2S_SR_RXPLVL  GENMASK(14, 13)
+#define I2S_SR_RXWNE   BIT(15)
+
+#define I2S_SR_MASKGENMASK(15, 0)
+
+/* Bit definition for SPI_IFCR register */
+#define I2S_IFCR_EOTC  BIT(3)
+#define I2S_IFCR_TXTFC BIT(4)
+#define I2S_IFCR_UDRC  BIT(5)
+#define I2S_IFCR_OVRC  BIT(6)
+#define I2S_IFCR_CRCEC BIT(7)
+#define I2S_IFCR_TIFRECBIT(8)
+#define I2S_IFCR_MODFC BIT(9)
+#define I2S_IFCR_TSERFC  

[PATCH v3 0/3] Add I2S driver

2017-05-11 Thread olivier moysan
This patch-set handles the SPI/I2S IP on STM32 platforms.

It applies to STM32 platforms implementing version 2 of SPI/I2S IP like STM32H7 
series.

The SPI/I2S block is a serial peripheral interface (SPI), which can also be 
configured to work on I2S/PCM mode.
ASoC STM32 I2S driver only supports this I2S/PCM mode.

The I2S/PCM interface can either support full duplex or half-duplex 
communication
(transmitter or receiver only). The change of mode requires to stop the 
interface.
This means that the two audio paths cannot be basically managed independently.

The driver supports playback and capture through a single bidirectionnal DAI. 
In the first version of the driver, playback and capture paths are made 
mutually exclusive.

A second patch introduces support of full duplex mode. 
In this implementation the interface is systematically configured in 
full-duplex mode
from hardware point of view. So, when managing a single audio path, the 
interface
is not configured as transmit or receive only, as it should be.
This restriction is handled by masking underrun/overrun errors from the unused 
path.

The I2S/PCM interface supports four audio standards:
I2S Philips standard, MSB justified standard, LSB justified standard, PCM 
standard
PCM standard is declined in two versions, PCM short and long,
according frame synchronization duration.

These standards can be mapped to ASoC standards as follows:
- I2S: i2s
- MSB justified standard: left_j
- LSB justified standard: right_j
- PCM short: dsp_a
PCM long format is not exposed as it does not match supported ASoC standards.

v2 -> v3
- fix spinlock handling

olivier moysan (3):
  dt-bindings: Document STM32 I2S bindings
  ASoC: stm32: Add I2S driver
  ASoC: stm32: Add full duplex support to i2s

 .../devicetree/bindings/sound/st,stm32-i2s.txt |  68 ++
 sound/soc/stm/Kconfig  |   2 +-
 sound/soc/stm/Makefile |   4 +
 sound/soc/stm/stm32_i2s.c  | 946 +
 4 files changed, 1019 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
 create mode 100644 sound/soc/stm/stm32_i2s.c

-- 
1.9.1



[PATCH v3 3/3] ASoC: stm32: Add full duplex support to i2s

2017-05-11 Thread olivier moysan
This patch allows to use i2s interface either as single
audio path (rx or tx), or bidirectional audio path.
This patch is added separately, as the driver does not
follow recommended use of the interface, to support this
configuration.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_i2s.c | 87 +--
 1 file changed, 46 insertions(+), 41 deletions(-)

diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 22152a1..8052629 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -489,7 +489,6 @@ static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai,
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
int format = params_width(params);
u32 cfgr, cfgr_mask, cfg1, cfg1_mask;
-   bool playback_flg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
unsigned int fthlv;
int ret;
 
@@ -515,19 +514,13 @@ static int stm32_i2s_configure(struct snd_soc_dai 
*cpu_dai,
}
 
if (STM32_I2S_IS_SLAVE(i2s)) {
-   if (playback_flg)
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_TX_SLAVE);
-   else
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_RX_SLAVE);
+   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_SLAVE);
 
/* As data length is either 16 or 32 bits, fixch always set */
cfgr |= I2S_CGFR_FIXCH;
cfgr_mask |= I2S_CGFR_FIXCH;
} else {
-   if (playback_flg)
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_TX_MASTER);
-   else
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_RX_MASTER);
+   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_MASTER);
}
cfgr_mask |= I2S_CGFR_I2SCFG_MASK;
 
@@ -536,9 +529,7 @@ static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai,
if (ret < 0)
return ret;
 
-   cfg1 = I2S_CFG1_RXDMAEN;
-   if (playback_flg)
-   cfg1 = I2S_CFG1_TXDMAEN;
+   cfg1 = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN;
cfg1_mask = cfg1;
 
fthlv = STM32_I2S_FIFO_SIZE * I2S_FIFO_TH_ONE_QUARTER / 4;
@@ -553,32 +544,15 @@ static int stm32_i2s_startup(struct snd_pcm_substream 
*substream,
 struct snd_soc_dai *cpu_dai)
 {
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
-   int ret, ier;
 
i2s->substream = substream;
 
spin_lock(>lock_fd);
-   if (i2s->refcount) {
-   dev_err(cpu_dai->dev, "%s stream already started\n",
-   (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-   "Capture" : "Playback"));
-   spin_unlock(>lock_fd);
-   return -EBUSY;
-   }
-   i2s->refcount = 1;
+   i2s->refcount++;
spin_unlock(>lock_fd);
 
-   ret = regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
-I2S_IFCR_MASK, I2S_IFCR_MASK);
-   if (ret < 0)
-   return ret;
-
-   /* Enable ITs */
-   ier = I2S_IER_OVRIE | I2S_IER_UDRIE;
-   if (STM32_I2S_IS_SLAVE(i2s))
-   ier |= I2S_IER_TIFREIE;
-
-   return regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, ier, ier);
+   return regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
+ I2S_IFCR_MASK, I2S_IFCR_MASK);
 }
 
 static int stm32_i2s_hw_params(struct snd_pcm_substream *substream,
@@ -605,7 +579,7 @@ static int stm32_i2s_trigger(struct snd_pcm_substream 
*substream, int cmd,
 {
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
bool playback_flg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
-   u32 cfg1_mask;
+   u32 cfg1_mask, ier;
int ret;
 
switch (cmd) {
@@ -628,10 +602,48 @@ static int stm32_i2s_trigger(struct snd_pcm_substream 
*substream, int cmd,
dev_err(cpu_dai->dev, "Error %d starting I2S\n", ret);
return ret;
}
+
+   regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
+  I2S_IFCR_MASK, I2S_IFCR_MASK);
+
+   if (playback_flg) {
+   ier = I2S_IER_UDRIE;
+   } else {
+   ier = I2S_IER_OVRIE;
+
+   spin_lock(>lock_fd);
+   if (i2s->refcount == 1)
+   /* dummy write to trigger capture */
+   regmap_write(i2s->regmap,
+STM32_I2S_TXDR_REG, 0);
+   spin_unlock(>lock_fd);
+   }
+
+   if (STM32_I2S_IS_SLAVE(i2s))
+   ier |= I2S_IER_TIFREIE;
+
+

[PATCH v3 1/3] dt-bindings: Document STM32 I2S bindings

2017-05-11 Thread olivier moysan
Add documentation of device tree bindings for STM32 SPI/I2S.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 .../devicetree/bindings/sound/st,stm32-i2s.txt | 68 ++
 1 file changed, 68 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.txt

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
new file mode 100644
index 000..67b854a
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
@@ -0,0 +1,68 @@
+STMicroelectronics STM32 SPI/I2S Controller
+
+The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode.
+Only some SPI instances support I2S.
+
+Required properties:
+  - compatible: Must be "st,stm32h7-i2s"
+  - reg: Offset and length of the device's register set.
+  - interrupts: Must contain the interrupt line id.
+  - clocks: Must contain phandle and clock specifier pairs for each entry
+   in clock-names.
+  - clock-names: Must contain "i2sclk", "pclk", "x8k" and "x11k".
+   "i2sclk": clock which feeds the internal clock generator
+   "pclk": clock which feeds the peripheral bus interface
+   "x8k": I2S parent clock for sampling rates multiple of 8kHz.
+   "x11k": I2S parent clock for sampling rates multiple of 11.025kHz.
+  - dmas: DMA specifiers for tx and rx dma.
+See Documentation/devicetree/bindings/dma/stm32-dma.txt.
+  - dma-names: Identifier for each DMA request line. Must be "tx" and "rx".
+  - pinctrl-names: should contain only value "default"
+  - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
+
+Optional properties:
+  - resets: Reference to a reset controller asserting the reset controller
+
+The device node should contain one 'port' child node with one child 'endpoint'
+node, according to the bindings defined in Documentation/devicetree/bindings/
+graph.txt.
+
+Example:
+sound_card {
+   compatible = "audio-graph-card";
+   dais = <_port 0>;
+};
+
+i2s2: audio-controller@40003800 {
+   compatible = "st,stm32h7-i2s";
+   #sound-dai-cells = <0>;
+   reg = <0x40003800 0x400>;
+   interrupts = <36>;
+   clocks = < PCLK1>, < SPI2_CK>, < PLL1_Q>, < PLL2_P>;
+   clock-names = "pclk", "i2sclk",  "x8k", "x11k";
+   dmas = < 2 39 0x400 0x1>,
+   < 3 40 0x400 0x1>;
+   dma-names = "rx", "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_i2s2>;
+
+   i2s2_port: port@0 {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   cpu_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   format = "i2s";
+   bitclock-master = <_endpoint>;
+   frame-master = <_endpoint>;
+   };
+   };
+};
+
+audio-codec {
+   codec_port: port@0 {
+   codec_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   };
+   };
+};
-- 
1.9.1



[PATCH v2 0/3] Add I2S driver

2017-05-10 Thread olivier moysan
This patch-set handles the SPI/I2S IP on STM32 platforms.

It applies to STM32 platforms implementing version 2 of SPI/I2S IP like STM32H7 
series.

The SPI/I2S block is a serial peripheral interface (SPI), which can also be 
configured to work on I2S/PCM mode.
ASoC STM32 I2S driver only supports this I2S/PCM mode.

The I2S/PCM interface can either support full duplex or half-duplex 
communication
(transmitter or receiver only). The change of mode requires to stop the 
interface.
This means that the two audio paths cannot be basically managed independently.

The driver supports playback and capture through a single bidirectionnal DAI. 
In the first version of the driver, playback and capture paths are made 
mutually exclusive.

A second patch introduces support of full duplex mode. 
In this implementation the interface is systematically configured in 
full-duplex mode
from hardware point of view. So, when managing a single audio path, the 
interface
is not configured as transmit or receive only, as it should be.
This restriction is handled by masking underrun/overrun errors from the unused 
path.

The I2S/PCM interface supports four audio standards:
I2S Philips standard, MSB justified standard, LSB justified standard, PCM 
standard
PCM standard is declined in two versions, PCM short and long,
according frame synchronization duration.

These standards can be mapped to ASoC standards as follows:
- I2S: i2s
- MSB justified standard: left_j
- LSB justified standard: right_j
- PCM short: dsp_a
PCM long format is not exposed as it does not match supported ASoC standards.

olivier moysan (3):
  dt-bindings: Document STM32 I2S bindings
  ASoC: stm32: Add I2S driver
  ASoC: stm32: Add full duplex support to i2s

 .../devicetree/bindings/sound/st,stm32-i2s.txt |  68 ++
 sound/soc/stm/Kconfig  |   2 +-
 sound/soc/stm/Makefile |   4 +
 sound/soc/stm/stm32_i2s.c  | 947 +
 4 files changed, 1020 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
 create mode 100644 sound/soc/stm/stm32_i2s.c

-- 
1.9.1



[PATCH v2 3/3] ASoC: stm32: Add full duplex support to i2s

2017-05-10 Thread olivier moysan
This patch allows to use i2s interface either as single
audio path (rx or tx), or bidirectional audio path.
This patch is added separately, as the driver does not
follow recommended use of the interface, to support this
configuration.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_i2s.c | 88 +--
 1 file changed, 47 insertions(+), 41 deletions(-)

diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 22152a1..a8e03c5 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -489,7 +489,6 @@ static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai,
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
int format = params_width(params);
u32 cfgr, cfgr_mask, cfg1, cfg1_mask;
-   bool playback_flg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
unsigned int fthlv;
int ret;
 
@@ -515,19 +514,13 @@ static int stm32_i2s_configure(struct snd_soc_dai 
*cpu_dai,
}
 
if (STM32_I2S_IS_SLAVE(i2s)) {
-   if (playback_flg)
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_TX_SLAVE);
-   else
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_RX_SLAVE);
+   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_SLAVE);
 
/* As data length is either 16 or 32 bits, fixch always set */
cfgr |= I2S_CGFR_FIXCH;
cfgr_mask |= I2S_CGFR_FIXCH;
} else {
-   if (playback_flg)
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_TX_MASTER);
-   else
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_RX_MASTER);
+   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_MASTER);
}
cfgr_mask |= I2S_CGFR_I2SCFG_MASK;
 
@@ -536,9 +529,7 @@ static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai,
if (ret < 0)
return ret;
 
-   cfg1 = I2S_CFG1_RXDMAEN;
-   if (playback_flg)
-   cfg1 = I2S_CFG1_TXDMAEN;
+   cfg1 = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN;
cfg1_mask = cfg1;
 
fthlv = STM32_I2S_FIFO_SIZE * I2S_FIFO_TH_ONE_QUARTER / 4;
@@ -553,32 +544,15 @@ static int stm32_i2s_startup(struct snd_pcm_substream 
*substream,
 struct snd_soc_dai *cpu_dai)
 {
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
-   int ret, ier;
 
i2s->substream = substream;
 
spin_lock(>lock_fd);
-   if (i2s->refcount) {
-   dev_err(cpu_dai->dev, "%s stream already started\n",
-   (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-   "Capture" : "Playback"));
-   spin_unlock(>lock_fd);
-   return -EBUSY;
-   }
-   i2s->refcount = 1;
+   i2s->refcount++;
spin_unlock(>lock_fd);
 
-   ret = regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
-I2S_IFCR_MASK, I2S_IFCR_MASK);
-   if (ret < 0)
-   return ret;
-
-   /* Enable ITs */
-   ier = I2S_IER_OVRIE | I2S_IER_UDRIE;
-   if (STM32_I2S_IS_SLAVE(i2s))
-   ier |= I2S_IER_TIFREIE;
-
-   return regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, ier, ier);
+   return regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
+ I2S_IFCR_MASK, I2S_IFCR_MASK);
 }
 
 static int stm32_i2s_hw_params(struct snd_pcm_substream *substream,
@@ -605,9 +579,11 @@ static int stm32_i2s_trigger(struct snd_pcm_substream 
*substream, int cmd,
 {
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
bool playback_flg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
-   u32 cfg1_mask;
+   u32 cfg1_mask, ier;
int ret;
 
+   spin_lock(>lock_fd);
+
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
@@ -628,10 +604,45 @@ static int stm32_i2s_trigger(struct snd_pcm_substream 
*substream, int cmd,
dev_err(cpu_dai->dev, "Error %d starting I2S\n", ret);
return ret;
}
+
+   regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
+  I2S_IFCR_MASK, I2S_IFCR_MASK);
+
+   if (playback_flg) {
+   ier = I2S_IER_UDRIE;
+   } else {
+   ier = I2S_IER_OVRIE;
+
+   if (i2s->refcount == 1) {
+   /* dummy write to trigger capture */
+   ret = regmap_write(i2s->regmap,
+  STM32_I2S_TXDR_REG, 0);
+   if (ret)
+   return ret;
+

[PATCH v2 2/3] ASoC: stm32: Add I2S driver

2017-05-10 Thread olivier moysan
Add I2S ASoC driver for STM32.
This version of the driver supports only
exclusive playback and capture interface.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/Kconfig |   2 +-
 sound/soc/stm/Makefile|   4 +
 sound/soc/stm/stm32_i2s.c | 941 ++
 3 files changed, 946 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/stm/stm32_i2s.c

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 972970f..a6372de 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -5,4 +5,4 @@ menuconfig SND_SOC_STM32
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
help
- Say Y if you want to enable ASoC-support for STM32
+ Say Y if you want to enable ASoC support for STM32
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
index e466a47..8251931 100644
--- a/sound/soc/stm/Makefile
+++ b/sound/soc/stm/Makefile
@@ -4,3 +4,7 @@ obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o
 
 snd-soc-stm32-sai-objs := stm32_sai.o
 obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o
+
+# I2S
+snd-soc-stm32-i2s-objs := stm32_i2s.o
+obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-i2s.o
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
new file mode 100644
index 000..22152a1
--- /dev/null
+++ b/sound/soc/stm/stm32_i2s.c
@@ -0,0 +1,941 @@
+/*
+ *  STM32 ALSA SoC Digital Audio Interface (I2S) driver.
+ *
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Olivier Moysan <olivier.moy...@st.com> for STMicroelectronics.
+ *
+ * License terms: GPL V2.0.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
more
+ * details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define STM32_I2S_CR1_REG  0x0
+#define STM32_I2S_CFG1_REG 0x08
+#define STM32_I2S_CFG2_REG 0x0C
+#define STM32_I2S_IER_REG  0x10
+#define STM32_I2S_SR_REG   0x14
+#define STM32_I2S_IFCR_REG 0x18
+#define STM32_I2S_TXDR_REG 0X20
+#define STM32_I2S_RXDR_REG 0x30
+#define STM32_I2S_CGFR_REG 0X50
+
+/* Bit definition for SPI2S_CR1 register */
+#define I2S_CR1_SPEBIT(0)
+#define I2S_CR1_CSTART BIT(9)
+#define I2S_CR1_CSUSP  BIT(10)
+#define I2S_CR1_HDDIR  BIT(11)
+#define I2S_CR1_SSIBIT(12)
+#define I2S_CR1_CRC33_17   BIT(13)
+#define I2S_CR1_RCRCI  BIT(14)
+#define I2S_CR1_TCRCI  BIT(15)
+
+/* Bit definition for SPI_CFG2 register */
+#define I2S_CFG2_IOSWP_SHIFT   15
+#define I2S_CFG2_IOSWP BIT(I2S_CFG2_IOSWP_SHIFT)
+#define I2S_CFG2_LSBFRST   BIT(23)
+#define I2S_CFG2_AFCNTRBIT(31)
+
+/* Bit definition for SPI_CFG1 register */
+#define I2S_CFG1_FTHVL_SHIFT   5
+#define I2S_CFG1_FTHVL_MASKGENMASK(8, I2S_CFG1_FTHVL_SHIFT)
+#define I2S_CFG1_FTHVL_SET(x)  ((x) << I2S_CFG1_FTHVL_SHIFT)
+
+#define I2S_CFG1_TXDMAEN   BIT(15)
+#define I2S_CFG1_RXDMAEN   BIT(14)
+
+/* Bit definition for SPI2S_IER register */
+#define I2S_IER_RXPIE  BIT(0)
+#define I2S_IER_TXPIE  BIT(1)
+#define I2S_IER_DPXPIE BIT(2)
+#define I2S_IER_EOTIE  BIT(3)
+#define I2S_IER_TXTFIE BIT(4)
+#define I2S_IER_UDRIE  BIT(5)
+#define I2S_IER_OVRIE  BIT(6)
+#define I2S_IER_CRCEIE BIT(7)
+#define I2S_IER_TIFREIEBIT(8)
+#define I2S_IER_MODFIE BIT(9)
+#define I2S_IER_TSERFIEBIT(10)
+
+/* Bit definition for SPI2S_SR register */
+#define I2S_SR_RXP BIT(0)
+#define I2S_SR_TXP BIT(1)
+#define I2S_SR_DPXPBIT(2)
+#define I2S_SR_EOT BIT(3)
+#define I2S_SR_TXTFBIT(4)
+#define I2S_SR_UDR BIT(5)
+#define I2S_SR_OVR BIT(6)
+#define I2S_SR_CRCERR  BIT(7)
+#define I2S_SR_TIFRE   BIT(8)
+#define I2S_SR_MODFBIT(9)
+#define I2S_SR_TSERF   BIT(10)
+#define I2S_SR_SUSPBIT(11)
+#define I2S_SR_TXC BIT(12)
+#define I2S_SR_RXPLVL  GENMASK(14, 13)
+#define I2S_SR_RXWNE   BIT(15)
+
+#define I2S_SR_MASKGENMASK(15, 0)
+
+/* Bit definition for SPI_IFCR register */
+#define I2S_IFCR_EOTC  BIT(3)
+#define I2S_IFCR_TXTFC BIT(4)
+#define I2S_IFCR_UDRC  BIT(5)
+#define I2S_IFCR_OVRC  BIT(6)
+#define I2S_IFCR_CRCEC BIT(7)
+#define I2S_IFCR_TIFRECBIT(8)
+#define I2S_IFCR_MODFC BIT(9)
+#define I2S_IFCR_TSERFC  

[PATCH v2 1/3] dt-bindings: Document STM32 I2S bindings

2017-05-10 Thread olivier moysan
Add documentation of device tree bindings for STM32 SPI/I2S.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 .../devicetree/bindings/sound/st,stm32-i2s.txt | 68 ++
 1 file changed, 68 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.txt

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
new file mode 100644
index 000..67b854a
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
@@ -0,0 +1,68 @@
+STMicroelectronics STM32 SPI/I2S Controller
+
+The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode.
+Only some SPI instances support I2S.
+
+Required properties:
+  - compatible: Must be "st,stm32h7-i2s"
+  - reg: Offset and length of the device's register set.
+  - interrupts: Must contain the interrupt line id.
+  - clocks: Must contain phandle and clock specifier pairs for each entry
+   in clock-names.
+  - clock-names: Must contain "i2sclk", "pclk", "x8k" and "x11k".
+   "i2sclk": clock which feeds the internal clock generator
+   "pclk": clock which feeds the peripheral bus interface
+   "x8k": I2S parent clock for sampling rates multiple of 8kHz.
+   "x11k": I2S parent clock for sampling rates multiple of 11.025kHz.
+  - dmas: DMA specifiers for tx and rx dma.
+See Documentation/devicetree/bindings/dma/stm32-dma.txt.
+  - dma-names: Identifier for each DMA request line. Must be "tx" and "rx".
+  - pinctrl-names: should contain only value "default"
+  - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
+
+Optional properties:
+  - resets: Reference to a reset controller asserting the reset controller
+
+The device node should contain one 'port' child node with one child 'endpoint'
+node, according to the bindings defined in Documentation/devicetree/bindings/
+graph.txt.
+
+Example:
+sound_card {
+   compatible = "audio-graph-card";
+   dais = <_port 0>;
+};
+
+i2s2: audio-controller@40003800 {
+   compatible = "st,stm32h7-i2s";
+   #sound-dai-cells = <0>;
+   reg = <0x40003800 0x400>;
+   interrupts = <36>;
+   clocks = < PCLK1>, < SPI2_CK>, < PLL1_Q>, < PLL2_P>;
+   clock-names = "pclk", "i2sclk",  "x8k", "x11k";
+   dmas = < 2 39 0x400 0x1>,
+   < 3 40 0x400 0x1>;
+   dma-names = "rx", "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_i2s2>;
+
+   i2s2_port: port@0 {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   cpu_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   format = "i2s";
+   bitclock-master = <_endpoint>;
+   frame-master = <_endpoint>;
+   };
+   };
+};
+
+audio-codec {
+   codec_port: port@0 {
+   codec_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   };
+   };
+};
-- 
1.9.1



[PATCH v2 2/2] ASoC: stm32: Add SPDIFRX support

2017-06-20 Thread olivier moysan
Add SPDIFRX support to STM32.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/Kconfig |  10 +
 sound/soc/stm/Makefile|   4 +
 sound/soc/stm/stm32_spdifrx.c | 998 ++
 3 files changed, 1012 insertions(+)
 create mode 100644 sound/soc/stm/stm32_spdifrx.c

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 23600a5..3398e6c 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -18,4 +18,14 @@ config SND_SOC_STM32_I2S
help
  Say Y if you want to enable I2S for STM32
 
+config SND_SOC_STM32_SPDIFRX
+   tristate "STM32 S/PDIF receiver (SPDIFRX) support"
+   depends on ARCH_STM32 || COMPILE_TEST
+   depends on SND_SOC
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   select SND_SOC_SPDIF
+   help
+ Say Y if you want to enable S/PDIF capture for STM32
+
 endmenu
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
index 4140c67..4ed22e6 100644
--- a/sound/soc/stm/Makefile
+++ b/sound/soc/stm/Makefile
@@ -8,3 +8,7 @@ obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai.o
 # I2S
 snd-soc-stm32-i2s-objs := stm32_i2s.o
 obj-$(CONFIG_SND_SOC_STM32_I2S) += snd-soc-stm32-i2s.o
+
+# SPDIFRX
+snd-soc-stm32-spdifrx-objs := stm32_spdifrx.o
+obj-$(CONFIG_SND_SOC_STM32_SPDIFRX) += snd-soc-stm32-spdifrx.o
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
new file mode 100644
index 000..4e4250b
--- /dev/null
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -0,0 +1,998 @@
+/*
+ * STM32 ALSA SoC Digital Audio Interface (SPDIF-rx) driver.
+ *
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Olivier Moysan <olivier.moy...@st.com> for STMicroelectronics.
+ *
+ * License terms: GPL V2.0.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
more
+ * details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+/* SPDIF-rx Register Map */
+#define STM32_SPDIFRX_CR   0x00
+#define STM32_SPDIFRX_IMR  0x04
+#define STM32_SPDIFRX_SR   0x08
+#define STM32_SPDIFRX_IFCR 0x0C
+#define STM32_SPDIFRX_DR   0x10
+#define STM32_SPDIFRX_CSR  0x14
+#define STM32_SPDIFRX_DIR  0x18
+
+/* Bit definition for SPDIF_CR register */
+#define SPDIFRX_CR_SPDIFEN_SHIFT   0
+#define SPDIFRX_CR_SPDIFEN_MASKGENMASK(1, SPDIFRX_CR_SPDIFEN_SHIFT)
+#define SPDIFRX_CR_SPDIFENSET(x)   ((x) << SPDIFRX_CR_SPDIFEN_SHIFT)
+
+#define SPDIFRX_CR_RXDMAEN BIT(2)
+#define SPDIFRX_CR_RXSTEO  BIT(3)
+
+#define SPDIFRX_CR_DRFMT_SHIFT 4
+#define SPDIFRX_CR_DRFMT_MASK  GENMASK(5, SPDIFRX_CR_DRFMT_SHIFT)
+#define SPDIFRX_CR_DRFMTSET(x) ((x) << SPDIFRX_CR_DRFMT_SHIFT)
+
+#define SPDIFRX_CR_PMSKBIT(6)
+#define SPDIFRX_CR_VMSKBIT(7)
+#define SPDIFRX_CR_CUMSK   BIT(8)
+#define SPDIFRX_CR_PTMSK   BIT(9)
+#define SPDIFRX_CR_CBDMAEN BIT(10)
+#define SPDIFRX_CR_CHSEL_SHIFT 11
+#define SPDIFRX_CR_CHSEL   BIT(SPDIFRX_CR_CHSEL_SHIFT)
+
+#define SPDIFRX_CR_NBTR_SHIFT  12
+#define SPDIFRX_CR_NBTR_MASK   GENMASK(13, SPDIFRX_CR_NBTR_SHIFT)
+#define SPDIFRX_CR_NBTRSET(x)  ((x) << SPDIFRX_CR_NBTR_SHIFT)
+
+#define SPDIFRX_CR_WFA BIT(14)
+
+#define SPDIFRX_CR_INSEL_SHIFT 16
+#define SPDIFRX_CR_INSEL_MASK  GENMASK(18, PDIFRX_CR_INSEL_SHIFT)
+#define SPDIFRX_CR_INSELSET(x) ((x) << SPDIFRX_CR_INSEL_SHIFT)
+
+#define SPDIFRX_CR_CKSEN_SHIFT 20
+#define SPDIFRX_CR_CKSEN   BIT(20)
+#define SPDIFRX_CR_CKSBKPENBIT(21)
+
+/* Bit definition for SPDIFRX_IMR register */
+#define SPDIFRX_IMR_RXNEI  BIT(0)
+#define SPDIFRX_IMR_CSRNEIEBIT(1)
+#define SPDIFRX_IMR_PERRIE BIT(2)
+#define SPDIFRX_IMR_OVRIE  BIT(3)
+#define SPDIFRX_IMR_SBLKIE BIT(4)
+#define SPDIFRX_IMR_SYNCDIEBIT(5)
+#define SPDIFRX_IMR_IFEIE  BIT(6)
+
+#define SPDIFRX_XIMR_MASK  GENMASK(6, 0)
+
+/* Bit definition for SPDIFRX_SR register */
+#define SPDIFRX_SR_RXNEBIT(0)
+#define SPDIFRX_SR_CSRNE   BIT(1)
+#define SPDIFRX_SR_PERRBIT(2)
+#define SPDIFRX_SR_OVR BIT(3)
+#define SPDIFRX_SR_SBD BIT(4)
+#define SPDIFRX_SR_SYNCD   BIT(5)
+#define SPDIFRX_SR_FERRBIT(6)
+#define SPDIFRX_SR_SERRBIT(7)
+#define SPDIFRX_SR_TERRBIT(8)
+
+#define SPDIFRX_SR_WIDTH5_SHIFT16
+#define SPDIFRX_SR_WIDTH5_MASK GENMASK(30, PDIFRX_SR_WIDTH5_SHIFT)
+#define SPDIFRX_SR_WIDTH5SET(x)((x) << SPDIFRX_SR_WIDTH5_S

[PATCH v2 1/2] ASoC: stm32: Add DT bindings for SPDIFRX interface

2017-06-20 Thread olivier moysan
Add documentation of device tree bindings for the
STM32 SPDIFRX interface.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 .../devicetree/bindings/sound/st,stm32-spdifrx.txt | 56 ++
 1 file changed, 56 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt
new file mode 100644
index 000..33826f2
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt
@@ -0,0 +1,56 @@
+STMicroelectronics STM32 S/PDIF receiver (SPDIFRX).
+
+The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with
+IEC-60958 and IEC-61937.
+
+Required properties:
+  - compatible: should be "st,stm32h7-spdifrx"
+  - reg: cpu DAI IP base address and size
+  - clocks: must contain an entry for kclk (used as S/PDIF signal reference)
+  - clock-names: must contain "kclk"
+  - interrupts: cpu DAI interrupt line
+  - dmas: DMA specifiers for audio data DMA and iec control flow DMA
+See STM32 DMA bindings, Documentation/devicetree/bindings/dma/stm32-dma.txt
+  - dma-names: two dmas have to be defined, "rx" and "rx-ctrl"
+
+Optional properties:
+  - resets: Reference to a reset controller asserting the SPDIFRX
+
+The device node should contain one 'port' child node with one child 'endpoint'
+node, according to the bindings defined in Documentation/devicetree/bindings/
+graph.txt.
+
+Example:
+spdifrx: spdifrx@40004000 {
+   compatible = "st,stm32h7-spdifrx";
+   reg = <0x40004000 0x400>;
+   clocks = < SPDIFRX_CK>;
+   clock-names = "kclk";
+   interrupts = <97>;
+   dmas = < 2 93 0x400 0x0>,
+  < 3 94 0x400 0x0>;
+   dma-names = "rx", "rx-ctrl";
+   pinctrl-0 = <_pins>;
+   pinctrl-names = "default";
+
+   spdifrx_port: port {
+   cpu_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   };
+   };
+};
+
+spdif_in: spdif-in {
+   compatible = "linux,spdif-dir";
+
+   codec_port: port {
+   codec_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   };
+   };
+};
+
+soundcard {
+   compatible = "audio-graph-card";
+   dais = <_port>;
+};
-- 
1.9.1



[PATCH v2 0/2] ASoC: stm32: add SPDIFRX driver

2017-06-20 Thread olivier moysan
This patch-set handles the SPDIFRX on STM32 platforms.

The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with
IEC-60958 and IEC-61937 standards.

SPDIFRX uses two DMA channels:
- one DMA channel for S/PDIF data stream.
- one DMA channel for control flow (channel status and user data bits).

DMA is used for control flow instead of interrupts to get better performances,
as channel status and user data are retrieved byte per byte.

v1 -> v2:
- fix merge issue

olivier moysan (2):
  ASoC: stm32: Add DT bindings for SPDIFRX interface
  ASoC: stm32: Add SPDIFRX support

 .../devicetree/bindings/sound/st,stm32-spdifrx.txt |  56 ++
 sound/soc/stm/Kconfig  |  10 +
 sound/soc/stm/Makefile |   4 +
 sound/soc/stm/stm32_spdifrx.c  | 998 +
 4 files changed, 1068 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt
 create mode 100644 sound/soc/stm/stm32_spdifrx.c

-- 
1.9.1



Re: [PATCH 1/2] dt-bindings: Document the STM32 SPDIFRX interface

2017-06-27 Thread Olivier MOYSAN
Hello Rob,

On 06/23/2017 08:55 PM, Rob Herring wrote:
> On Fri, Jun 16, 2017 at 03:57:31PM +0200, olivier moysan wrote:
>> This adds documentation of device tree bindings for the
>> STM32 SPDIFRX interface.
>>
>> Signed-off-by: olivier moysan <olivier.moy...@st.com>
>> ---
>>   .../devicetree/bindings/sound/st,stm32-spdifrx.txt | 56 
>> ++
>>   1 file changed, 56 insertions(+)
>>   create mode 100644 
>> Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt
>>
>> diff --git a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt 
>> b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt
>> new file mode 100644
>> index 000..33826f2
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt
>> @@ -0,0 +1,56 @@
>> +STMicroelectronics STM32 S/PDIF receiver (SPDIFRX).
>> +
>> +The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with
>> +IEC-60958 and IEC-61937.
>> +
>> +Required properties:
>> +  - compatible: should be "st,stm32h7-spdifrx"
>> +  - reg: cpu DAI IP base address and size
>> +  - clocks: must contain an entry for kclk (used as S/PDIF signal reference)
>> +  - clock-names: must contain "kclk"
>> +  - interrupts: cpu DAI interrupt line
>> +  - dmas: DMA specifiers for audio data DMA and iec control flow DMA
>> +See STM32 DMA bindings, 
>> Documentation/devicetree/bindings/dma/stm32-dma.txt
>> +  - dma-names: two dmas have to be defined, "rx" and "rx-ctrl"
>> +
>> +Optional properties:
>> +  - resets: Reference to a reset controller asserting the SPDIFRX
>> +
>> +The device node should contain one 'port' child node with one child 
>> 'endpoint'
>> +node, according to the bindings defined in 
>> Documentation/devicetree/bindings/
>> +graph.txt.
>> +
>> +Example:
>> +spdifrx: spdifrx@40004000 {
>> +compatible = "st,stm32h7-spdifrx";
>> +reg = <0x40004000 0x400>;
>> +clocks = < SPDIFRX_CK>;
>> +clock-names = "kclk";
>> +interrupts = <97>;
>> +dmas = < 2 93 0x400 0x0>,
>> +   < 3 94 0x400 0x0>;
>> +dma-names = "rx", "rx-ctrl";
>> +pinctrl-0 = <_pins>;
>> +pinctrl-names = "default";
>> +
>> +spdifrx_port: port {
>> +cpu_endpoint: endpoint {
>> +remote-endpoint = <_endpoint>;
>> +};
>> +};
>> +};
>> +
>> +spdif_in: spdif-in {
>> +compatible = "linux,spdif-dir";
> 
> What is this? It should go.
> 
> Rob
> 

This is the ASoC spdif stub codec. This is relevant in DT when
spdif interface is wired to a connector.
I will remove it from bindings.

BRs
olivier

Re: [PATCH v3 1/3] dt-bindings: Document STM32 I2S bindings

2017-05-18 Thread Olivier MOYSAN
Hello Rob,

Thanks for your comment.

On 05/13/2017 02:17 AM, Rob Herring wrote:
> On Thu, May 11, 2017 at 11:45:02AM +0200, olivier moysan wrote:
>> Add documentation of device tree bindings for STM32 SPI/I2S.
>>
>> Signed-off-by: olivier moysan <olivier.moy...@st.com>
>> ---
>>  .../devicetree/bindings/sound/st,stm32-i2s.txt | 68 
>> ++
>>  1 file changed, 68 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
>>
>> diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt 
>> b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
>> new file mode 100644
>> index 000..67b854a
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
>> @@ -0,0 +1,68 @@
>> +STMicroelectronics STM32 SPI/I2S Controller
>> +
>> +The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode.
>> +Only some SPI instances support I2S.
>> +
>> +Required properties:
>> +  - compatible: Must be "st,stm32h7-i2s"
>> +  - reg: Offset and length of the device's register set.
>> +  - interrupts: Must contain the interrupt line id.
>> +  - clocks: Must contain phandle and clock specifier pairs for each entry
>> +in clock-names.
>> +  - clock-names: Must contain "i2sclk", "pclk", "x8k" and "x11k".
>> +"i2sclk": clock which feeds the internal clock generator
>> +"pclk": clock which feeds the peripheral bus interface
>> +"x8k": I2S parent clock for sampling rates multiple of 8kHz.
>> +"x11k": I2S parent clock for sampling rates multiple of 11.025kHz.
>> +  - dmas: DMA specifiers for tx and rx dma.
>> +See Documentation/devicetree/bindings/dma/stm32-dma.txt.
>> +  - dma-names: Identifier for each DMA request line. Must be "tx" and "rx".
>> +  - pinctrl-names: should contain only value "default"
>> +  - pinctrl-0: see 
>> Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
>> +
>> +Optional properties:
>> +  - resets: Reference to a reset controller asserting the reset controller
>> +
>> +The device node should contain one 'port' child node with one child 
>> 'endpoint'
>> +node, according to the bindings defined in 
>> Documentation/devicetree/bindings/
>> +graph.txt.
>> +
>> +Example:
>> +sound_card {
>> +compatible = "audio-graph-card";
>> +dais = <_port 0>;
>
> What is the 0 representing?
>

This is no more relevant, so to be removed.

>> +};
>> +
>> +i2s2: audio-controller@40003800 {
>> +compatible = "st,stm32h7-i2s";
>> +#sound-dai-cells = <0>;
>
> Should be dropped.
>

ok

>> +reg = <0x40003800 0x400>;
>> +interrupts = <36>;
>> +clocks = < PCLK1>, < SPI2_CK>, < PLL1_Q>, < PLL2_P>;
>> +clock-names = "pclk", "i2sclk",  "x8k", "x11k";
>> +dmas = < 2 39 0x400 0x1>,
>> +   < 3 40 0x400 0x1>;
>> +dma-names = "rx", "tx";
>> +pinctrl-names = "default";
>> +pinctrl-0 = <_i2s2>;
>> +
>> +i2s2_port: port@0 {
>> +#address-cells = <1>;
>> +#size-cells = <0>;
>
> This shouldn't even compile. You don't need these because because you
> have no reg property in the endpoint.
>
> You have a unit-address here w/o a reg property. You don't need a reg
> prop because you only have 1 port.
>

ok.

>> +
>> +cpu_endpoint: endpoint {
>> +remote-endpoint = <_endpoint>;
>> +format = "i2s";
>> +bitclock-master = <_endpoint>;
>> +frame-master = <_endpoint>;
>> +};
>> +};
>> +};
>> +
>> +audio-codec {
>> +codec_port: port@0 {
>> +codec_endpoint: endpoint {
>> +remote-endpoint = <_endpoint>;
>> +};
>> +};
>> +};
>> --
>> 1.9.1
>>

BRs
Olivier


[PATCH v4 3/3] ASoC: stm32: Add full duplex support to i2s

2017-05-18 Thread olivier moysan
This patch allows to use i2s interface either as single
audio path (rx or tx), or bidirectional audio path.
This patch is added separately, as the driver does not
follow recommended use of the interface, to support this
configuration.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_i2s.c | 87 +--
 1 file changed, 46 insertions(+), 41 deletions(-)

diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 22152a1..8052629 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -489,7 +489,6 @@ static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai,
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
int format = params_width(params);
u32 cfgr, cfgr_mask, cfg1, cfg1_mask;
-   bool playback_flg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
unsigned int fthlv;
int ret;
 
@@ -515,19 +514,13 @@ static int stm32_i2s_configure(struct snd_soc_dai 
*cpu_dai,
}
 
if (STM32_I2S_IS_SLAVE(i2s)) {
-   if (playback_flg)
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_TX_SLAVE);
-   else
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_RX_SLAVE);
+   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_SLAVE);
 
/* As data length is either 16 or 32 bits, fixch always set */
cfgr |= I2S_CGFR_FIXCH;
cfgr_mask |= I2S_CGFR_FIXCH;
} else {
-   if (playback_flg)
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_TX_MASTER);
-   else
-   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_RX_MASTER);
+   cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_MASTER);
}
cfgr_mask |= I2S_CGFR_I2SCFG_MASK;
 
@@ -536,9 +529,7 @@ static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai,
if (ret < 0)
return ret;
 
-   cfg1 = I2S_CFG1_RXDMAEN;
-   if (playback_flg)
-   cfg1 = I2S_CFG1_TXDMAEN;
+   cfg1 = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN;
cfg1_mask = cfg1;
 
fthlv = STM32_I2S_FIFO_SIZE * I2S_FIFO_TH_ONE_QUARTER / 4;
@@ -553,32 +544,15 @@ static int stm32_i2s_startup(struct snd_pcm_substream 
*substream,
 struct snd_soc_dai *cpu_dai)
 {
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
-   int ret, ier;
 
i2s->substream = substream;
 
spin_lock(>lock_fd);
-   if (i2s->refcount) {
-   dev_err(cpu_dai->dev, "%s stream already started\n",
-   (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-   "Capture" : "Playback"));
-   spin_unlock(>lock_fd);
-   return -EBUSY;
-   }
-   i2s->refcount = 1;
+   i2s->refcount++;
spin_unlock(>lock_fd);
 
-   ret = regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
-I2S_IFCR_MASK, I2S_IFCR_MASK);
-   if (ret < 0)
-   return ret;
-
-   /* Enable ITs */
-   ier = I2S_IER_OVRIE | I2S_IER_UDRIE;
-   if (STM32_I2S_IS_SLAVE(i2s))
-   ier |= I2S_IER_TIFREIE;
-
-   return regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, ier, ier);
+   return regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
+ I2S_IFCR_MASK, I2S_IFCR_MASK);
 }
 
 static int stm32_i2s_hw_params(struct snd_pcm_substream *substream,
@@ -605,7 +579,7 @@ static int stm32_i2s_trigger(struct snd_pcm_substream 
*substream, int cmd,
 {
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
bool playback_flg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
-   u32 cfg1_mask;
+   u32 cfg1_mask, ier;
int ret;
 
switch (cmd) {
@@ -628,10 +602,48 @@ static int stm32_i2s_trigger(struct snd_pcm_substream 
*substream, int cmd,
dev_err(cpu_dai->dev, "Error %d starting I2S\n", ret);
return ret;
}
+
+   regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
+  I2S_IFCR_MASK, I2S_IFCR_MASK);
+
+   if (playback_flg) {
+   ier = I2S_IER_UDRIE;
+   } else {
+   ier = I2S_IER_OVRIE;
+
+   spin_lock(>lock_fd);
+   if (i2s->refcount == 1)
+   /* dummy write to trigger capture */
+   regmap_write(i2s->regmap,
+STM32_I2S_TXDR_REG, 0);
+   spin_unlock(>lock_fd);
+   }
+
+   if (STM32_I2S_IS_SLAVE(i2s))
+   ier |= I2S_IER_TIFREIE;
+
+

[PATCH v4 0/3] ASoC: Add STM32 I2S support

2017-05-18 Thread olivier moysan
This patch-set handles the SPI/I2S IP on STM32 platforms.

It applies to STM32 platforms implementing version 2 of SPI/I2S IP like STM32H7 
series.

The SPI/I2S block is a serial peripheral interface (SPI), which can also be 
configured to work on I2S/PCM mode.
ASoC STM32 I2S driver only supports this I2S/PCM mode.

The I2S/PCM interface can either support full duplex or half-duplex 
communication
(transmitter or receiver only). The change of mode requires to stop the 
interface.
This means that the two audio paths cannot be basically managed independently.

The driver supports playback and capture through a single bidirectionnal DAI. 
In the first version of the driver, playback and capture paths are made 
mutually exclusive.

A second patch introduces support of full duplex mode. 
In this implementation the interface is systematically configured in 
full-duplex mode
from hardware point of view. So, when managing a single audio path, the 
interface
is not configured as transmit or receive only, as it should be.
This restriction is handled by masking underrun/overrun errors from the unused 
path.

The I2S/PCM interface supports four audio standards:
I2S Philips standard, MSB justified standard, LSB justified standard, PCM 
standard
PCM standard is declined in two versions, PCM short and long,
according frame synchronization duration.

These standards can be mapped to ASoC standards as follows:
- I2S: i2s
- MSB justified standard: left_j
- LSB justified standard: right_j
- PCM short: dsp_a
PCM long format is not exposed as it does not match supported ASoC standards.

v3 -> v4
- update example in dt bindings

olivier moysan (3):
  dt-bindings: Document STM32 I2S bindings
  ASoC: stm32: Add I2S driver
  ASoC: stm32: Add full duplex support to i2s

 .../devicetree/bindings/sound/st,stm32-i2s.txt |  62 ++
 sound/soc/stm/Kconfig  |   2 +-
 sound/soc/stm/Makefile |   4 +
 sound/soc/stm/stm32_i2s.c  | 946 +
 4 files changed, 1013 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
 create mode 100644 sound/soc/stm/stm32_i2s.c

-- 
1.9.1



[PATCH v4 1/3] dt-bindings: Document STM32 I2S bindings

2017-05-18 Thread olivier moysan
Add documentation of device tree bindings for STM32 SPI/I2S.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 .../devicetree/bindings/sound/st,stm32-i2s.txt | 62 ++
 1 file changed, 62 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.txt

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
new file mode 100644
index 000..4bda520
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
@@ -0,0 +1,62 @@
+STMicroelectronics STM32 SPI/I2S Controller
+
+The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode.
+Only some SPI instances support I2S.
+
+Required properties:
+  - compatible: Must be "st,stm32h7-i2s"
+  - reg: Offset and length of the device's register set.
+  - interrupts: Must contain the interrupt line id.
+  - clocks: Must contain phandle and clock specifier pairs for each entry
+   in clock-names.
+  - clock-names: Must contain "i2sclk", "pclk", "x8k" and "x11k".
+   "i2sclk": clock which feeds the internal clock generator
+   "pclk": clock which feeds the peripheral bus interface
+   "x8k": I2S parent clock for sampling rates multiple of 8kHz.
+   "x11k": I2S parent clock for sampling rates multiple of 11.025kHz.
+  - dmas: DMA specifiers for tx and rx dma.
+See Documentation/devicetree/bindings/dma/stm32-dma.txt.
+  - dma-names: Identifier for each DMA request line. Must be "tx" and "rx".
+  - pinctrl-names: should contain only value "default"
+  - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
+
+Optional properties:
+  - resets: Reference to a reset controller asserting the reset controller
+
+The device node should contain one 'port' child node with one child 'endpoint'
+node, according to the bindings defined in Documentation/devicetree/bindings/
+graph.txt.
+
+Example:
+sound_card {
+   compatible = "audio-graph-card";
+   dais = <_port>;
+};
+
+i2s2: audio-controller@40003800 {
+   compatible = "st,stm32h7-i2s";
+   reg = <0x40003800 0x400>;
+   interrupts = <36>;
+   clocks = < PCLK1>, < SPI2_CK>, < PLL1_Q>, < PLL2_P>;
+   clock-names = "pclk", "i2sclk",  "x8k", "x11k";
+   dmas = < 2 39 0x400 0x1>,
+   < 3 40 0x400 0x1>;
+   dma-names = "rx", "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_i2s2>;
+
+   i2s2_port: port@0 {
+   cpu_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   format = "i2s";
+   };
+   };
+};
+
+audio-codec {
+   codec_port: port@0 {
+   codec_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   };
+   };
+};
-- 
1.9.1



[PATCH v4 2/3] ASoC: stm32: Add I2S driver

2017-05-18 Thread olivier moysan
Add I2S ASoC driver for STM32.
This version of the driver supports only
exclusive playback and capture interface.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/Kconfig |   2 +-
 sound/soc/stm/Makefile|   4 +
 sound/soc/stm/stm32_i2s.c | 941 ++
 3 files changed, 946 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/stm/stm32_i2s.c

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 972970f..a6372de 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -5,4 +5,4 @@ menuconfig SND_SOC_STM32
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
help
- Say Y if you want to enable ASoC-support for STM32
+ Say Y if you want to enable ASoC support for STM32
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
index e466a47..8251931 100644
--- a/sound/soc/stm/Makefile
+++ b/sound/soc/stm/Makefile
@@ -4,3 +4,7 @@ obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o
 
 snd-soc-stm32-sai-objs := stm32_sai.o
 obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o
+
+# I2S
+snd-soc-stm32-i2s-objs := stm32_i2s.o
+obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-i2s.o
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
new file mode 100644
index 000..22152a1
--- /dev/null
+++ b/sound/soc/stm/stm32_i2s.c
@@ -0,0 +1,941 @@
+/*
+ *  STM32 ALSA SoC Digital Audio Interface (I2S) driver.
+ *
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Olivier Moysan <olivier.moy...@st.com> for STMicroelectronics.
+ *
+ * License terms: GPL V2.0.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
more
+ * details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define STM32_I2S_CR1_REG  0x0
+#define STM32_I2S_CFG1_REG 0x08
+#define STM32_I2S_CFG2_REG 0x0C
+#define STM32_I2S_IER_REG  0x10
+#define STM32_I2S_SR_REG   0x14
+#define STM32_I2S_IFCR_REG 0x18
+#define STM32_I2S_TXDR_REG 0X20
+#define STM32_I2S_RXDR_REG 0x30
+#define STM32_I2S_CGFR_REG 0X50
+
+/* Bit definition for SPI2S_CR1 register */
+#define I2S_CR1_SPEBIT(0)
+#define I2S_CR1_CSTART BIT(9)
+#define I2S_CR1_CSUSP  BIT(10)
+#define I2S_CR1_HDDIR  BIT(11)
+#define I2S_CR1_SSIBIT(12)
+#define I2S_CR1_CRC33_17   BIT(13)
+#define I2S_CR1_RCRCI  BIT(14)
+#define I2S_CR1_TCRCI  BIT(15)
+
+/* Bit definition for SPI_CFG2 register */
+#define I2S_CFG2_IOSWP_SHIFT   15
+#define I2S_CFG2_IOSWP BIT(I2S_CFG2_IOSWP_SHIFT)
+#define I2S_CFG2_LSBFRST   BIT(23)
+#define I2S_CFG2_AFCNTRBIT(31)
+
+/* Bit definition for SPI_CFG1 register */
+#define I2S_CFG1_FTHVL_SHIFT   5
+#define I2S_CFG1_FTHVL_MASKGENMASK(8, I2S_CFG1_FTHVL_SHIFT)
+#define I2S_CFG1_FTHVL_SET(x)  ((x) << I2S_CFG1_FTHVL_SHIFT)
+
+#define I2S_CFG1_TXDMAEN   BIT(15)
+#define I2S_CFG1_RXDMAEN   BIT(14)
+
+/* Bit definition for SPI2S_IER register */
+#define I2S_IER_RXPIE  BIT(0)
+#define I2S_IER_TXPIE  BIT(1)
+#define I2S_IER_DPXPIE BIT(2)
+#define I2S_IER_EOTIE  BIT(3)
+#define I2S_IER_TXTFIE BIT(4)
+#define I2S_IER_UDRIE  BIT(5)
+#define I2S_IER_OVRIE  BIT(6)
+#define I2S_IER_CRCEIE BIT(7)
+#define I2S_IER_TIFREIEBIT(8)
+#define I2S_IER_MODFIE BIT(9)
+#define I2S_IER_TSERFIEBIT(10)
+
+/* Bit definition for SPI2S_SR register */
+#define I2S_SR_RXP BIT(0)
+#define I2S_SR_TXP BIT(1)
+#define I2S_SR_DPXPBIT(2)
+#define I2S_SR_EOT BIT(3)
+#define I2S_SR_TXTFBIT(4)
+#define I2S_SR_UDR BIT(5)
+#define I2S_SR_OVR BIT(6)
+#define I2S_SR_CRCERR  BIT(7)
+#define I2S_SR_TIFRE   BIT(8)
+#define I2S_SR_MODFBIT(9)
+#define I2S_SR_TSERF   BIT(10)
+#define I2S_SR_SUSPBIT(11)
+#define I2S_SR_TXC BIT(12)
+#define I2S_SR_RXPLVL  GENMASK(14, 13)
+#define I2S_SR_RXWNE   BIT(15)
+
+#define I2S_SR_MASKGENMASK(15, 0)
+
+/* Bit definition for SPI_IFCR register */
+#define I2S_IFCR_EOTC  BIT(3)
+#define I2S_IFCR_TXTFC BIT(4)
+#define I2S_IFCR_UDRC  BIT(5)
+#define I2S_IFCR_OVRC  BIT(6)
+#define I2S_IFCR_CRCEC BIT(7)
+#define I2S_IFCR_TIFRECBIT(8)
+#define I2S_IFCR_MODFC BIT(9)
+#define I2S_IFCR_TSERFC  

Re: [PATCH v4 2/3] ASoC: stm32: Add I2S driver

2017-05-22 Thread Olivier MOYSAN
Hello Mark,

Thanks, for applying the patches.

On 05/19/2017 07:33 PM, Mark Brown wrote:
> On Thu, May 18, 2017 at 05:19:52PM +0200, olivier moysan wrote:
> 
> This looks good so I'm going to apply it, a few things below though -
> can you please send a followup patch for the issue with the Kconfig
> symbol?
> 
>> --- a/sound/soc/stm/Kconfig
>> +++ b/sound/soc/stm/Kconfig
>> @@ -5,4 +5,4 @@ menuconfig SND_SOC_STM32
>>  select SND_SOC_GENERIC_DMAENGINE_PCM
>>  select REGMAP_MMIO
>>  help
>> -  Say Y if you want to enable ASoC-support for STM32
>> +  Say Y if you want to enable ASoC support for STM32
> 
> This appears to be an unrelated typo fix.
> 

ok

>> diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
>> index e466a47..8251931 100644
>> --- a/sound/soc/stm/Makefile
>> +++ b/sound/soc/stm/Makefile
>> @@ -4,3 +4,7 @@ obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o
>>   
>>   snd-soc-stm32-sai-objs := stm32_sai.o
>>   obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o
>> +
>> +# I2S
>> +snd-soc-stm32-i2s-objs := stm32_i2s.o
>> +obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-i2s.o
> 
> Perhaps make this a separate option?  It probably makes sense to rename
> the option for the SAI at the same time.
> 

ok, I will fix it in a new patch.

>> +
>> +ret = clk_prepare_enable(i2s->pclk);
>> +if (ret) {
>> +dev_err(>dev, "Enable pclk failed: %d\n", ret);
>> +return ret;
>> +}
>> +
>> +ret = clk_prepare_enable(i2s->i2sclk);
>> +if (ret) {
>> +dev_err(>dev, "Enable i2sclk failed: %d\n", ret);
>> +goto err_pclk_disable;
>> +}
> 
> It'd be nice to have runtime PM to disable these when the device is idle
> but that's not essential.
> 

Yes, I agree.

BRs
olivier


Re: [PATCH 14/15] sound: stm32: use devm_of_platform_populate()

2017-05-30 Thread Olivier MOYSAN

Acked-by: Olivier Moysan <olivier.moy...@st.com>


[PATCH 5/7] ASoC: stm32: sai: change stop sequence

2017-06-16 Thread olivier moysan
Disable SAI before stopping DMA data transfers.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai_sub.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 24b8874..97b69a3 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -629,12 +629,12 @@ static int stm32_sai_trigger(struct snd_pcm_substream 
*substream, int cmd,
dev_dbg(cpu_dai->dev, "Disable DMA and SAI\n");
 
regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
-  SAI_XCR1_DMAEN,
-  (unsigned int)~SAI_XCR1_DMAEN);
+  SAI_XCR1_SAIEN,
+  (unsigned int)~SAI_XCR1_SAIEN);
 
ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
-SAI_XCR1_SAIEN,
-(unsigned int)~SAI_XCR1_SAIEN);
+SAI_XCR1_DMAEN,
+(unsigned int)~SAI_XCR1_DMAEN);
if (ret < 0)
dev_err(cpu_dai->dev, "Failed to update CR1 
register\n");
break;
-- 
1.9.1



[PATCH 6/7] ASoC: stm32: sai: fix clock management

2017-06-16 Thread olivier moysan
Allow peripheral clock enable/disable on regmap accesses.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai_sub.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 97b69a3..2466af0 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -766,8 +766,8 @@ static int stm32_sai_sub_parse_of(struct platform_device 
*pdev,
return PTR_ERR(base);
 
sai->phys_addr = res->start;
-   sai->regmap = devm_regmap_init_mmio(>dev, base,
-   _sai_sub_regmap_config);
+   sai->regmap = devm_regmap_init_mmio_clk(>dev, "sai_ck", base,
+   _sai_sub_regmap_config);
 
/* Get direction property */
if (of_property_match_string(np, "dma-names", "tx") >= 0) {
-- 
1.9.1



[PATCH 3/7] ASoC: stm32: sai: typo fixes

2017-06-16 Thread olivier moysan
Fix typos in sai driver.

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

diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index 2a27a26..6159d66 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -110,6 +110,6 @@ static int stm32_sai_remove(struct platform_device *pdev)
 module_platform_driver(stm32_sai_driver);
 
 MODULE_DESCRIPTION("STM32 Soc SAI Interface");
-MODULE_AUTHOR("Olivier Moysan, <olivier.moy...@st.com>");
+MODULE_AUTHOR("Olivier Moysan <olivier.moy...@st.com>");
 MODULE_ALIAS("platform:st,stm32-sai");
 MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h
index a801fda..270be93 100644
--- a/sound/soc/stm/stm32_sai.h
+++ b/sound/soc/stm/stm32_sai.h
@@ -125,7 +125,6 @@
 #define SAI_XFRCR_FSOFFBIT(SAI_XFRCR_FSOFF_SHIFT)
 
 /** Bit definition for SAI_XSLOTR register **/
-
 #define SAI_XSLOTR_FBOFF_SHIFT 0
 #define SAI_XSLOTR_FBOFF_MASK  GENMASK(4, SAI_XSLOTR_FBOFF_SHIFT)
 #define SAI_XSLOTR_FBOFF_SET(x)((x) << SAI_XSLOTR_FBOFF_SHIFT)
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index ae4706c..d7aeed3 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -181,29 +181,29 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
   SAI_XCLRFR_MASK);
 
if (flags & SAI_XIMR_OVRUDRIE) {
-   dev_err(>dev, "IT %s\n",
+   dev_err(>dev, "IRQ %s\n",
STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun");
status = SNDRV_PCM_STATE_XRUN;
}
 
if (flags & SAI_XIMR_MUTEDETIE)
-   dev_dbg(>dev, "IT mute detected\n");
+   dev_dbg(>dev, "IRQ mute detected\n");
 
if (flags & SAI_XIMR_WCKCFGIE) {
-   dev_err(>dev, "IT wrong clock configuration\n");
+   dev_err(>dev, "IRQ wrong clock configuration\n");
status = SNDRV_PCM_STATE_DISCONNECTED;
}
 
if (flags & SAI_XIMR_CNRDYIE)
-   dev_warn(>dev, "IT Codec not ready\n");
+   dev_err(>dev, "IRQ Codec not ready\n");
 
if (flags & SAI_XIMR_AFSDETIE) {
-   dev_warn(>dev, "IT Anticipated frame synchro\n");
+   dev_err(>dev, "IRQ Anticipated frame synchro\n");
status = SNDRV_PCM_STATE_XRUN;
}
 
if (flags & SAI_XIMR_LFSDETIE) {
-   dev_warn(>dev, "IT Late frame synchro\n");
+   dev_err(>dev, "IRQ Late frame synchro\n");
status = SNDRV_PCM_STATE_XRUN;
}
 
@@ -235,7 +235,7 @@ 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;
 
-   dev_dbg(cpu_dai->dev, "masks tx/rx:%#x/%#x, slots:%d, width:%d\n",
+   dev_dbg(cpu_dai->dev, "Masks tx/rx:%#x/%#x, slots:%d, width:%d\n",
tx_mask, rx_mask, slots, slot_width);
 
switch (slot_width) {
@@ -377,7 +377,7 @@ static int stm32_sai_startup(struct snd_pcm_substream 
*substream,
 
ret = clk_prepare_enable(sai->sai_ck);
if (ret < 0) {
-   dev_err(cpu_dai->dev, "failed to enable clock: %d\n", ret);
+   dev_err(cpu_dai->dev, "Failed to enable clock: %d\n", ret);
return ret;
}
 
@@ -497,7 +497,7 @@ static int stm32_sai_set_slots(struct snd_soc_dai *cpu_dai)
   SAI_XSLOTR_SLOTEN_SET(sai->slot_mask));
}
 
-   dev_dbg(cpu_dai->dev, "slots %d, slot width %d\n",
+   dev_dbg(cpu_dai->dev, "Slots %d, slot width %d\n",
sai->slots, sai->slot_width);
 
return 0;
@@ -521,7 +521,7 @@ static void stm32_sai_set_frame(struct snd_soc_dai *cpu_dai)
frcr |= SAI_XFRCR_FSALL_SET((fs_active - 1));
frcr_mask = SAI_XFRCR_FRL_MASK | SAI_XFRCR_FSALL_MASK;
 
-   dev_dbg(cpu_dai->dev, "frame length %d, frame active %d\n",
+   dev_dbg(cpu_dai->dev, "Frame length %d, frame active %d\n",
sai->fs_length, fs_active);
 
regmap_update_bits(sai->regmap, STM_SAI_FRCR_REGX, frcr_mask, frcr);
@@ -784,7 +784,7 @@ static int stm32_sai_sub_parse_of(struct platform_device 
*pdev,
 
sai->sai_c

[PATCH 2/2] ASoC: stm32: sai: add h7 support

2017-06-16 Thread olivier moysan
Add support of SAI on STM32H7 family.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai.c | 13 +-
 sound/soc/stm/stm32_sai.h | 72 ++---
 sound/soc/stm/stm32_sai_sub.c | 92 ---
 3 files changed, 155 insertions(+), 22 deletions(-)

diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index 6159d66..f771331 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -27,8 +27,17 @@
 
 #include "stm32_sai.h"
 
+static const struct stm32_sai_conf stm32_sai_conf_f4 = {
+   .version = SAI_STM32F4,
+};
+
+static const struct stm32_sai_conf stm32_sai_conf_h7 = {
+   .version = SAI_STM32H7,
+};
+
 static const struct of_device_id stm32_sai_ids[] = {
-   { .compatible = "st,stm32f4-sai", .data = (void *)SAI_STM32F4 },
+   { .compatible = "st,stm32f4-sai", .data = (void *)_sai_conf_f4 },
+   { .compatible = "st,stm32h7-sai", .data = (void *)_sai_conf_h7 },
{}
 };
 
@@ -52,7 +61,7 @@ static int stm32_sai_probe(struct platform_device *pdev)
 
of_id = of_match_device(stm32_sai_ids, >dev);
if (of_id)
-   sai->version = (enum stm32_sai_version)of_id->data;
+   sai->conf = (struct stm32_sai_conf *)of_id->data;
else
return -EINVAL;
 
diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h
index 270be93..889974dc 100644
--- a/sound/soc/stm/stm32_sai.h
+++ b/sound/soc/stm/stm32_sai.h
@@ -31,6 +31,10 @@
 #define STM_SAI_CLRFR_REGX 0x18
 #define STM_SAI_DR_REGX0x1C
 
+/* Sub-block A registers, relative to sub-block A address */
+#define STM_SAI_PDMCR_REGX 0x40
+#define STM_SAI_PDMLY_REGX 0x44
+
 / Bit definition for SAI_GCR register ***/
 #define SAI_GCR_SYNCIN_SHIFT   0
 #define SAI_GCR_SYNCIN_MASKGENMASK(1, SAI_GCR_SYNCIN_SHIFT)
@@ -75,10 +79,11 @@
 #define SAI_XCR1_NODIV BIT(SAI_XCR1_NODIV_SHIFT)
 
 #define SAI_XCR1_MCKDIV_SHIFT  20
-#define SAI_XCR1_MCKDIV_WIDTH  4
-#define SAI_XCR1_MCKDIV_MASK   GENMASK(24, SAI_XCR1_MCKDIV_SHIFT)
+#define SAI_XCR1_MCKDIV_WIDTH(x)   (((x) == SAI_STM32F4) ? 4 : 6)
+#define SAI_XCR1_MCKDIV_MASK(x) GENMASK((SAI_XCR1_MCKDIV_SHIFT + (x) - 1),\
+   SAI_XCR1_MCKDIV_SHIFT)
 #define SAI_XCR1_MCKDIV_SET(x) ((x) << SAI_XCR1_MCKDIV_SHIFT)
-#define SAI_XCR1_MCKDIV_MAX((1 << SAI_XCR1_MCKDIV_WIDTH) - 1)
+#define SAI_XCR1_MCKDIV_MAX(x) ((1 << SAI_XCR1_MCKDIV_WIDTH(x)) - 1)
 
 #define SAI_XCR1_OSR_SHIFT 26
 #define SAI_XCR1_OSR   BIT(SAI_XCR1_OSR_SHIFT)
@@ -178,8 +183,65 @@
 #define SAI_XCLRFR_SHIFT   0
 #define SAI_XCLRFR_MASKGENMASK(6, SAI_XCLRFR_SHIFT)
 
+/** Bit definition for SAI_PDMCR register **/
+#define SAI_PDMCR_PDMENBIT(0)
+
+#define SAI_PDMCR_MICNBR_SHIFT 4
+#define SAI_PDMCR_MICNBR_MASK  GENMASK(5, SAI_PDMCR_MICNBR_SHIFT)
+#define SAI_PDMCR_MICNBR_SET(x)((x) << SAI_PDMCR_MICNBR_SHIFT)
+
+#define SAI_PDMCR_CKEN1BIT(8)
+#define SAI_PDMCR_CKEN2BIT(9)
+#define SAI_PDMCR_CKEN3BIT(10)
+#define SAI_PDMCR_CKEN4BIT(11)
+
+/** Bit definition for (SAI_PDMDLY register /
+#define SAI_PDMDLY_1L_SHIFT0
+#define SAI_PDMDLY_1L_MASK GENMASK(2, SAI_PDMDLY_1L_SHIFT)
+#define SAI_PDMDLY_1L_WIDTH3
+
+#define SAI_PDMDLY_1R_SHIFT4
+#define SAI_PDMDLY_1R_MASK GENMASK(6, SAI_PDMDLY_1R_SHIFT)
+#define SAI_PDMDLY_1R_WIDTH3
+
+#define SAI_PDMDLY_2L_SHIFT8
+#define SAI_PDMDLY_2L_MASK GENMASK(10, SAI_PDMDLY_2L_SHIFT)
+#define SAI_PDMDLY_2L_WIDTH3
+
+#define SAI_PDMDLY_2R_SHIFT12
+#define SAI_PDMDLY_2R_MASK GENMASK(14, SAI_PDMDLY_2R_SHIFT)
+#define SAI_PDMDLY_2R_WIDTH3
+
+#define SAI_PDMDLY_3L_SHIFT16
+#define SAI_PDMDLY_3L_MASK GENMASK(18, SAI_PDMDLY_3L_SHIFT)
+#define SAI_PDMDLY_3L_WIDTH3
+
+#define SAI_PDMDLY_3R_SHIFT20
+#define SAI_PDMDLY_3R_MASK GENMASK(22, SAI_PDMDLY_3R_SHIFT)
+#define SAI_PDMDLY_3R_WIDTH3
+
+#define SAI_PDMDLY_4L_SHIFT24
+#define SAI_PDMDLY_4L_MASK GENMASK(26, SAI_PDMDLY_4L_SHIFT)
+#define SAI_PDMDLY_4L_WIDTH3
+
+#define SAI_PDMDLY_4R_SHIFT28
+#define SAI_PDMDLY_4R_MASK GENMASK(30, SAI_PDMDLY_4R_SHIFT)
+#define SAI_PDMDLY_4R_WIDTH3
+
+#define STM_SAI_IS_F4(ip)  ((ip)->conf->version == SAI_STM32F4)
+#define STM_SAI_IS_H7(ip)  ((ip)->conf->version == SAI_STM32H7)
+
 enum stm32_sai_version {
-   SAI_STM32F4
+   SAI_STM32F4,
+   SAI_STM32H7
+};
+
+/**
+ * struct stm32_sai_conf - SAI configuration
+ * @version: SAI version
+ */
+struct stm32_sai_conf {
+   int version;
 };
 
 /**
@@ -194,6 +256,6 @@ struct stm32_sai_data {
struct platform_device *pde

[PATCH 2/7] ASoC: stm32: change SAI configuration flag

2017-06-16 Thread olivier moysan
Use a specific flag for SAI interface instead
of common stm32 asoc flag.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/Kconfig  | 10 +++---
 sound/soc/stm/Makefile |  4 ++--
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 972970f..d747993 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -1,8 +1,12 @@
-menuconfig SND_SOC_STM32
-   tristate "STMicroelectronics STM32 SOC audio support"
+menu "STMicroelectronics STM32 SOC audio support"
+
+config SND_SOC_STM32_SAI
+   tristate "STM32 SAI interface (Serial Audio Interface) support"
depends on ARCH_STM32 || COMPILE_TEST
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
help
- Say Y if you want to enable ASoC-support for STM32
+ Say Y if you want to enable SAI for STM32
+
+endmenu
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
index e466a47..386ce4b 100644
--- a/sound/soc/stm/Makefile
+++ b/sound/soc/stm/Makefile
@@ -1,6 +1,6 @@
 # SAI
 snd-soc-stm32-sai-sub-objs := stm32_sai_sub.o
-obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o
+obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai-sub.o
 
 snd-soc-stm32-sai-objs := stm32_sai.o
-obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o
+obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai.o
-- 
1.9.1



[PATCH 4/7] ASoC: stm32: sai: remove spurious trace

2017-06-16 Thread olivier moysan
Remove spurious trace in sai driver.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai_sub.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index d7aeed3..24b8874 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -761,9 +761,6 @@ static int stm32_sai_sub_parse_of(struct platform_device 
*pdev,
return -ENODEV;
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-   dev_err(>dev, "res %pr\n", res);
-
base = devm_ioremap_resource(>dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
-- 
1.9.1



[PATCH 0/7] ASoC: stm32: sai: misc fixes

2017-06-16 Thread olivier moysan
This patch-set gathers various fixes on STM32 SAI driver.

olivier moysan (7):
  dt-bindings: stm32: sai: fix DT example
  ASoC: stm32: change SAI configuration flag
  ASoC: stm32: sai: typo fixes
  ASoC: stm32: sai: remove spurious trace
  ASoC: stm32: sai: change stop sequence
  ASoC: stm32: sai: fix clock management
  ASoC: stm32: sai: manage master clock

 .../devicetree/bindings/sound/st,stm32-sai.txt | 25 --
 sound/soc/stm/Kconfig  | 10 ++--
 sound/soc/stm/Makefile |  4 +-
 sound/soc/stm/stm32_sai.c  |  2 +-
 sound/soc/stm/stm32_sai.h  |  1 -
 sound/soc/stm/stm32_sai_sub.c  | 57 +-
 6 files changed, 54 insertions(+), 45 deletions(-)

-- 
1.9.1



[PATCH 1/7] dt-bindings: stm32: sai: fix DT example

2017-06-16 Thread olivier moysan
Correct the device tree example.

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

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
index c59a3d7..a0feeed 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -36,6 +36,10 @@ SAI subnodes required properties:
   - pinctrl-names: should contain only value "default"
   - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
 
+The device node should contain one 'port' child node with one child 'endpoint'
+node, according to the bindings defined in Documentation/devicetree/bindings/
+graph.txt.
+
 Example:
 sound_card {
compatible = "audio-graph-card";
@@ -46,16 +50,15 @@ sai1: sai1@40015800 {
compatible = "st,stm32f4-sai";
#address-cells = <1>;
#size-cells = <1>;
-   ranges;
+   ranges = <0 0x40015800 0x400>;
reg = <0x40015800 0x4>;
clocks = < 1 CLK_SAIQ_PDIV>, < 1 CLK_I2SQ_PDIV>;
clock-names = "x8k", "x11k";
interrupts = <87>;
 
sai1b: audio-controller@40015824 {
-   #sound-dai-cells = <0>;
compatible = "st,stm32-sai-sub-b";
-   reg = <0x40015824 0x1C>;
+   reg = <0x24 0x1C>;
clocks = < 1 CLK_SAI2>;
clock-names = "sai_ck";
dmas = < 5 0 0x400 0x0>;
@@ -63,18 +66,10 @@ sai1: sai1@40015800 {
pinctrl-names = "default";
pinctrl-0 = <_sai1b>;
 
-   ports {
-   #address-cells = <1>;
-   #size-cells = <0>;
-
-   sai1b_port: port@0 {
-   reg = <0>;
-   cpu_endpoint: endpoint {
-   remote-endpoint = <_endpoint>;
-   audio-graph-card,format = "i2s";
-   audio-graph-card,bitclock-master = 
<_endpoint>;
-   audio-graph-card,frame-master = 
<_endpoint>;
-   };
+   sai1b_port: port {
+   cpu_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   format = "i2s";
};
};
};
-- 
1.9.1



[PATCH 1/2] dt-bindings: stm32: add h7 support for sai

2017-06-16 Thread olivier moysan
Document device tree bindings for STM32H7 SAI.

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

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
index a0feeed..f1c5ae5 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -6,7 +6,7 @@ The SAI contains two independent audio sub-blocks. Each 
sub-block has
 its own clock generator and I/O lines controller.
 
 Required properties:
-  - compatible: Should be "st,stm32f4-sai"
+  - compatible: Should be "st,stm32f4-sai" or "st,stm32h7-sai"
   - reg: Base address and size of SAI common register set.
   - clocks: Must contain phandle and clock specifier pairs for each entry
in clock-names.
@@ -47,24 +47,24 @@ sound_card {
 };
 
 sai1: sai1@40015800 {
-   compatible = "st,stm32f4-sai";
+   compatible = "st,stm32h7-sai";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x40015800 0x400>;
reg = <0x40015800 0x4>;
-   clocks = < 1 CLK_SAIQ_PDIV>, < 1 CLK_I2SQ_PDIV>;
+   clocks = < PLL1_Q>, < PLL2_P>;
clock-names = "x8k", "x11k";
interrupts = <87>;
 
-   sai1b: audio-controller@40015824 {
-   compatible = "st,stm32-sai-sub-b";
-   reg = <0x24 0x1C>;
-   clocks = < 1 CLK_SAI2>;
+   sai1a: audio-controller@40015804 {
+   compatible = "st,stm32-sai-sub-a";
+   reg = <0x4 0x1C>;
+   clocks = < SAI1_CK>;
clock-names = "sai_ck";
-   dmas = < 5 0 0x400 0x0>;
+   dmas = < 1 87 0x400 0x0>;
dma-names = "tx";
pinctrl-names = "default";
-   pinctrl-0 = <_sai1b>;
+   pinctrl-0 = <_sai1a>;
 
sai1b_port: port {
cpu_endpoint: endpoint {
-- 
1.9.1



[PATCH 7/7] ASoC: stm32: sai: manage master clock

2017-06-16 Thread olivier moysan
Disable master clock by default, and activate
it only when requested.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai_sub.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 2466af0..ce48c02 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -220,8 +220,15 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai 
*cpu_dai,
int clk_id, unsigned int freq, int dir)
 {
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+   int ret;
 
if ((dir == SND_SOC_CLOCK_OUT) && sai->master) {
+   ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
+SAI_XCR1_NODIV,
+(unsigned int)~SAI_XCR1_NODIV);
+   if (ret < 0)
+   return ret;
+
sai->mclk_rate = freq;
dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
}
@@ -356,6 +363,10 @@ 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;
+
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");
@@ -652,6 +663,9 @@ static void stm32_sai_shutdown(struct snd_pcm_substream 
*substream,
 
regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0);
 
+   regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV,
+  SAI_XCR1_NODIV);
+
clk_disable_unprepare(sai->sai_ck);
sai->substream = NULL;
 }
-- 
1.9.1



[PATCH 0/2] ASoC: stm32: sai: Add H7 support

2017-06-16 Thread olivier moysan
This patch-set adds support of the Serial Audio Interface (SAI) IP on H7 STM32 
platform family.

olivier moysan (2):
  dt-bindings: stm32: add h7 support for sai
  ASoC: stm32: sai: add h7 support

 .../devicetree/bindings/sound/st,stm32-sai.txt | 18 ++---
 sound/soc/stm/stm32_sai.c  | 13 ++-
 sound/soc/stm/stm32_sai.h  | 72 +++--
 sound/soc/stm/stm32_sai_sub.c  | 92 ++
 4 files changed, 164 insertions(+), 31 deletions(-)

-- 
1.9.1



[PATCH 2/2] ASoC: stm32: Add SPDIFRX support

2017-06-16 Thread olivier moysan
Add SPDIFRX support to STM32.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/Kconfig |  10 +
 sound/soc/stm/Makefile|   4 +
 sound/soc/stm/stm32_spdifrx.c | 998 ++
 sound/soc/stm/stm32_spdifrx.h | 224 ++
 4 files changed, 1236 insertions(+)
 create mode 100644 sound/soc/stm/stm32_spdifrx.c
 create mode 100644 sound/soc/stm/stm32_spdifrx.h

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index d747993..45c05a3 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -9,4 +9,14 @@ config SND_SOC_STM32_SAI
help
  Say Y if you want to enable SAI for STM32
 
+config SND_SOC_STM32_SPDIFRX
+   tristate "STM32 S/PDIF receiver (SPDIFRX) support"
+   depends on ARCH_STM32 || COMPILE_TEST
+   depends on SND_SOC
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   select SND_SOC_SPDIF
+   help
+ Say Y if you want to enable S/PDIF capture for STM32
+
 endmenu
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
index 386ce4b..c6a8e72 100644
--- a/sound/soc/stm/Makefile
+++ b/sound/soc/stm/Makefile
@@ -4,3 +4,7 @@ obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai-sub.o
 
 snd-soc-stm32-sai-objs := stm32_sai.o
 obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai.o
+
+# SPDIFRX
+snd-soc-stm32-spdifrx-objs := stm32_spdifrx.o
+obj-$(CONFIG_SND_SOC_STM32_SPDIFRX) += snd-soc-stm32-spdifrx.o
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
new file mode 100644
index 000..4e4250b
--- /dev/null
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -0,0 +1,998 @@
+/*
+ * STM32 ALSA SoC Digital Audio Interface (SPDIF-rx) driver.
+ *
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Olivier Moysan <olivier.moy...@st.com> for STMicroelectronics.
+ *
+ * License terms: GPL V2.0.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
more
+ * details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+/* SPDIF-rx Register Map */
+#define STM32_SPDIFRX_CR   0x00
+#define STM32_SPDIFRX_IMR  0x04
+#define STM32_SPDIFRX_SR   0x08
+#define STM32_SPDIFRX_IFCR 0x0C
+#define STM32_SPDIFRX_DR   0x10
+#define STM32_SPDIFRX_CSR  0x14
+#define STM32_SPDIFRX_DIR  0x18
+
+/* Bit definition for SPDIF_CR register */
+#define SPDIFRX_CR_SPDIFEN_SHIFT   0
+#define SPDIFRX_CR_SPDIFEN_MASKGENMASK(1, SPDIFRX_CR_SPDIFEN_SHIFT)
+#define SPDIFRX_CR_SPDIFENSET(x)   ((x) << SPDIFRX_CR_SPDIFEN_SHIFT)
+
+#define SPDIFRX_CR_RXDMAEN BIT(2)
+#define SPDIFRX_CR_RXSTEO  BIT(3)
+
+#define SPDIFRX_CR_DRFMT_SHIFT 4
+#define SPDIFRX_CR_DRFMT_MASK  GENMASK(5, SPDIFRX_CR_DRFMT_SHIFT)
+#define SPDIFRX_CR_DRFMTSET(x) ((x) << SPDIFRX_CR_DRFMT_SHIFT)
+
+#define SPDIFRX_CR_PMSKBIT(6)
+#define SPDIFRX_CR_VMSKBIT(7)
+#define SPDIFRX_CR_CUMSK   BIT(8)
+#define SPDIFRX_CR_PTMSK   BIT(9)
+#define SPDIFRX_CR_CBDMAEN BIT(10)
+#define SPDIFRX_CR_CHSEL_SHIFT 11
+#define SPDIFRX_CR_CHSEL   BIT(SPDIFRX_CR_CHSEL_SHIFT)
+
+#define SPDIFRX_CR_NBTR_SHIFT  12
+#define SPDIFRX_CR_NBTR_MASK   GENMASK(13, SPDIFRX_CR_NBTR_SHIFT)
+#define SPDIFRX_CR_NBTRSET(x)  ((x) << SPDIFRX_CR_NBTR_SHIFT)
+
+#define SPDIFRX_CR_WFA BIT(14)
+
+#define SPDIFRX_CR_INSEL_SHIFT 16
+#define SPDIFRX_CR_INSEL_MASK  GENMASK(18, PDIFRX_CR_INSEL_SHIFT)
+#define SPDIFRX_CR_INSELSET(x) ((x) << SPDIFRX_CR_INSEL_SHIFT)
+
+#define SPDIFRX_CR_CKSEN_SHIFT 20
+#define SPDIFRX_CR_CKSEN   BIT(20)
+#define SPDIFRX_CR_CKSBKPENBIT(21)
+
+/* Bit definition for SPDIFRX_IMR register */
+#define SPDIFRX_IMR_RXNEI  BIT(0)
+#define SPDIFRX_IMR_CSRNEIEBIT(1)
+#define SPDIFRX_IMR_PERRIE BIT(2)
+#define SPDIFRX_IMR_OVRIE  BIT(3)
+#define SPDIFRX_IMR_SBLKIE BIT(4)
+#define SPDIFRX_IMR_SYNCDIEBIT(5)
+#define SPDIFRX_IMR_IFEIE  BIT(6)
+
+#define SPDIFRX_XIMR_MASK  GENMASK(6, 0)
+
+/* Bit definition for SPDIFRX_SR register */
+#define SPDIFRX_SR_RXNEBIT(0)
+#define SPDIFRX_SR_CSRNE   BIT(1)
+#define SPDIFRX_SR_PERRBIT(2)
+#define SPDIFRX_SR_OVR BIT(3)
+#define SPDIFRX_SR_SBD BIT(4)
+#define SPDIFRX_SR_SYNCD   BIT(5)
+#define SPDIFRX_SR_FERRBIT(6)
+#define SPDIFRX_SR_SERRBIT(7)
+#define SPDIFRX_SR_TERRBIT(8)
+
+#define SPDIFRX_SR_WIDTH5_SHIFT16
+#define SPDIFRX_SR_WIDTH5_MAS

[PATCH 1/2] dt-bindings: Document the STM32 SPDIFRX interface

2017-06-16 Thread olivier moysan
This adds documentation of device tree bindings for the
STM32 SPDIFRX interface.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 .../devicetree/bindings/sound/st,stm32-spdifrx.txt | 56 ++
 1 file changed, 56 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt
new file mode 100644
index 000..33826f2
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt
@@ -0,0 +1,56 @@
+STMicroelectronics STM32 S/PDIF receiver (SPDIFRX).
+
+The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with
+IEC-60958 and IEC-61937.
+
+Required properties:
+  - compatible: should be "st,stm32h7-spdifrx"
+  - reg: cpu DAI IP base address and size
+  - clocks: must contain an entry for kclk (used as S/PDIF signal reference)
+  - clock-names: must contain "kclk"
+  - interrupts: cpu DAI interrupt line
+  - dmas: DMA specifiers for audio data DMA and iec control flow DMA
+See STM32 DMA bindings, Documentation/devicetree/bindings/dma/stm32-dma.txt
+  - dma-names: two dmas have to be defined, "rx" and "rx-ctrl"
+
+Optional properties:
+  - resets: Reference to a reset controller asserting the SPDIFRX
+
+The device node should contain one 'port' child node with one child 'endpoint'
+node, according to the bindings defined in Documentation/devicetree/bindings/
+graph.txt.
+
+Example:
+spdifrx: spdifrx@40004000 {
+   compatible = "st,stm32h7-spdifrx";
+   reg = <0x40004000 0x400>;
+   clocks = < SPDIFRX_CK>;
+   clock-names = "kclk";
+   interrupts = <97>;
+   dmas = < 2 93 0x400 0x0>,
+  < 3 94 0x400 0x0>;
+   dma-names = "rx", "rx-ctrl";
+   pinctrl-0 = <_pins>;
+   pinctrl-names = "default";
+
+   spdifrx_port: port {
+   cpu_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   };
+   };
+};
+
+spdif_in: spdif-in {
+   compatible = "linux,spdif-dir";
+
+   codec_port: port {
+   codec_endpoint: endpoint {
+   remote-endpoint = <_endpoint>;
+   };
+   };
+};
+
+soundcard {
+   compatible = "audio-graph-card";
+   dais = <_port>;
+};
-- 
1.9.1



[PATCH 0/2] ASoC: stm32: add SPDIFRX driver

2017-06-16 Thread olivier moysan
This patch-set handles the SPDIFRX on STM32 platforms.

The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with
IEC-60958 and IEC-61937 standards.

SPDIFRX uses two DMA channels:
- one DMA channel for S/PDIF data stream.
- one DMA channel for control flow (channel status and user data bits).

DMA is used for control flow instead of interrupts to get better performances,
as channel status and user data are retrieved byte per byte.

Note: This patch-set depends on "change SAI configuration flag" patch,
which introduces a change on Kconfig file.

olivier moysan (2):
  dt-bindings: Document the STM32 SPDIFRX interface
  ASoC: stm32: Add SPDIFRX support

 .../devicetree/bindings/sound/st,stm32-spdifrx.txt |  56 ++
 sound/soc/stm/Kconfig  |  10 +
 sound/soc/stm/Makefile |   4 +
 sound/soc/stm/stm32_spdifrx.c  | 998 +
 sound/soc/stm/stm32_spdifrx.h  | 224 +
 5 files changed, 1292 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt
 create mode 100644 sound/soc/stm/stm32_spdifrx.c
 create mode 100644 sound/soc/stm/stm32_spdifrx.h

-- 
1.9.1



[PATCH 1/1] ASoC: stm32: change configuration flag

2017-06-19 Thread olivier moysan
Use a specific flag for SAI and I2S interfaces,
instead of common flag.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/Kconfig  | 19 ---
 sound/soc/stm/Makefile |  6 +++---
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index a6372de..23600a5 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -1,8 +1,21 @@
-menuconfig SND_SOC_STM32
-   tristate "STMicroelectronics STM32 SOC audio support"
+menu "STMicroelectronics STM32 SOC audio support"
+
+config SND_SOC_STM32_SAI
+   tristate "STM32 SAI interface (Serial Audio Interface) support"
depends on ARCH_STM32 || COMPILE_TEST
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
help
- Say Y if you want to enable ASoC support for STM32
+ Say Y if you want to enable SAI for STM32
+
+config SND_SOC_STM32_I2S
+   tristate "STM32 I2S interface (SPI/I2S block) support"
+   depends on ARCH_STM32 || COMPILE_TEST
+   depends on SND_SOC
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   help
+ Say Y if you want to enable I2S for STM32
+
+endmenu
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
index 8251931..4140c67 100644
--- a/sound/soc/stm/Makefile
+++ b/sound/soc/stm/Makefile
@@ -1,10 +1,10 @@
 # SAI
 snd-soc-stm32-sai-sub-objs := stm32_sai_sub.o
-obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o
+obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai-sub.o
 
 snd-soc-stm32-sai-objs := stm32_sai.o
-obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o
+obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai.o
 
 # I2S
 snd-soc-stm32-i2s-objs := stm32_i2s.o
-obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-i2s.o
+obj-$(CONFIG_SND_SOC_STM32_I2S) += snd-soc-stm32-i2s.o
-- 
1.9.1



Re: [PATCH 2/7] ASoC: stm32: change SAI configuration flag

2017-06-19 Thread Olivier MOYSAN
Hello Mark,

On 06/16/2017 07:49 PM, Mark Brown wrote:
> On Fri, Jun 16, 2017 at 02:15:29PM +0200, olivier moysan wrote:
>> Use a specific flag for SAI interface instead
>> of common stm32 asoc flag.
> 
> This doesn't apply against current code, please check and resend.
> 

I pushed this patch-set on stm topic branch.
I resend a patch on next, to fix the merge issue.

Best regards
olivier


Re: [PATCH v3 1/2] ASoC: stm32: add bindings for SAI

2017-05-02 Thread Olivier MOYSAN
Hello Rob,

On 04/28/2017 10:53 PM, Rob Herring wrote:
> On Mon, Apr 10, 2017 at 05:19:55PM +0200, olivier moysan wrote:
>> This patch adds documentation of device tree bindings for the
>> STM32 SAI ASoC driver.
>>
>> Signed-off-by: olivier moysan <olivier.moy...@st.com>
>> ---
>>  .../devicetree/bindings/sound/st,stm32-sai.txt | 89 
>> ++
>>  1 file changed, 89 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-sai.txt
>>
>> diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt 
>> b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
>> new file mode 100644
>> index 000..c59a3d7
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
>> @@ -0,0 +1,89 @@
>> +STMicroelectronics STM32 Serial Audio Interface (SAI).
>
> [...]
>
>> +sai1b: audio-controller@40015824 {
>> +#sound-dai-cells = <0>;
>> +compatible = "st,stm32-sai-sub-b";
>> +reg = <0x40015824 0x1C>;
>> +clocks = < 1 CLK_SAI2>;
>> +clock-names = "sai_ck";
>> +dmas = < 5 0 0x400 0x0>;
>> +dma-names = "tx";
>> +pinctrl-names = "default";
>> +pinctrl-0 = <_sai1b>;
>> +
>> +ports {
>> +#address-cells = <1>;
>> +#size-cells = <0>;
>> +
>> +sai1b_port: port@0 {
>> +reg = <0>;
>> +cpu_endpoint: endpoint {
>> +remote-endpoint = <_endpoint>;
>> +audio-graph-card,format = "i2s";
>> +audio-graph-card,bitclock-master = 
>> <_endpoint>;
>> +audio-graph-card,frame-master = 
>> <_endpoint>;
>
> These property names are wrong.
>

I have taken into account this comment (and previous ones).
They will be included in next update of this patch set.

>> +};
>> +};
>> +};
>> +};
>> +};
>> +
>> +audio-codec {
>> +codec_port: port {
>> +codec_endpoint: endpoint {
>> +remote-endpoint = <_endpoint>;
>> +};
>> +};
>> +};
>> --
>> 1.9.1
>>

Best regards
Olivier


[PATCH 1/3] ASoC: stm32: fix sync property description in SAI bindings

2017-11-22 Thread Olivier Moysan
SAI sync property must be described in SAI subnodes
section, as it is a property of child node.
This patch fixes commit 14f0e5f8d97e632695d92f41f2e91d10d8005d47
"ASoC: stm32: Add synchronization to SAI bindings".

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 Documentation/devicetree/bindings/sound/st,stm32-sai.txt | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
index 1f9cd70..b1acc1a 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -20,11 +20,6 @@ Required properties:
 
 Optional properties:
   - resets: Reference to a reset controller asserting the SAI
-  - st,sync: specify synchronization mode.
-   By default SAI sub-block is in asynchronous mode.
-   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.
 
 SAI subnodes:
 Two subnodes corresponding to SAI sub-block instances A et B can be defined.
@@ -44,6 +39,13 @@ SAI subnodes required properties:
   - pinctrl-names: should contain only value "default"
   - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
 
+SAI subnodes Optional properties:
+  - st,sync: specify synchronization mode.
+   By default SAI sub-block is in asynchronous mode.
+   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.
+
 The device node should contain one 'port' child node with one child 'endpoint'
 node, according to the bindings defined in Documentation/devicetree/bindings/
 graph.txt.
-- 
1.9.1



[PATCH 0/3] ASoC: stm32: sai: fixes related to synchro feature

2017-11-22 Thread Olivier Moysan
Fix sai binding and simplify code related to synchro feature.
This change allows to remove stm32_sai_remove() function
and use devm_of_platform_populate().

Olivier Moysan (3):
  ASoC: stm32: fix sync property description in SAI bindings
  ASoC: stm32: sai: simplify sync modes management
  ASoC: stm32: sai: use devm_of_platform_populate()

 .../devicetree/bindings/sound/st,stm32-sai.txt |  12 ++-
 sound/soc/stm/stm32_sai.c  | 114 -
 2 files changed, 29 insertions(+), 97 deletions(-)

-- 
1.9.1



[PATCH 2/3] ASoC: stm32: sai: simplify sync modes management

2017-11-22 Thread Olivier Moysan
Use function of_find_device_by_node() to retrieve SAI
synchro provider device and private data.
This allows to remove registration of probed SAI
in a linked list.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai.c | 105 ++
 1 file changed, 22 insertions(+), 83 deletions(-)

diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index d6f71a3..0a1f064 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -28,16 +28,6 @@
 
 #include "stm32_sai.h"
 
-static LIST_HEAD(sync_providers);
-static DEFINE_MUTEX(sync_mutex);
-
-struct sync_provider {
-   struct list_head link;
-   struct device_node *node;
-   int  (*sync_conf)(void *data, int synco);
-   void *data;
-};
-
 static const struct stm32_sai_conf stm32_sai_conf_f4 = {
.version = SAI_STM32F4,
 };
@@ -70,9 +60,8 @@ static int stm32_sai_sync_conf_client(struct stm32_sai_data 
*sai, int synci)
return 0;
 }
 
-static int stm32_sai_sync_conf_provider(void *data, int synco)
+static int stm32_sai_sync_conf_provider(struct stm32_sai_data *sai, int synco)
 {
-   struct stm32_sai_data *sai = (struct stm32_sai_data *)data;
u32 prev_synco;
int ret;
 
@@ -103,73 +92,34 @@ static int stm32_sai_sync_conf_provider(void *data, int 
synco)
return 0;
 }
 
-static int stm32_sai_set_sync_provider(struct device_node *np, int synco)
+static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,
+ struct device_node *np_provider,
+ int synco, int synci)
 {
-   struct sync_provider *provider;
+   struct platform_device *pdev = of_find_device_by_node(np_provider);
+   struct stm32_sai_data *sai_provider;
int ret;
 
-   mutex_lock(_mutex);
-   list_for_each_entry(provider, _providers, link) {
-   if (provider->node == np) {
-   ret = provider->sync_conf(provider->data, synco);
-   mutex_unlock(_mutex);
-   return ret;
-   }
+   if (!pdev) {
+   dev_err(_client->pdev->dev,
+   "Device not found for node %s\n", np_provider->name);
+   return -ENODEV;
}
-   mutex_unlock(_mutex);
 
-   /* SAI sync provider not found */
-   return -ENODEV;
-}
-
-static int stm32_sai_set_sync(struct stm32_sai_data *sai,
- struct device_node *np_provider,
- int synco, int synci)
-{
-   int ret;
+   sai_provider = platform_get_drvdata(pdev);
+   if (!sai_provider) {
+   dev_err(_client->pdev->dev,
+   "SAI sync provider data not found\n");
+   return -EINVAL;
+   }
 
/* Configure sync client */
-   stm32_sai_sync_conf_client(sai, synci);
+   ret = stm32_sai_sync_conf_client(sai_client, synci);
+   if (ret < 0)
+   return ret;
 
/* Configure sync provider */
-   ret = stm32_sai_set_sync_provider(np_provider, synco);
-
-   return ret;
-}
-
-static int stm32_sai_sync_add_provider(struct platform_device *pdev,
-  void *data)
-{
-   struct sync_provider *sp;
-
-   sp = devm_kzalloc(>dev, sizeof(*sp), GFP_KERNEL);
-   if (!sp)
-   return -ENOMEM;
-
-   sp->node = of_node_get(pdev->dev.of_node);
-   sp->data = data;
-   sp->sync_conf = _sai_sync_conf_provider;
-
-   mutex_lock(_mutex);
-   list_add(>link, _providers);
-   mutex_unlock(_mutex);
-
-   return 0;
-}
-
-static void stm32_sai_sync_del_provider(struct device_node *np)
-{
-   struct sync_provider *sp;
-
-   mutex_lock(_mutex);
-   list_for_each_entry(sp, _providers, link) {
-   if (sp->node == np) {
-   list_del(>link);
-   of_node_put(sp->node);
-   break;
-   }
-   }
-   mutex_unlock(_mutex);
+   return stm32_sai_sync_conf_provider(sai_provider, synco);
 }
 
 static int stm32_sai_probe(struct platform_device *pdev)
@@ -179,7 +129,6 @@ static int stm32_sai_probe(struct platform_device *pdev)
struct reset_control *rst;
struct resource *res;
const struct of_device_id *of_id;
-   int ret;
 
sai = devm_kzalloc(>dev, sizeof(*sai), GFP_KERNEL);
if (!sai)
@@ -231,27 +180,17 @@ static int stm32_sai_probe(struct platform_device *pdev)
reset_control_deassert(rst);
}
 
-   ret = stm32_sai_sync_add_provider(pdev, sai);
-   if (ret < 0)
-   return ret;
-   sai->set_sync = _sai_set_sync;
-
sai->pdev = pdev;
+   sai->set_sync = _sai_set_sync;
platform_set_drvdata(pdev, sai);
 
-   ret = of_pla

[PATCH 3/3] ASoC: stm32: sai: use devm_of_platform_populate()

2017-11-22 Thread Olivier Moysan
Use devm_of_platform_populate() instead of of_platform_depopulate()
to simplify driver code.

Signed-off-by: Benjamin Gaignard <benjamin.gaign...@linaro.org>
Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai.c | 11 +--
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index 0a1f064..d743b7d 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -124,7 +124,6 @@ static int stm32_sai_set_sync(struct stm32_sai_data 
*sai_client,
 
 static int stm32_sai_probe(struct platform_device *pdev)
 {
-   struct device_node *np = pdev->dev.of_node;
struct stm32_sai_data *sai;
struct reset_control *rst;
struct resource *res;
@@ -184,14 +183,7 @@ static int stm32_sai_probe(struct platform_device *pdev)
sai->set_sync = _sai_set_sync;
platform_set_drvdata(pdev, sai);
 
-   return of_platform_populate(np, NULL, NULL, >dev);
-}
-
-static int stm32_sai_remove(struct platform_device *pdev)
-{
-   of_platform_depopulate(>dev);
-
-   return 0;
+   return devm_of_platform_populate(>dev);
 }
 
 MODULE_DEVICE_TABLE(of, stm32_sai_ids);
@@ -202,7 +194,6 @@ static int stm32_sai_remove(struct platform_device *pdev)
.of_match_table = stm32_sai_ids,
},
.probe = stm32_sai_probe,
-   .remove = stm32_sai_remove,
 };
 
 module_platform_driver(stm32_sai_driver);
-- 
1.9.1



[RFC PATCH 1/2] ASoC: add support of mclk clock providers in wm8894 driver

2017-12-14 Thread Olivier Moysan
Wolfson wm8994 codec bindings exposes MCLK1 and MCLK1 clocks.
This patch adds support of MCLK1 and MCLK2 in mfd driver.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 drivers/mfd/wm8994-core.c| 9 +
 include/linux/mfd/wm8994/pdata.h | 6 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 953d079..f1ff9d8 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -12,6 +12,7 @@
  *
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -310,6 +311,14 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
if (pdata->ldo[1].enable < 0)
pdata->ldo[1].enable = 0;
 
+   pdata->mclk1 = devm_clk_get(wm8994->dev, "MCLK1");
+   if (IS_ERR(pdata->mclk1))
+   pdata->mclk1 = NULL;
+
+   pdata->mclk2 = devm_clk_get(wm8994->dev, "MCLK2");
+   if (IS_ERR(pdata->mclk2))
+   pdata->mclk2 = NULL;
+
return 0;
 }
 #else
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index 90c6052..8037d26 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -233,6 +233,12 @@ struct wm8994_pdata {
 * GPIO for the IRQ pin if host only supports edge triggering
 */
int irq_gpio;
+
+   /* MCLK1 clock provider */
+   struct clk *mclk1;
+
+   /* MCLK2 clock provider */
+   struct clk *mclk2;
 };
 
 #endif
-- 
1.9.1



[RFC PATCH 0/2] select master clock in wm8994 driver based on DT clocks configuration

2017-12-14 Thread Olivier Moysan
Hello,

This RFC follows a previous RFC related to master clock issues with Wolfson 
wm8994 codec:
http://mailman.alsa-project.org/pipermail/alsa-devel/2017-March/118834.html

This RFC provides a new proposal regarding master clock selection in wm8994 
driver.
Below is a reminder of the problem:

Use case:
CPU DAI and codec are managed through audio graph card.
Wolson codec wm8994 is set as slave of CPU DAI and CPU DAI feeds codec with 
master clock.
Master clock is derived from mclk-fs property and provided to CPU DAI and codec 
through snd_soc_dai_set_sysclk API. 

Analysis:
The audio graph card sets clock id to 0, while wm8994 codec driver expects a 
clock id in the range [1..4]. (MCLK1, MCLK2 ..)

Proposal:
Wolfson wm8994 codec bindings exposes MCLK1 and MCLK1 clocks.
It seems that these clocks are not supported in wm8994 driver, yet.
First patch adds support of these clocks.

Second patch sets master clock according to clocks provided in DT.
The patch assumes that MCLK1 and MCLK2 are linked to aif1 and aif2 interfaces 
respectively.
If MCLKx is defined, is it used as source clock for aifx interface.
Otherwise clock id parameter is used as usual. 
By default clock rate is requested from clock framework. 
This is not convenient, when mclk clock frequency is computed for mclk-fs ratio,
as codec set_sysclk() is called before cpu set_sysclk() callback.
In this case frequency provided by set_sysclk() must be used.
So, if MCLKx rate is 0, frequency parameter provided by wm8994_set_dai_sysclk() 
is used.

I have a limited view of potential side effects here, so any comments are 
welcome.
If some adaptations are required to make this change more generic, please let 
me know.

Regards
Olivier

Olivier Moysan (2):
  ASoC: add support of mclk clock providers in wm8894 driver
  ASoC: select sysclk clock from mlck clock provider in wm8994 driver

 drivers/mfd/wm8994-core.c|  9 +
 include/linux/mfd/wm8994/pdata.h |  6 ++
 sound/soc/codecs/wm8994.c| 20 +++-
 3 files changed, 34 insertions(+), 1 deletion(-)

-- 
1.9.1



[RFC PATCH 2/2] ASoC: select sysclk clock from mlck clock provider in wm8994 driver

2017-12-14 Thread Olivier Moysan
When defined in device tree, MCLK1 and MCLK2 are used
as sysclk for aif1 and aif2 interfaces respectively.
If clock rate is let 0, the frequency provided by
wm8994_set_dai_sysclk() is used instead.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/soc/codecs/wm8994.c | 20 +++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 21ffd64..7a84e37 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -2376,18 +2377,35 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai 
*dai,
 {
struct snd_soc_codec *codec = dai->codec;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+   struct wm8994 *control = wm8994->wm8994;
+   struct wm8994_pdata *pdata = >pdata;
+   unsigned long rate;
int i;
 
switch (dai->id) {
case 1:
+   if (pdata->mclk1) {
+   rate = clk_get_rate(pdata->mclk1);
+   if (rate)
+   freq = (unsigned int)rate;
+   clk_id = WM8994_SYSCLK_MCLK1;
+   }
+   break;
case 2:
+   if (pdata->mclk2) {
+   rate = clk_get_rate(pdata->mclk2);
+   if (rate)
+   freq = (unsigned int)rate;
+   clk_id = WM8994_SYSCLK_MCLK2;
+   }
break;
-
default:
/* AIF3 shares clocking with AIF1/2 */
return -EINVAL;
}
 
+   dev_info(codec->dev, "%s:.clock id %d\n", __func__, clk_id);
+
switch (clk_id) {
case WM8994_SYSCLK_MCLK1:
wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1;
-- 
1.9.1



Re: [RFC PATCH 2/2] ASoC: select sysclk clock from mlck clock provider in wm8994 driver

2017-12-15 Thread Olivier MOYSAN
Hello Mark,

Thanks for your comment.

On 12/14/2017 06:36 PM, Mark Brown wrote:
> On Thu, Dec 14, 2017 at 05:53:58PM +0100, Olivier Moysan wrote:
>> When defined in device tree, MCLK1 and MCLK2 are used
>> as sysclk for aif1 and aif2 interfaces respectively.
> 
> That's not a valid assumption as far as I remember?  The AIFs can use
> either MCLK depending on the system configuration I think.
> 

You are right. wm8994 allows to select either MCLK for each AIF.
 From this point of view, the current patch is too limiting.
MCLK information in DT allows to enforce MCLK use, but an additionnal 
information is required to determine AIF MCLK assignment.
Available properties in codec DAI node, such as clocks property, cannot 
help here.

Maybe a DAPM linked to a control is a better way to select AIF source,
When source is not provided by clk_id in wm8994_set_dai_sysclk().
In this case, wm8994_set_dai_sysclk() would only have to check
if clock source is not already set.

Please let me know if this option sounds better to you.

>> If clock rate is let 0, the frequency provided by
>> wm8994_set_dai_sysclk() is used instead.
> 
> I'd expect this the other way around, if we didn't specify a frequency
> then read it from the input otherwise try to use clk_set_rate() to
> propagate things up.
> 

If I implement a control to select the AIF source, I will drop the code
related to mclk clock provider.

Regards
Olivier


Re: [RFC PATCH 2/2] ASoC: select sysclk clock from mlck clock provider in wm8994 driver

2017-12-20 Thread Olivier MOYSAN
Hello Mark,

On 12/19/2017 10:35 AM, Mark Brown wrote:
> On Fri, Dec 15, 2017 at 03:15:22PM +0000, Olivier MOYSAN wrote:
> 
>> You are right. wm8994 allows to select either MCLK for each AIF.
>>   From this point of view, the current patch is too limiting.
>> MCLK information in DT allows to enforce MCLK use, but an additionnal
>> information is required to determine AIF MCLK assignment.
>> Available properties in codec DAI node, such as clocks property, cannot
>> help here.
> 
>> Maybe a DAPM linked to a control is a better way to select AIF source,
>> When source is not provided by clk_id in wm8994_set_dai_sysclk().
>> In this case, wm8994_set_dai_sysclk() would only have to check
>> if clock source is not already set.
> 
>> Please let me know if this option sounds better to you.
> 
> What are you trying to accomplish here?  You appear to be trying to move
> the system clocking configuration from the machine driver to the CODEC
> which is not how things are supposed to work.
> 

As a generic machine, simple or audio graph cards are not able to manage 
codec clock muxing.
If we exclude the management of muxing through codec controls,
the remaining solution is to handle it fully through clock framework.
The current patch only supports a limited range of muxing capabilities 
of the codec.
To have a full management of the muxing, I think it is necessary to add
a device tree node for each codec interface and to define an aif clock 
in these nodes.
Then parent clock assignment of these aif clocks would allow to handle 
the muxing.

Please, let me known if is this the right direction for you.

BRs
olivier


[PATCH 2/2] ASoC: stm32: spdifrx: fix control DMA error management

2017-11-06 Thread Olivier Moysan
Fix DMA channel request error handling.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_spdifrx.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index d7dbe84..b9bdefc 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -392,6 +392,12 @@ static int stm32_spdifrx_dma_ctrl_register(struct device 
*dev,
 {
int ret;
 
+   spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl");
+   if (IS_ERR(spdifrx->ctrl_chan)) {
+   dev_err(dev, "dma_request_slave_channel failed\n");
+   return PTR_ERR(spdifrx->ctrl_chan);
+   }
+
spdifrx->dmab = devm_kzalloc(dev, sizeof(struct snd_dma_buffer),
 GFP_KERNEL);
if (!spdifrx->dmab)
@@ -406,12 +412,6 @@ static int stm32_spdifrx_dma_ctrl_register(struct device 
*dev,
return ret;
}
 
-   spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl");
-   if (!spdifrx->ctrl_chan) {
-   dev_err(dev, "dma_request_slave_channel failed\n");
-   return -EINVAL;
-   }
-
spdifrx->slave_config.direction = DMA_DEV_TO_MEM;
spdifrx->slave_config.src_addr = (dma_addr_t)(spdifrx->phys_addr +
 STM32_SPDIFRX_CSR);
@@ -423,7 +423,6 @@ static int stm32_spdifrx_dma_ctrl_register(struct device 
*dev,
 >slave_config);
if (ret < 0) {
dev_err(dev, "dmaengine_slave_config returned error %d\n", ret);
-   dma_release_channel(spdifrx->ctrl_chan);
spdifrx->ctrl_chan = NULL;
}
 
@@ -962,7 +961,7 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
return 0;
 
 error:
-   if (spdifrx->ctrl_chan)
+   if (!IS_ERR(spdifrx->ctrl_chan))
dma_release_channel(spdifrx->ctrl_chan);
if (spdifrx->dmab)
snd_dma_free_pages(spdifrx->dmab);
-- 
1.9.1



[PATCH 1/2] ASoC: stm32: spdifrx: fix 16 bits capture

2017-11-06 Thread Olivier Moysan
Change DMA bus width to manage properly 16 bits packed format.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_spdifrx.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index 84cc567..d7dbe84 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -750,17 +750,21 @@ static int stm32_spdifrx_hw_params(struct 
snd_pcm_substream *substream,
switch (data_size) {
case 16:
fmt = SPDIFRX_DRFMT_PACKED;
-   spdifrx->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
case 32:
fmt = SPDIFRX_DRFMT_LEFT;
-   spdifrx->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
default:
dev_err(>pdev->dev, "Unexpected data format\n");
return -EINVAL;
}
 
+   /*
+* Set buswidth to 4 bytes for all data formats.
+* Packed format: transfer 2 x 2 bytes samples
+* Left format: transfer 1 x 3 bytes samples + 1 dummy byte
+*/
+   spdifrx->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
snd_soc_dai_init_dma_data(cpu_dai, NULL, >dma_params);
 
return regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR,
-- 
1.9.1



[PATCH 0/2] ASoC: stm32: spdifrx: DMA management fixes

2017-11-06 Thread Olivier Moysan
This patch-set gathers DMA management fixes for STM32 SPDIFRX.

Olivier Moysan (2):
  ASoC: stm32: spdifrx: fix 16 bits capture
  ASoC: stm32: spdifrx: fix control DMA error management

 sound/soc/stm/stm32_spdifrx.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

-- 
1.9.1



Re: [INTERNAL][PATCH 4/7] ASoC: stm32: sai: fix stop management in isr

2017-11-02 Thread Olivier MOYSAN
Hello Takashi,

Sorry for late answer. I was OoO.
Ok, I will add a protection on sai->substream accesses.

Best regards
Olivier


On 10/26/2017 05:32 PM, Takashi Iwai wrote:
> On Thu, 19 Oct 2017 15:03:20 +0200,
> Olivier Moysan wrote:
>>
>> Add check on substream validity.
>>
>> Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
>> ---
>>   sound/soc/stm/stm32_sai_sub.c | 12 
>>   1 file changed, 8 insertions(+), 4 deletions(-)
>>
>> diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
>> index 2af397d..815ef10 100644
>> --- a/sound/soc/stm/stm32_sai_sub.c
>> +++ b/sound/soc/stm/stm32_sai_sub.c
>> @@ -184,7 +184,6 @@ static bool stm32_sai_sub_writeable_reg(struct device 
>> *dev, unsigned int reg)
>>   static irqreturn_t stm32_sai_isr(int irq, void *devid)
>>   {
>>  struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid;
>> -struct snd_pcm_substream *substream = sai->substream;
>>  struct platform_device *pdev = sai->pdev;
>>  unsigned int sr, imr, flags;
>>  snd_pcm_state_t status = SNDRV_PCM_STATE_RUNNING;
>> @@ -199,6 +198,11 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
>>  regmap_update_bits(sai->regmap, STM_SAI_CLRFR_REGX, SAI_XCLRFR_MASK,
>> SAI_XCLRFR_MASK);
>>   
>> +if (!sai->substream) {
>> +dev_err(>dev, "Device stopped. Spurious IRQ 0x%x\n", sr);
>> +return IRQ_NONE;
>> +}
>> +
>>  if (flags & SAI_XIMR_OVRUDRIE) {
>>  dev_err(>dev, "IRQ %s\n",
>>  STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun");
>> @@ -227,9 +231,9 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
>>  }
>>   
>>  if (status != SNDRV_PCM_STATE_RUNNING) {
>> -snd_pcm_stream_lock(substream);
>> -snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
>> -snd_pcm_stream_unlock(substream);
>> +snd_pcm_stream_lock(sai->substream);
>> +snd_pcm_stop(sai->substream, SNDRV_PCM_STATE_XRUN);
>> +snd_pcm_stream_unlock(sai->substream);
> 
> Actually changing to sai->substream opens a race, so this chunk is a
> bad move, at least.  We have no protection of sai->substream in this
> context, thus it can hit a NULL dereference...
> 
> 
> thanks,
> 
> Takashi
> 

[PATCH 2/2] ASoC: add mclk-fs support to audio graph card

2017-11-09 Thread Olivier Moysan
Add mclk-fs support to audio graph card
as it was previously implemented in simple card.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/soc/generic/audio-graph-card.c | 47 ++--
 1 file changed, 39 insertions(+), 8 deletions(-)

diff --git a/sound/soc/generic/audio-graph-card.c 
b/sound/soc/generic/audio-graph-card.c
index 488c52f..1b61642 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -29,7 +29,9 @@ struct graph_card_data {
struct graph_dai_props {
struct asoc_simple_dai cpu_dai;
struct asoc_simple_dai codec_dai;
+   unsigned int mclk_fs;
} *dai_props;
+   unsigned int mclk_fs;
struct snd_soc_dai_link *dai_link;
struct gpio_desc *pa_gpio;
 };
@@ -95,9 +97,43 @@ static void asoc_graph_card_shutdown(struct 
snd_pcm_substream *substream)
asoc_simple_card_clk_disable(_props->codec_dai);
 }
 
+static int asoc_graph_card_hw_params(struct snd_pcm_substream *substream,
+struct snd_pcm_hw_params *params)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_dai *codec_dai = rtd->codec_dai;
+   struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+   struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+   struct graph_dai_props *dai_props = graph_priv_to_props(priv, rtd->num);
+   unsigned int mclk, mclk_fs = 0;
+   int ret = 0;
+
+   if (priv->mclk_fs)
+   mclk_fs = priv->mclk_fs;
+   else if (dai_props->mclk_fs)
+   mclk_fs = dai_props->mclk_fs;
+
+   if (mclk_fs) {
+   mclk = params_rate(params) * mclk_fs;
+   ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+SND_SOC_CLOCK_IN);
+   if (ret && ret != -ENOTSUPP)
+   goto err;
+
+   ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
+SND_SOC_CLOCK_OUT);
+   if (ret && ret != -ENOTSUPP)
+   goto err;
+   }
+   return 0;
+err:
+   return ret;
+}
+
 static const struct snd_soc_ops asoc_graph_card_ops = {
.startup = asoc_graph_card_startup,
.shutdown = asoc_graph_card_shutdown,
+   .hw_params = asoc_graph_card_hw_params,
 };
 
 static int asoc_graph_card_dai_init(struct snd_soc_pcm_runtime *rtd)
@@ -146,10 +182,7 @@ static int asoc_graph_card_dai_link_of(struct device_node 
*cpu_port,
if (ret < 0)
goto dai_link_of_err;
 
-   /*
-* we need to consider "mclk-fs" around here
-* see simple-card
-*/
+   of_property_read_u32(rcpu_ep, "mclk-fs", _props->mclk_fs);
 
ret = asoc_simple_card_parse_graph_cpu(cpu_ep, dai_link);
if (ret < 0)
@@ -217,10 +250,8 @@ static int asoc_graph_card_parse_of(struct graph_card_data 
*priv)
if (ret < 0)
return ret;
 
-   /*
-* we need to consider "mclk-fs" around here
-* see simple-card
-*/
+   /* Factor to mclk, used in hw_params() */
+   of_property_read_u32(node, "mclk-fs", >mclk_fs);
 
of_for_each_phandle(, rc, node, "dais", NULL, 0) {
ret = asoc_graph_card_dai_link_of(it.node, priv, idx++);
-- 
1.9.1



[PATCH 0/2] ASoC: add mclk-fs support to audio graph card

2017-11-09 Thread Olivier Moysan
The aim of these patches is to port mclk-fs property to audio graph card, 
as originally implemented in simple card.

Olivier Moysan (2):
  ASoC: add mclk-fs to audio graph card binding
  ASoC: add mclk-fs support to audio graph card

 .../devicetree/bindings/sound/audio-graph-card.txt |  1 +
 sound/soc/generic/audio-graph-card.c   | 47 ++
 2 files changed, 40 insertions(+), 8 deletions(-)

-- 
1.9.1



[PATCH 1/2] ASoC: add mclk-fs to audio graph card binding

2017-11-09 Thread Olivier Moysan
Add mclk-fs support to audio graph card
as initially supported in simple card.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 Documentation/devicetree/bindings/sound/audio-graph-card.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/sound/audio-graph-card.txt 
b/Documentation/devicetree/bindings/sound/audio-graph-card.txt
index 6e6720a..d04ea3b 100644
--- a/Documentation/devicetree/bindings/sound/audio-graph-card.txt
+++ b/Documentation/devicetree/bindings/sound/audio-graph-card.txt
@@ -17,6 +17,7 @@ Below are same as Simple-Card.
 - bitclock-master
 - bitclock-inversion
 - frame-inversion
+- mclk-fs
 - dai-tdm-slot-num
 - dai-tdm-slot-width
 - clocks / system-clock-frequency
-- 
1.9.1



[PATCH 1/1] ASoC: stm32: sai: fix warning in stm32_sai_set_config()

2017-11-02 Thread Olivier Moysan
Fix uninitialized warning introduced by
"Move static settings to DAI init" commit
in stm32_sai_set_config() function.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai_sub.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 150ad54..08583b9 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -482,13 +482,13 @@ static int stm32_sai_set_config(struct snd_soc_dai 
*cpu_dai,
cr1_mask = SAI_XCR1_DS_MASK;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
-   cr1 |= SAI_XCR1_DS_SET(SAI_DATASIZE_8);
+   cr1 = SAI_XCR1_DS_SET(SAI_DATASIZE_8);
break;
case SNDRV_PCM_FORMAT_S16_LE:
-   cr1 |= SAI_XCR1_DS_SET(SAI_DATASIZE_16);
+   cr1 = SAI_XCR1_DS_SET(SAI_DATASIZE_16);
break;
case SNDRV_PCM_FORMAT_S32_LE:
-   cr1 |= SAI_XCR1_DS_SET(SAI_DATASIZE_32);
+   cr1 = SAI_XCR1_DS_SET(SAI_DATASIZE_32);
break;
default:
dev_err(cpu_dai->dev, "Data format not supported");
-- 
1.9.1



Re: [RFC PATCH 2/2] ASoC: select sysclk clock from mlck clock provider in wm8994 driver

2017-12-21 Thread Olivier MOYSAN
Hello Mark,

On 12/20/2017 04:50 PM, Mark Brown wrote:
> On Wed, Dec 20, 2017 at 12:42:10PM +0000, Olivier MOYSAN wrote:
> 
>> As a generic machine, simple or audio graph cards are not able to manage
>> codec clock muxing.
>> If we exclude the management of muxing through codec controls,
>> the remaining solution is to handle it fully through clock framework.
>> The current patch only supports a limited range of muxing capabilities
>> of the codec.
>> To have a full management of the muxing, I think it is necessary to add
>> a device tree node for each codec interface and to define an aif clock
>> in these nodes.
>> Then parent clock assignment of these aif clocks would allow to handle
>> the muxing.
> 
> Controlling clocking through a clock API binding would be good, yes.
> That'd solve a bunch of other problems with use of multi-purpose clocks
> for audio as well.
> 

Thanks for your feedback. I will implement this in a patch v2.

BRs


Re: [PATCH 0/3] ASoC: stm32: sai: add support of iec958 controls

2018-05-17 Thread Olivier MOYSAN
Hello Takashi,

On 04/17/2018 01:17 PM, Mark Brown wrote:
> On Tue, Apr 17, 2018 at 08:29:17AM +0000, Olivier MOYSAN wrote:
> 
>> I guess the blocking patch in this patchset is the patch "add IEC958
>> channel status control helper". This patch has been reviewed several
>> times, but did not get a ack so far.
>> If you think these helpers will not be merged, I will reintegrate the
>> corresponding code in stm driver.
>> Please let me know, if I need to prepare a v2 without helpers, or if we
>> can go further in the review of iec helpers patch ?
> 
> I don't mind either way but you're right here, I'm waiting for Takashi
> to review the first patch.  I'd probably be OK with it just integrated
> into the driver if we have to go that way though.
> 

Kind reminder.
Would you have some comments on this patchset ?

Thanks
olivier


[PATCH v2 0/1] ASoC: stm32: sai: add iec958 controls support

2018-06-11 Thread Olivier Moysan
Changes v2:
- Remove iec958 helpers and implement iec958 controls in sai driver 

Olivier Moysan (1):
  ASoC: stm32: sai: add iec958 controls support

 sound/soc/stm/Kconfig |   1 +
 sound/soc/stm/stm32_sai_sub.c | 139 ++
 2 files changed, 128 insertions(+), 12 deletions(-)

-- 
1.9.1



[PATCH v2 1/1] ASoC: stm32: sai: add iec958 controls support

2018-06-11 Thread Olivier Moysan
Add support of iec958 controls for STM32 SAI.

Signed-off-by: Olivier Moysan 
---
 sound/soc/stm/Kconfig |   1 +
 sound/soc/stm/stm32_sai_sub.c | 139 ++
 2 files changed, 128 insertions(+), 12 deletions(-)

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 48f9ddd94016..9b2681397dba 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -6,6 +6,7 @@ config SND_SOC_STM32_SAI
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
+   select SND_PCM_IEC958
help
  Say Y if you want to enable SAI for STM32
 
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index cfeb219e1d78..c4f15ea14197 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -96,7 +96,8 @@
  * @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
+ * @snd_aes_iec958: iec958 data
+ * @ctrl_lock: control lock
  */
 struct stm32_sai_sub_data {
struct platform_device *pdev;
@@ -125,7 +126,8 @@ struct stm32_sai_sub_data {
int slot_mask;
int data_size;
unsigned int spdif_frm_cnt;
-   unsigned char spdif_status_bits[SAI_IEC60958_STATUS_BYTES];
+   struct snd_aes_iec958 iec958;
+   struct mutex ctrl_lock; /* protect resources accessed by controls */
 };
 
 enum stm32_sai_fifo_th {
@@ -184,10 +186,6 @@ 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,
@@ -210,6 +208,49 @@ static bool stm32_sai_sub_writeable_reg(struct device 
*dev, unsigned int reg)
.fast_io = true,
 };
 
+static int snd_pcm_iec958_info(struct snd_kcontrol *kcontrol,
+  struct snd_ctl_elem_info *uinfo)
+{
+   uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+   uinfo->count = 1;
+
+   return 0;
+}
+
+static int snd_pcm_iec958_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uctl)
+{
+   struct stm32_sai_sub_data *sai = snd_kcontrol_chip(kcontrol);
+
+   mutex_lock(>ctrl_lock);
+   memcpy(uctl->value.iec958.status, sai->iec958.status, 4);
+   mutex_unlock(>ctrl_lock);
+
+   return 0;
+}
+
+static int snd_pcm_iec958_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uctl)
+{
+   struct stm32_sai_sub_data *sai = snd_kcontrol_chip(kcontrol);
+
+   mutex_lock(>ctrl_lock);
+   memcpy(sai->iec958.status, uctl->value.iec958.status, 4);
+   mutex_unlock(>ctrl_lock);
+
+   return 0;
+}
+
+static const struct snd_kcontrol_new iec958_ctls = {
+   .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+   SNDRV_CTL_ELEM_ACCESS_VOLATILE),
+   .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+   .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+   .info = snd_pcm_iec958_info,
+   .get = snd_pcm_iec958_get,
+   .put = snd_pcm_iec958_put,
+};
+
 static irqreturn_t stm32_sai_isr(int irq, void *devid)
 {
struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid;
@@ -619,6 +660,59 @@ static void stm32_sai_set_frame(struct snd_soc_dai 
*cpu_dai)
}
 }
 
+static void stm32_sai_init_iec958_status(struct stm32_sai_sub_data *sai)
+{
+   unsigned char *cs = sai->iec958.status;
+
+   cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
+   cs[1] = IEC958_AES1_CON_GENERAL;
+   cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
+   cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | IEC958_AES3_CON_FS_NOTID;
+}
+
+static void stm32_sai_set_iec958_status(struct stm32_sai_sub_data *sai,
+   struct snd_pcm_runtime *runtime)
+{
+   if (!runtime)
+   return;
+
+   /* Force the sample rate according to runtime rate */
+   mutex_lock(>ctrl_lock);
+   switch (runtime->rate) {
+   case 22050:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_22050;
+   break;
+   case 44100:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_44100;
+   break;
+   case 88200:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_88200;
+   break;
+   case 176400:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_176400;
+   break;
+   case 24000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_24000;
+   break;
+   case 48000:

[INTERNAL][PATCH 1/7] ASoC: stm32: Add synchronization to SAI bindings

2017-10-19 Thread Olivier Moysan
Add synchronization configuration to STM32 SAI bindings.
This patch also adds peripheral clock which is required
to access synchronization register.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 Documentation/devicetree/bindings/sound/st,stm32-sai.txt | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
index f1c5ae5..1f9cd70 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -10,13 +10,21 @@ Required properties:
   - reg: Base address and size of SAI common register set.
   - clocks: Must contain phandle and clock specifier pairs for each entry
in clock-names.
-  - clock-names: Must contain "x8k" and "x11k"
+  - clock-names: Must contain "pclk" "x8k" and "x11k"
+   "pclk": Clock which feeds the peripheral bus interface.
+   Mandatory for "st,stm32h7-sai" compatible.
+   Not used for "st,stm32f4-sai" compatible.
"x8k": SAI parent clock for sampling rates multiple of 8kHz.
"x11k": SAI parent clock for sampling rates multiple of 11.025kHz.
   - interrupts: cpu DAI interrupt line shared by SAI sub-blocks
 
 Optional properties:
   - resets: Reference to a reset controller asserting the SAI
+  - st,sync: specify synchronization mode.
+   By default SAI sub-block is in asynchronous mode.
+   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.
 
 SAI subnodes:
 Two subnodes corresponding to SAI sub-block instances A et B can be defined.
@@ -52,8 +60,8 @@ sai1: sai1@40015800 {
#size-cells = <1>;
ranges = <0 0x40015800 0x400>;
reg = <0x40015800 0x4>;
-   clocks = < PLL1_Q>, < PLL2_P>;
-   clock-names = "x8k", "x11k";
+   clocks = < SAI1_CK>, < PLL1_Q>, < PLL2_P>;
+   clock-names = "pclk", "x8k", "x11k";
interrupts = <87>;
 
sai1a: audio-controller@40015804 {
-- 
1.9.1



[INTERNAL][PATCH 0/7] ASoC: stm32: Add SAI synchronization support

2017-10-19 Thread Olivier Moysan
This patch-set adds support of synchronization features for SAI interface.
It also adds minor fixes and improvements.

Olivier Moysan (7):
  ASoC: stm32: Add synchronization to SAI bindings
  ASoC: stm32: sai: Move static settings to DAI init
  ASoC: stm32: sai: Fix DMA burst size
  ASoC: stm32: sai: fix stop management in isr
  ASoC: stm32: sai: Remove spurious IRQs on stop
  ASoC: stm32: sai: Fix get reset controller
  ASoC: stm32: sai: Add synchronization support

 .../devicetree/bindings/sound/st,stm32-sai.txt |  14 +-
 sound/soc/stm/stm32_sai.c  | 162 -
 sound/soc/stm/stm32_sai.h  |  22 ++-
 sound/soc/stm/stm32_sai_sub.c  | 156 +---
 4 files changed, 318 insertions(+), 36 deletions(-)

-- 
1.9.1



[INTERNAL][PATCH 2/7] ASoC: stm32: sai: Move static settings to DAI init

2017-10-19 Thread Olivier Moysan
Audio interface direction and protocol settings does not change
at runtime. So, these settings are moved from hw_params
function to dai_probe and set_fmt.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai_sub.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 90d4396..fdc1891 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -304,12 +304,15 @@ static int stm32_sai_set_dai_tdm_slot(struct snd_soc_dai 
*cpu_dai, u32 tx_mask,
 static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 {
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
-   int cr1 = 0, frcr = 0;
-   int cr1_mask = 0, frcr_mask = 0;
+   int cr1, frcr = 0;
+   int cr1_mask, frcr_mask = 0;
int ret;
 
dev_dbg(cpu_dai->dev, "fmt %x\n", fmt);
 
+   cr1_mask = SAI_XCR1_PRTCFG_MASK;
+   cr1 = SAI_XCR1_PRTCFG_SET(SAI_FREE_PROTOCOL);
+
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
/* SCK active high for all protocols */
case SND_SOC_DAIFMT_I2S:
@@ -336,7 +339,7 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai 
*cpu_dai, unsigned int fmt)
return -EINVAL;
}
 
-   cr1_mask |= SAI_XCR1_PRTCFG_MASK | SAI_XCR1_CKSTR;
+   cr1_mask |= SAI_XCR1_CKSTR;
frcr_mask |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSOFF |
 SAI_XFRCR_FSDEF;
 
@@ -450,7 +453,7 @@ static int stm32_sai_set_config(struct snd_soc_dai *cpu_dai,
   SAI_XCR2_FFLUSH | SAI_XCR2_FTH_SET(fth));
 
/* Mode, data format and channel config */
-   cr1 = SAI_XCR1_PRTCFG_SET(SAI_FREE_PROTOCOL);
+   cr1_mask = SAI_XCR1_DS_MASK;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
cr1 |= SAI_XCR1_DS_SET(SAI_DATASIZE_8);
@@ -465,11 +468,6 @@ static int stm32_sai_set_config(struct snd_soc_dai 
*cpu_dai,
dev_err(cpu_dai->dev, "Data format not supported");
return -EINVAL;
}
-   cr1_mask = SAI_XCR1_DS_MASK | SAI_XCR1_PRTCFG_MASK;
-
-   cr1_mask |= SAI_XCR1_RX_TX;
-   if (STM_SAI_IS_CAPTURE(sai))
-   cr1 |= SAI_XCR1_RX_TX;
 
cr1_mask |= SAI_XCR1_MONO;
if ((sai->slots == 2) && (params_channels(params) == 1))
@@ -725,6 +723,7 @@ static void stm32_sai_shutdown(struct snd_pcm_substream 
*substream,
 static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
 {
struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
+   int cr1 = 0, cr1_mask;
 
sai->dma_params.addr = (dma_addr_t)(sai->phys_addr + STM_SAI_DR_REGX);
sai->dma_params.maxburst = 1;
@@ -736,7 +735,11 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
else
snd_soc_dai_init_dma_data(cpu_dai, NULL, >dma_params);
 
-   return 0;
+   cr1_mask = SAI_XCR1_RX_TX;
+   if (STM_SAI_IS_CAPTURE(sai))
+   cr1 |= SAI_XCR1_RX_TX;
+
+   return regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1);
 }
 
 static const struct snd_soc_dai_ops stm32_sai_pcm_dai_ops = {
-- 
1.9.1



[INTERNAL][PATCH 7/7] ASoC: stm32: sai: Add synchronization support

2017-10-19 Thread Olivier Moysan
Add Synchronization support for STM32 SAI.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai.c | 160 --
 sound/soc/stm/stm32_sai.h |  22 +-
 sound/soc/stm/stm32_sai_sub.c |  95 +
 3 files changed, 269 insertions(+), 8 deletions(-)

diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index 5fe878ac..d6f71a3 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -16,6 +16,7 @@
  * details.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -27,6 +28,16 @@
 
 #include "stm32_sai.h"
 
+static LIST_HEAD(sync_providers);
+static DEFINE_MUTEX(sync_mutex);
+
+struct sync_provider {
+   struct list_head link;
+   struct device_node *node;
+   int  (*sync_conf)(void *data, int synco);
+   void *data;
+};
+
 static const struct stm32_sai_conf stm32_sai_conf_f4 = {
.version = SAI_STM32F4,
 };
@@ -41,23 +52,143 @@
{}
 };
 
+static int stm32_sai_sync_conf_client(struct stm32_sai_data *sai, int synci)
+{
+   int ret;
+
+   /* Enable peripheral clock to allow GCR register access */
+   ret = clk_prepare_enable(sai->pclk);
+   if (ret) {
+   dev_err(>pdev->dev, "failed to enable clock: %d\n", ret);
+   return ret;
+   }
+
+   writel_relaxed(FIELD_PREP(SAI_GCR_SYNCIN_MASK, (synci - 1)), sai->base);
+
+   clk_disable_unprepare(sai->pclk);
+
+   return 0;
+}
+
+static int stm32_sai_sync_conf_provider(void *data, int synco)
+{
+   struct stm32_sai_data *sai = (struct stm32_sai_data *)data;
+   u32 prev_synco;
+   int ret;
+
+   /* Enable peripheral clock to allow GCR register access */
+   ret = clk_prepare_enable(sai->pclk);
+   if (ret) {
+   dev_err(>pdev->dev, "failed to enable clock: %d\n", ret);
+   return ret;
+   }
+
+   dev_dbg(>pdev->dev, "Set %s%s as synchro provider\n",
+   sai->pdev->dev.of_node->name,
+   synco == STM_SAI_SYNC_OUT_A ? "A" : "B");
+
+   prev_synco = FIELD_GET(SAI_GCR_SYNCOUT_MASK, readl_relaxed(sai->base));
+   if (prev_synco != STM_SAI_SYNC_OUT_NONE && synco != prev_synco) {
+   dev_err(>pdev->dev, "%s%s already set as sync provider\n",
+   sai->pdev->dev.of_node->name,
+   prev_synco == STM_SAI_SYNC_OUT_A ? "A" : "B");
+   clk_disable_unprepare(sai->pclk);
+   return -EINVAL;
+   }
+
+   writel_relaxed(FIELD_PREP(SAI_GCR_SYNCOUT_MASK, synco), sai->base);
+
+   clk_disable_unprepare(sai->pclk);
+
+   return 0;
+}
+
+static int stm32_sai_set_sync_provider(struct device_node *np, int synco)
+{
+   struct sync_provider *provider;
+   int ret;
+
+   mutex_lock(_mutex);
+   list_for_each_entry(provider, _providers, link) {
+   if (provider->node == np) {
+   ret = provider->sync_conf(provider->data, synco);
+   mutex_unlock(_mutex);
+   return ret;
+   }
+   }
+   mutex_unlock(_mutex);
+
+   /* SAI sync provider not found */
+   return -ENODEV;
+}
+
+static int stm32_sai_set_sync(struct stm32_sai_data *sai,
+ struct device_node *np_provider,
+ int synco, int synci)
+{
+   int ret;
+
+   /* Configure sync client */
+   stm32_sai_sync_conf_client(sai, synci);
+
+   /* Configure sync provider */
+   ret = stm32_sai_set_sync_provider(np_provider, synco);
+
+   return ret;
+}
+
+static int stm32_sai_sync_add_provider(struct platform_device *pdev,
+  void *data)
+{
+   struct sync_provider *sp;
+
+   sp = devm_kzalloc(>dev, sizeof(*sp), GFP_KERNEL);
+   if (!sp)
+   return -ENOMEM;
+
+   sp->node = of_node_get(pdev->dev.of_node);
+   sp->data = data;
+   sp->sync_conf = _sai_sync_conf_provider;
+
+   mutex_lock(_mutex);
+   list_add(>link, _providers);
+   mutex_unlock(_mutex);
+
+   return 0;
+}
+
+static void stm32_sai_sync_del_provider(struct device_node *np)
+{
+   struct sync_provider *sp;
+
+   mutex_lock(_mutex);
+   list_for_each_entry(sp, _providers, link) {
+   if (sp->node == np) {
+   list_del(>link);
+   of_node_put(sp->node);
+   break;
+   }
+   }
+   mutex_unlock(_mutex);
+}
+
 static int stm32_sai_probe(struct platform_device *pdev)
 {
struct device_node *np = pdev->dev.of_node;
struct stm32_sai_data *sai;
struct reset_control *rst;
struct resource *res;
-  

Re: [INTERNAL][PATCH 0/7] ASoC: stm32: Add SAI synchronization support

2017-10-19 Thread Olivier MOYSAN
Please ignore "[INTERNAL]" in subject.
Sorry for this unappropriated header.

On 10/19/2017 03:03 PM, Olivier Moysan wrote:
> This patch-set adds support of synchronization features for SAI interface.
> It also adds minor fixes and improvements.
> 
> Olivier Moysan (7):
>ASoC: stm32: Add synchronization to SAI bindings
>ASoC: stm32: sai: Move static settings to DAI init
>ASoC: stm32: sai: Fix DMA burst size
>ASoC: stm32: sai: fix stop management in isr
>ASoC: stm32: sai: Remove spurious IRQs on stop
>ASoC: stm32: sai: Fix get reset controller
>ASoC: stm32: sai: Add synchronization support
> 
>   .../devicetree/bindings/sound/st,stm32-sai.txt |  14 +-
>   sound/soc/stm/stm32_sai.c  | 162 
> -
>   sound/soc/stm/stm32_sai.h  |  22 ++-
>   sound/soc/stm/stm32_sai_sub.c  | 156 
> +---
>   4 files changed, 318 insertions(+), 36 deletions(-)
> 

[INTERNAL][PATCH 4/7] ASoC: stm32: sai: fix stop management in isr

2017-10-19 Thread Olivier Moysan
Add check on substream validity.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai_sub.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 2af397d..815ef10 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -184,7 +184,6 @@ static bool stm32_sai_sub_writeable_reg(struct device *dev, 
unsigned int reg)
 static irqreturn_t stm32_sai_isr(int irq, void *devid)
 {
struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid;
-   struct snd_pcm_substream *substream = sai->substream;
struct platform_device *pdev = sai->pdev;
unsigned int sr, imr, flags;
snd_pcm_state_t status = SNDRV_PCM_STATE_RUNNING;
@@ -199,6 +198,11 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
regmap_update_bits(sai->regmap, STM_SAI_CLRFR_REGX, SAI_XCLRFR_MASK,
   SAI_XCLRFR_MASK);
 
+   if (!sai->substream) {
+   dev_err(>dev, "Device stopped. Spurious IRQ 0x%x\n", sr);
+   return IRQ_NONE;
+   }
+
if (flags & SAI_XIMR_OVRUDRIE) {
dev_err(>dev, "IRQ %s\n",
STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun");
@@ -227,9 +231,9 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
}
 
if (status != SNDRV_PCM_STATE_RUNNING) {
-   snd_pcm_stream_lock(substream);
-   snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-   snd_pcm_stream_unlock(substream);
+   snd_pcm_stream_lock(sai->substream);
+   snd_pcm_stop(sai->substream, SNDRV_PCM_STATE_XRUN);
+   snd_pcm_stream_unlock(sai->substream);
}
 
return IRQ_HANDLED;
-- 
1.9.1



[INTERNAL][PATCH 3/7] ASoC: stm32: sai: Fix DMA burst size

2017-10-19 Thread Olivier Moysan
Set best burst size tradeoff for 8, 16, 32 bits transfers.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai_sub.c | 21 +
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index fdc1891..2af397d 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -445,12 +445,16 @@ static int stm32_sai_set_config(struct snd_soc_dai 
*cpu_dai,
 {
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
int cr1, cr1_mask, ret;
-   int fth = STM_SAI_FIFO_TH_HALF;
 
-   /* FIFO config */
+   /*
+* DMA bursts increment is set to 4 words.
+* SAI fifo threshold is set to half fifo, to keep enough space
+* for DMA incoming bursts.
+*/
regmap_update_bits(sai->regmap, STM_SAI_CR2_REGX,
   SAI_XCR2_FFLUSH | SAI_XCR2_FTH_MASK,
-  SAI_XCR2_FFLUSH | SAI_XCR2_FTH_SET(fth));
+  SAI_XCR2_FFLUSH |
+  SAI_XCR2_FTH_SET(STM_SAI_FIFO_TH_HALF));
 
/* Mode, data format and channel config */
cr1_mask = SAI_XCR1_DS_MASK;
@@ -479,10 +483,6 @@ static int stm32_sai_set_config(struct snd_soc_dai 
*cpu_dai,
return ret;
}
 
-   /* DMA config */
-   sai->dma_params.maxburst = STM_SAI_FIFO_SIZE * fth / sizeof(u32);
-   snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)>dma_params);
-
return 0;
 }
 
@@ -726,7 +726,12 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
int cr1 = 0, cr1_mask;
 
sai->dma_params.addr = (dma_addr_t)(sai->phys_addr + STM_SAI_DR_REGX);
-   sai->dma_params.maxburst = 1;
+   /*
+* DMA supports 4, 8 or 16 burst sizes. Burst size 4 is the best choice,
+* as it allows bytes, half-word and words transfers. (See DMA fifos
+* constraints).
+*/
+   sai->dma_params.maxburst = 4;
/* Buswidth will be set by framework at runtime */
sai->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
 
-- 
1.9.1



[INTERNAL][PATCH 5/7] ASoC: stm32: sai: Remove spurious IRQs on stop

2017-10-19 Thread Olivier Moysan
Clear IRQ mask on stream stop to avoid spurious IRQs.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai_sub.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 815ef10..fd7dc77 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -419,8 +419,6 @@ static int stm32_sai_startup(struct snd_pcm_substream 
*substream,
}
 
/* Enable ITs */
-   regmap_update_bits(sai->regmap, STM_SAI_SR_REGX,
-  SAI_XSR_MASK, (unsigned int)~SAI_XSR_MASK);
 
regmap_update_bits(sai->regmap, STM_SAI_CLRFR_REGX,
   SAI_XCLRFR_MASK, SAI_XCLRFR_MASK);
@@ -693,6 +691,9 @@ static int stm32_sai_trigger(struct snd_pcm_substream 
*substream, int cmd,
case SNDRV_PCM_TRIGGER_STOP:
dev_dbg(cpu_dai->dev, "Disable DMA and SAI\n");
 
+   regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX,
+  SAI_XIMR_MASK, 0);
+
regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
   SAI_XCR1_SAIEN,
   (unsigned int)~SAI_XCR1_SAIEN);
-- 
1.9.1



[INTERNAL][PATCH 6/7] ASoC: stm32: sai: Fix get reset controller

2017-10-19 Thread Olivier Moysan
Use devm version of reset_control_get function
to manage driver removing properly.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_sai.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index 1258bef..5fe878ac 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -85,7 +85,7 @@ static int stm32_sai_probe(struct platform_device *pdev)
}
 
/* reset */
-   rst = reset_control_get_exclusive(>dev, NULL);
+   rst = devm_reset_control_get_exclusive(>dev, NULL);
if (!IS_ERR(rst)) {
reset_control_assert(rst);
udelay(2);
-- 
1.9.1



Re: [alsa-devel] [PATCH 1/1] ASoC: stm32: add of dependency for stm32 drivers

2018-02-01 Thread Olivier MOYSAN
hello,

On 02/01/2018 10:10 AM, Ladislav Michl wrote:
> On Thu, Feb 01, 2018 at 09:54:41AM +0100, Olivier Moysan wrote:
>> Add of dependency for STM32 ASoC drivers.
>> DFSDM of dependency is already inherited
>> from STM32_DFSDM_ADC dependency.
>>
>> Signed-off-by: olivier moysan <olivier.moy...@st.com>
>> ---
>>   sound/soc/stm/Kconfig | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
>> index 3ad881f..b5375f9 100644
>> --- a/sound/soc/stm/Kconfig
>> +++ b/sound/soc/stm/Kconfig
>> @@ -3,6 +3,7 @@ menu "STMicroelectronics STM32 SOC audio support"
>>   config SND_SOC_STM32_SAI
>>  tristate "STM32 SAI interface (Serial Audio Interface) support"
>>  depends on ARCH_STM32 || COMPILE_TEST
>> +depends on OF
> 
> depends on (ARCH_STM32 && OF) || COMPILE_TEST ?
> 

I can find in many configs "depends on OF && (ARCH_X || COMPILE_TEST)"
This seems reasonable to me, as the driver always requires OF 
dependency, regardless the compilation context.
In fact, I cannot see why OF would not have to be selected
for COMPILE_TEST.

BRs

>>  depends on SND_SOC
>>  select SND_SOC_GENERIC_DMAENGINE_PCM
>>  select REGMAP_MMIO
>> @@ -12,6 +13,7 @@ config SND_SOC_STM32_SAI
>>   config SND_SOC_STM32_I2S
>>  tristate "STM32 I2S interface (SPI/I2S block) support"
>>  depends on ARCH_STM32 || COMPILE_TEST
>> +depends on OF
>>  depends on SND_SOC
>>  select SND_SOC_GENERIC_DMAENGINE_PCM
>>  select REGMAP_MMIO
>> @@ -21,6 +23,7 @@ config SND_SOC_STM32_I2S
>>   config SND_SOC_STM32_SPDIFRX
>>  tristate "STM32 S/PDIF receiver (SPDIFRX) support"
>>  depends on ARCH_STM32 || COMPILE_TEST
>> +depends on OF
>>  depends on SND_SOC
>>  select SND_SOC_GENERIC_DMAENGINE_PCM
>>  select REGMAP_MMIO
>> -- 
>> 1.9.1
>>
>> ___
>> Alsa-devel mailing list
>> alsa-de...@alsa-project.org
>> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

[PATCH 0/2] ASoC: stm32: spdifrx: change dai name

2018-01-31 Thread Olivier Moysan
This patchset changes spdifrx dai name and fixes a typo issue.

Olivier Moysan (2):
  ASoC: stm32: spdifrx: fix typo in function name.
  ASoC: stm32: spdifrx: Use default dai name

 sound/soc/stm/stm32_spdifrx.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

-- 
1.9.1



[PATCH 1/2] ASoC: stm32: spdifrx: fix typo in function name.

2018-01-31 Thread Olivier Moysan
Fix function name prefix for naming consistency.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_spdifrx.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index b9bdefc..42ad2ae 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -858,8 +858,8 @@ static void stm32_spdifrx_shutdown(struct snd_pcm_substream 
*substream,
{}
 };
 
-static int stm_spdifrx_parse_of(struct platform_device *pdev,
-   struct stm32_spdifrx_data *spdifrx)
+static int stm32_spdifrx_parse_of(struct platform_device *pdev,
+ struct stm32_spdifrx_data *spdifrx)
 {
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *of_id;
@@ -914,7 +914,7 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, spdifrx);
 
-   ret = stm_spdifrx_parse_of(pdev, spdifrx);
+   ret = stm32_spdifrx_parse_of(pdev, spdifrx);
if (ret)
return ret;
 
-- 
1.9.1



[PATCH 2/2] ASoC: stm32: spdifrx: Use default dai name

2018-01-31 Thread Olivier Moysan
Use dai name provided by framework from dev_name() function.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/stm32_spdifrx.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index 42ad2ae..373df4f 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -819,7 +819,6 @@ static void stm32_spdifrx_shutdown(struct snd_pcm_substream 
*substream,
 
 static struct snd_soc_dai_driver stm32_spdifrx_dai[] = {
{
-   .name = "spdifrx-capture-cpu-dai",
.probe = stm32_spdifrx_dai_probe,
.capture = {
.stream_name = "CPU-Capture",
-- 
1.9.1



[PATCH v2 1/1] ASoC: stm32: add of dependency for stm32 drivers

2018-02-05 Thread Olivier Moysan
Add of dependency for STM32 ASoC drivers.
DFSDM of dependency is already inherited
from STM32_DFSDM_ADC dependency.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/Kconfig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 3ad881f..48f9ddd 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -2,7 +2,7 @@ menu "STMicroelectronics STM32 SOC audio support"
 
 config SND_SOC_STM32_SAI
tristate "STM32 SAI interface (Serial Audio Interface) support"
-   depends on ARCH_STM32 || COMPILE_TEST
+   depends on (ARCH_STM32 && OF) || COMPILE_TEST
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
@@ -11,7 +11,7 @@ config SND_SOC_STM32_SAI
 
 config SND_SOC_STM32_I2S
tristate "STM32 I2S interface (SPI/I2S block) support"
-   depends on ARCH_STM32 || COMPILE_TEST
+   depends on (ARCH_STM32 && OF) || COMPILE_TEST
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
@@ -20,7 +20,7 @@ config SND_SOC_STM32_I2S
 
 config SND_SOC_STM32_SPDIFRX
tristate "STM32 S/PDIF receiver (SPDIFRX) support"
-   depends on ARCH_STM32 || COMPILE_TEST
+   depends on (ARCH_STM32 && OF) || COMPILE_TEST
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
-- 
1.9.1



[PATCH 1/1] ASoC: stm32: add of dependency for stm32 drivers

2018-02-01 Thread Olivier Moysan
Add of dependency for STM32 ASoC drivers.
DFSDM of dependency is already inherited
from STM32_DFSDM_ADC dependency.

Signed-off-by: olivier moysan <olivier.moy...@st.com>
---
 sound/soc/stm/Kconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 3ad881f..b5375f9 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -3,6 +3,7 @@ menu "STMicroelectronics STM32 SOC audio support"
 config SND_SOC_STM32_SAI
tristate "STM32 SAI interface (Serial Audio Interface) support"
depends on ARCH_STM32 || COMPILE_TEST
+   depends on OF
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
@@ -12,6 +13,7 @@ config SND_SOC_STM32_SAI
 config SND_SOC_STM32_I2S
tristate "STM32 I2S interface (SPI/I2S block) support"
depends on ARCH_STM32 || COMPILE_TEST
+   depends on OF
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
@@ -21,6 +23,7 @@ config SND_SOC_STM32_I2S
 config SND_SOC_STM32_SPDIFRX
tristate "STM32 S/PDIF receiver (SPDIFRX) support"
depends on ARCH_STM32 || COMPILE_TEST
+   depends on OF
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
-- 
1.9.1



[RFC PATCH 1/3] ASoC: stm32: Add S/PDIF to SAI bindings

2018-02-19 Thread Olivier Moysan
Add S/PDIF IEC6958 protocol support to STM32 SAI bindings.

Signed-off-by: olivier moysan <olivier.moy...@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



[RFC PATCH 3/3] ASoC: stm32: sai: Add support of S/PDIF playback

2018-02-19 Thread Olivier Moysan
Add support of S/PDIF iec60958 playback on STM32 SAI.

Signed-off-by: olivier moysan <olivier.moy...@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 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -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(

[RFC PATCH 2/3] ASoC: dmaengine_pcm: add processing support

2018-02-19 Thread Olivier Moysan
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.moy...@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= _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, >component,
-   _pcm_component, NULL, 0);
+   if (config && config->process)
+   ret = snd_soc_add_component(dev, >component,
+   _pcm_component_process,
+   NULL, 0);
+   else
+   ret = snd_soc_add_component(dev, 

[RFC PATCH 0/3] ASoC: stm32: add S/PDIF support to SAI

2018-02-19 Thread Olivier Moysan
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
PCUVdata (16|24 bits)preamble

SAI data register format:
27-2423-0   
P CUVdata (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



[PATCH 0/3] ASoC: stm32: sai: add support of iec958 controls

2018-03-13 Thread Olivier Moysan
This patchset adds support of iec958 controls to STM32 SAI driver.

The patch makes use of iec958 control status helpers previously proposed
and discussed through the following threads:
https://patchwork.kernel.org/patch/8062601/
https://patchwork.kernel.org/patch/8091551/ (v2)
https://patchwork.kernel.org/patch/8462961/ (v3)
https://patchwork.kernel.org/patch/8533731/ (v4)

Olivier Moysan (3):
  ALSA: pcm: add IEC958 channel status control helper
  ASoC: stm32: sai: add iec958 controls support
  ASoC: dmaengine_pcm: document process callback

 include/sound/dmaengine_pcm.h |   2 +
 include/sound/pcm_iec958.h|  19 +++
 sound/core/pcm_iec958.c   | 114 ++
 sound/soc/stm/Kconfig |   1 +
 sound/soc/stm/stm32_sai_sub.c | 101 -
 5 files changed, 225 insertions(+), 12 deletions(-)

-- 
1.9.1



[PATCH 2/3] ASoC: stm32: sai: add iec958 controls support

2018-03-13 Thread Olivier Moysan
Add support of iec958 controls for STM32 SAI.

Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 sound/core/pcm_iec958.c   |   1 +
 sound/soc/stm/Kconfig |   1 +
 sound/soc/stm/stm32_sai_sub.c | 101 +-
 3 files changed, 91 insertions(+), 12 deletions(-)

diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
index aba1f522e98a..c34735ac3c48 100644
--- a/sound/core/pcm_iec958.c
+++ b/sound/core/pcm_iec958.c
@@ -19,6 +19,7 @@ static int snd_pcm_iec958_info(struct snd_kcontrol *kcontrol,
 {
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
+
return 0;
 }
 
diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 48f9ddd94016..9b2681397dba 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -6,6 +6,7 @@ config SND_SOC_STM32_SAI
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
+   select SND_PCM_IEC958
help
  Say Y if you want to enable SAI for STM32
 
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index cfeb219e1d78..c2e487e133aa 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "stm32_sai.h"
@@ -96,7 +97,7 @@
  * @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
+ * @snd_aes_iec958: iec958 data
  */
 struct stm32_sai_sub_data {
struct platform_device *pdev;
@@ -125,7 +126,7 @@ struct stm32_sai_sub_data {
int slot_mask;
int data_size;
unsigned int spdif_frm_cnt;
-   unsigned char spdif_status_bits[SAI_IEC60958_STATUS_BYTES];
+   struct snd_aes_iec958 iec958;
 };
 
 enum stm32_sai_fifo_th {
@@ -184,10 +185,6 @@ 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,
@@ -619,6 +616,59 @@ static void stm32_sai_set_frame(struct snd_soc_dai 
*cpu_dai)
}
 }
 
+static void stm32_sai_set_channel_status(struct stm32_sai_sub_data *sai,
+struct snd_pcm_runtime *runtime)
+{
+   if (!runtime)
+   return;
+
+   /* Force the sample rate according to runtime rate */
+   switch (runtime->rate) {
+   case 22050:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_22050;
+   break;
+   case 44100:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_44100;
+   break;
+   case 88200:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_88200;
+   break;
+   case 176400:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_176400;
+   break;
+   case 24000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_24000;
+   break;
+   case 48000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_48000;
+   break;
+   case 96000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_96000;
+   break;
+   case 192000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_192000;
+   break;
+   case 32000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_32000;
+   break;
+   default:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_NOTID;
+   break;
+   }
+}
+
+static int stm32_sai_iec958_set(struct snd_pcm_iec958_params *iec_param)
+{
+   struct stm32_sai_sub_data *sai = iec_param->private_data;
+
+   if (!sai->substream)
+   return 0;
+
+   stm32_sai_set_channel_status(sai, sai->substream->runtime);
+
+   return 0;
+}
+
 static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
 struct snd_pcm_hw_params *params)
 {
@@ -709,7 +759,11 @@ static int stm32_sai_hw_params(struct snd_pcm_substream 
*substream,
 
sai->data_size = params_width(params);
 
-   if (!STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+   if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+   /* Rate not already set in runtime structure */
+   substream->runtime->rate = params_rate(params);
+   stm32_sai_set_channel_status(sai, substream->runtime);
+   } else {
ret = stm32_sai_set_slots(cpu_dai);
if (ret < 0)
return ret;
@@ -789,6 +843,28 @@ static void stm32_sai_shutdown(struct snd_pcm_substream 
*s

[PATCH 1/3] ALSA: pcm: add IEC958 channel status control helper

2018-03-13 Thread Olivier Moysan
From: Arnaud Pouliquen <arnaud.pouliq...@st.com>

Add IEC958 channel status helper that creates control to handle the
IEC60958 status bits.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliq...@st.com>
Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 include/sound/pcm_iec958.h |  19 
 sound/core/pcm_iec958.c| 113 +
 2 files changed, 132 insertions(+)

diff --git a/include/sound/pcm_iec958.h b/include/sound/pcm_iec958.h
index 0939aa45e2fe..3c9701a9b1b0 100644
--- a/include/sound/pcm_iec958.h
+++ b/include/sound/pcm_iec958.h
@@ -4,9 +4,28 @@
 
 #include 
 
+/**
+ * struct snd_pcm_iec958_params: IEC 60958 controls parameters
+ * @ctrl_set: control set callback
+ * This callback is optional and shall be used to set associated driver
+ * configuration.
+ * @iec: Mandatory pointer to iec958 structure.
+ * @cs: Mandatory pointer to AES/IEC958  channel status bits.
+ * @cs_len: size in byte of the AES/IEC958  channel status bits.
+ * @private_data: Optional private pointer to driver context.
+ */
+struct snd_pcm_iec958_params {
+   int (*ctrl_set)(struct snd_pcm_iec958_params *iec_param);
+   unsigned char *cs;
+   unsigned char cs_len;
+   void *private_data;
+};
+
 int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
size_t len);
 
 int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
 u8 *cs, size_t len);
+int snd_pcm_add_iec958_ctl(struct snd_pcm *pcm, int subdevice, int stream,
+  struct snd_pcm_iec958_params *params);
 #endif
diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
index 5e6aed64f451..aba1f522e98a 100644
--- a/sound/core/pcm_iec958.c
+++ b/sound/core/pcm_iec958.c
@@ -7,11 +7,88 @@
  */
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
+static int snd_pcm_iec958_info(struct snd_kcontrol *kcontrol,
+  struct snd_ctl_elem_info *uinfo)
+{
+   uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+   uinfo->count = 1;
+   return 0;
+}
+
+/*
+ * IEC958 channel status default controls callbacks
+ */
+static int snd_pcm_iec958_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uctl)
+{
+   struct snd_pcm_iec958_params *params = snd_kcontrol_chip(kcontrol);
+   int i;
+
+   for (i = 0; i < params->cs_len; i++)
+   uctl->value.iec958.status[i] = params->cs[i];
+
+   return 0;
+}
+
+static int snd_pcm_iec958_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uctl)
+{
+   struct snd_pcm_iec958_params *params = snd_kcontrol_chip(kcontrol);
+   int err = 0;
+   unsigned int i, updated = 0;
+   unsigned char old_status[5];
+
+   for (i = 0; i < params->cs_len; i++) {
+   if (params->cs[i] != uctl->value.iec958.status[i])
+   updated = 1;
+   }
+
+   if (!updated)
+   return 0;
+
+   /* Store current status to restore them in error case */
+   for (i = 0; i < params->cs_len; i++) {
+   old_status[i] = params->cs[i];
+   params->cs[i] = uctl->value.iec958.status[i];
+   }
+
+   if (params->ctrl_set)
+   err = params->ctrl_set(params);
+   if (err < 0) {
+   for (i = 0; i < params->cs_len; i++)
+   params->cs[i] = old_status[i];
+   }
+
+   return err;
+}
+
+static const struct snd_kcontrol_new iec958_ctls[] = {
+   {
+   .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+  SNDRV_CTL_ELEM_ACCESS_VOLATILE),
+   .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+   .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+   .info = snd_pcm_iec958_info,
+   .get = snd_pcm_iec958_get,
+   .put = snd_pcm_iec958_put,
+   },
+   {
+   .access = (SNDRV_CTL_ELEM_ACCESS_READ |
+  SNDRV_CTL_ELEM_ACCESS_VOLATILE),
+   .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+   .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
+   .info = snd_pcm_iec958_info,
+   .get = snd_pcm_iec958_get,
+   },
+};
+
 static int create_iec958_consumer(uint rate, uint sample_width,
  u8 *cs, size_t len)
 {
@@ -21,6 +98,9 @@ static int create_iec958_consumer(uint rate, uint 
sample_width,
return -EINVAL;
 
switch (rate) {
+   case 0:
+   fs = IEC958_AES3_CON_FS_NOTID;
+   break;
case 32000:
fs = IEC958_AES3_CON_FS_32000;
break;
@@ -48,6 +128,9 @@ static int create_iec958_consumer(uint rate, uint 

[PATCH 3/3] ASoC: dmaengine_pcm: document process callback

2018-03-13 Thread Olivier Moysan
Add missing description of process callback.

Fixes: 78648092ef46 ("ASoC: dmaengine_pcm: add processing support")
Signed-off-by: Olivier Moysan <olivier.moy...@st.com>
---
 include/sound/dmaengine_pcm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index 47ef486852ed..e3481eebdd98 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -118,6 +118,8 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
  *   PCM substream. Will be called from the PCM drivers hwparams callback.
  * @compat_request_channel: Callback to request a DMA channel for platforms
  *   which do not use devicetree.
+ * @process: Callback used to apply processing on samples transferred from/to
+ *   user space.
  * @compat_filter_fn: Will be used as the filter function when requesting a
  *  channel for platforms which do not use devicetree. The filter parameter
  *  will be the DAI's DMA data.
-- 
1.9.1



Re: [PATCH 0/3] ASoC: stm32: sai: add support of iec958 controls

2018-04-17 Thread Olivier MOYSAN
Hello,

I guess the blocking patch in this patchset is the patch "add IEC958 
channel status control helper". This patch has been reviewed several 
times, but did not get a ack so far.
If you think these helpers will not be merged, I will reintegrate the 
corresponding code in stm driver.
Please let me know, if I need to prepare a v2 without helpers, or if we 
can go further in the review of iec helpers patch ?

Best regards
olivier


On 03/13/2018 05:27 PM, Olivier Moysan wrote:
> This patchset adds support of iec958 controls to STM32 SAI driver.
> 
> The patch makes use of iec958 control status helpers previously proposed
> and discussed through the following threads:
> https://patchwork.kernel.org/patch/8062601/
> https://patchwork.kernel.org/patch/8091551/ (v2)
> https://patchwork.kernel.org/patch/8462961/ (v3)
> https://patchwork.kernel.org/patch/8533731/ (v4)
> 
> Olivier Moysan (3):
>ALSA: pcm: add IEC958 channel status control helper
>ASoC: stm32: sai: add iec958 controls support
>ASoC: dmaengine_pcm: document process callback
> 
>   include/sound/dmaengine_pcm.h |   2 +
>   include/sound/pcm_iec958.h|  19 +++
>   sound/core/pcm_iec958.c   | 114 
> ++
>   sound/soc/stm/Kconfig |   1 +
>   sound/soc/stm/stm32_sai_sub.c | 101 -
>   5 files changed, 225 insertions(+), 12 deletions(-)
> 

[PATCH 2/4] ASoC: dt-bindings: add mclk support to cs42l51

2018-10-15 Thread Olivier Moysan
Add clocks properties to cs42l51 Cirrus codec,
to support master clock provider.

Signed-off-by: Olivier Moysan 
---
 Documentation/devicetree/bindings/sound/cs42l51.txt   | 17 +
 Documentation/devicetree/bindings/trivial-devices.txt |  1 -
 2 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/sound/cs42l51.txt

diff --git a/Documentation/devicetree/bindings/sound/cs42l51.txt 
b/Documentation/devicetree/bindings/sound/cs42l51.txt
new file mode 100644
index ..4b5de33ce377
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/cs42l51.txt
@@ -0,0 +1,17 @@
+CS42L51 audio CODEC
+
+Optional properties:
+
+  - clocks : a list of phandles + clock-specifiers, one for each entry in
+clock-names
+
+  - clock-names : must contain "MCLK"
+
+Example:
+
+cs42l51: cs42l51@4a {
+   compatible = "cirrus,cs42l51";
+   reg = <0x4a>;
+   clocks = <_prov>;
+   clock-names = "MCLK";
+};
diff --git a/Documentation/devicetree/bindings/trivial-devices.txt 
b/Documentation/devicetree/bindings/trivial-devices.txt
index 763a2808a95c..69c934aec13b 100644
--- a/Documentation/devicetree/bindings/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/trivial-devices.txt
@@ -35,7 +35,6 @@ at,24c08  i2c serial eeprom  (24cxx)
 atmel,at97sc3204t  i2c trusted platform module (TPM)
 capella,cm32181CM32181: Ambient Light Sensor
 capella,cm3232 CM3232: Ambient Light Sensor
-cirrus,cs42l51 Cirrus Logic CS42L51 audio codec
 dallas,ds1374  I2C, 32-Bit Binary Counter Watchdog RTC with Trickle 
Charger and Reset Input/Output
 dallas,ds1631  High-Precision Digital Thermometer
 dallas,ds1672  Dallas DS1672 Real-time Clock
-- 
2.7.4



[PATCH 1/4] ASoC: dt-bindings: add mclk provider support to stm32 sai

2018-10-15 Thread Olivier Moysan
add mclk provider support to stm32 sai

Signed-off-by: Olivier Moysan 
---
 Documentation/devicetree/bindings/sound/st,stm32-sai.txt | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt 
b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
index 3a3fc506e43a..3f4467ff0aa2 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -31,7 +31,11 @@ SAI subnodes required properties:
   - reg: Base address and size of SAI sub-block register set.
   - clocks: Must contain one phandle and clock specifier pair
for sai_ck which feeds the internal clock generator.
+   If the SAI shares a master clock, with another SAI set as MCLK
+   clock provider, SAI provider phandle must be specified here.
   - clock-names: Must contain "sai_ck".
+   Must also contain "MCLK", if SAI shares a master clock,
+   with a SAI set as MCLK clock provider.
   - dmas: see Documentation/devicetree/bindings/dma/stm32-dma.txt
   - dma-names: identifier string for each DMA request line
"tx": if sai sub-block is configured as playback DAI
@@ -51,6 +55,9 @@ SAI subnodes Optional properties:
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
+   - #clock-cells: should be 0. This property must be present if the SAI device
+   is a master clock provider, according to clocks bindings, described in
+   Documentation/devicetree/bindings/clock/clock-bindings.txt.
 
 The device node should contain one 'port' child node with one child 'endpoint'
 node, according to the bindings defined in Documentation/devicetree/bindings/
-- 
2.7.4



[PATCH 3/4] ASoC: stm32: sai: set sai as mclk clock provider

2018-10-15 Thread Olivier Moysan
Add master clock generation support in STM32 SAI.
The master clock provided by SAI can be used to feed a codec.

Signed-off-by: Olivier Moysan 
---
 sound/soc/stm/stm32_sai.h |   3 +
 sound/soc/stm/stm32_sai_sub.c | 275 --
 2 files changed, 242 insertions(+), 36 deletions(-)

diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h
index f25422174909..08de899c766b 100644
--- a/sound/soc/stm/stm32_sai.h
+++ b/sound/soc/stm/stm32_sai.h
@@ -91,6 +91,9 @@
 #define SAI_XCR1_OSR_SHIFT 26
 #define SAI_XCR1_OSR   BIT(SAI_XCR1_OSR_SHIFT)
 
+#define SAI_XCR1_MCKEN_SHIFT   27
+#define SAI_XCR1_MCKEN BIT(SAI_XCR1_MCKEN_SHIFT)
+
 /*** Bit definition for SAI_XCR2 register ***/
 #define SAI_XCR2_FTH_SHIFT 0
 #define SAI_XCR2_FTH_MASK  GENMASK(2, SAI_XCR2_FTH_SHIFT)
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 56a227e0bd71..31d22abd3204 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -17,6 +17,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -68,6 +69,8 @@
 #define SAI_IEC60958_BLOCK_FRAMES  192
 #define SAI_IEC60958_STATUS_BYTES  24
 
+#define SAI_MCLK_NAME_LEN  32
+
 /**
  * struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
  * @pdev: device data pointer
@@ -80,6 +83,7 @@
  * @pdata: SAI block parent data pointer
  * @np_sync_provider: synchronization provider node
  * @sai_ck: kernel clock feeding the SAI clock generator
+ * @sai_mclk: master clock from SAI mclk provider
  * @phys_addr: SAI registers physical base address
  * @mclk_rate: SAI block master clock frequency (Hz). set at init
  * @id: SAI sub block id corresponding to sub-block A or B
@@ -110,6 +114,7 @@ struct stm32_sai_sub_data {
struct stm32_sai_data *pdata;
struct device_node *np_sync_provider;
struct clk *sai_ck;
+   struct clk *sai_mclk;
dma_addr_t phys_addr;
unsigned int mclk_rate;
unsigned int id;
@@ -251,6 +256,177 @@ static const struct snd_kcontrol_new iec958_ctls = {
.put = snd_pcm_iec958_put,
 };
 
+struct stm32_sai_mclk_data {
+   struct clk_hw hw;
+   unsigned long freq;
+   struct stm32_sai_sub_data *sai_data;
+};
+
+#define to_mclk_data(_hw) container_of(_hw, struct stm32_sai_mclk_data, hw)
+#define STM32_SAI_MAX_CLKS 1
+
+static int stm32_sai_get_clk_div(struct stm32_sai_sub_data *sai,
+unsigned long input_rate,
+unsigned long output_rate)
+{
+   int version = sai->pdata->conf->version;
+   int div;
+
+   div = DIV_ROUND_CLOSEST(input_rate, output_rate);
+   if (div > SAI_XCR1_MCKDIV_MAX(version)) {
+   dev_err(>pdev->dev, "Divider %d out of range\n", div);
+   return -EINVAL;
+   }
+   dev_dbg(>pdev->dev, "SAI divider %d\n", div);
+
+   if (input_rate % div)
+   dev_dbg(>pdev->dev,
+   "Rate not accurate. requested (%ld), actual (%ld)\n",
+   output_rate, input_rate / div);
+
+   return div;
+}
+
+static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai,
+unsigned int div)
+{
+   int version = sai->pdata->conf->version;
+   int ret, cr1, mask;
+
+   if (div > SAI_XCR1_MCKDIV_MAX(version)) {
+   dev_err(>pdev->dev, "Divider %d out of range\n", div);
+   return -EINVAL;
+   }
+
+   mask = SAI_XCR1_MCKDIV_MASK(SAI_XCR1_MCKDIV_WIDTH(version));
+   cr1 = SAI_XCR1_MCKDIV_SET(div);
+   ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, mask, cr1);
+   if (ret < 0)
+   dev_err(>pdev->dev, "Failed to update CR1 register\n");
+
+   return ret;
+}
+
+static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+   struct stm32_sai_mclk_data *mclk = to_mclk_data(hw);
+   struct stm32_sai_sub_data *sai = mclk->sai_data;
+   int div;
+
+   div = stm32_sai_get_clk_div(sai, *prate, rate);
+   if (div < 0)
+   return div;
+
+   mclk->freq = *prate / div;
+
+   return mclk->freq;
+}
+
+static unsigned long stm32_sai_mclk_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct stm32_sai_mclk_data *mclk = to_mclk_data(hw);
+
+   return mclk->freq;
+}
+
+static int stm32_sai_mclk_set_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long parent_rate)
+{
+   struct stm32_sai_mclk_data *mclk = to_mclk_data(hw);
+   struct stm32_sai_sub_data *sai = mclk->sai_data;
+   unsigned int div;
+   int re

[PATCH 0/4] ASoC: stm32: sai: add mclk clock provider

2018-10-15 Thread Olivier Moysan
This patch set allows to use STM32 SAI interface as a master clock provider.
The Cirrus cs42l51 codec patch gives the example of the source code required on 
codec side,
to use SAI mclk provider.

These patches allow to cover the following use cases:
- SAI is master or slave and is master clock provider
- SAI is master or slave and is not master clock provider (another sai 
provides the mclk clock)

Implementation overview:
- mclk configuration
SAI is registered in clock framework:
- either as a mclk provider (optional in DT). SAI generates 
mclk when requested by DAPM
- or as a mclk consumer (optional in DT).
cs42l51 codec is configured as a mclk consumer (optional in DT)

- mclk power
A DAPM is registered in codec to handle mclk enable/disable (DAPM route 
is set in soundcard node)

- mclk rate:
mclk rate is computed at runtime from stream rate and mclk-fs ratio 
provided in DT
mclk rate is propagated through sysclk callback to the SAI which is 
mclk consumer.
The mclk rate is set exclusively to avoid concurrent rate requests on 
SAI master.

Regards
Olivier

Olivier Moysan (4):
  ASoC: dt-bindings: add mclk provider support to stm32 sai
  ASoC: dt-bindings: add mclk support to cs42l51
  ASoC: stm32: sai: set sai as mclk clock provider
  ASoC: cs42l51: add mclk support

 .../devicetree/bindings/sound/cs42l51.txt  |  17 ++
 .../devicetree/bindings/sound/st,stm32-sai.txt |   7 +
 .../devicetree/bindings/trivial-devices.txt|   1 -
 sound/soc/codecs/cs42l51.c |   8 +
 sound/soc/stm/stm32_sai.h  |   3 +
 sound/soc/stm/stm32_sai_sub.c  | 275 ++---
 6 files changed, 274 insertions(+), 37 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/cs42l51.txt

-- 
2.7.4



[PATCH 4/4] ASoC: cs42l51: add mclk support

2018-10-15 Thread Olivier Moysan
Add MCLK dapm to allow configuration of cirrus CS42l51
codec as a master clock consumer.

Signed-off-by: Olivier Moysan 
---
 sound/soc/codecs/cs42l51.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index 5080d7a3c279..eb40bff54cec 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -237,6 +237,10 @@ static const struct snd_soc_dapm_widget 
cs42l51_dapm_widgets[] = {
_adcr_mux_controls),
 };
 
+static const struct snd_soc_dapm_widget cs42l51_dapm_mclk_widgets[] = {
+   SND_SOC_DAPM_CLOCK_SUPPLY("MCLK")
+};
+
 static const struct snd_soc_dapm_route cs42l51_routes[] = {
{"HPL", NULL, "Left DAC"},
{"HPR", NULL, "Right DAC"},
@@ -487,6 +491,10 @@ static struct snd_soc_dai_driver cs42l51_dai = {
 static int cs42l51_component_probe(struct snd_soc_component *component)
 {
int ret, reg;
+   struct snd_soc_dapm_context *dapm;
+
+   dapm = snd_soc_component_get_dapm(component);
+   snd_soc_dapm_new_controls(dapm, cs42l51_dapm_mclk_widgets, 1);
 
/*
 * DAC configuration
-- 
2.7.4



[PATCH 1/2] ASoC: stm32: add clock dependency for sai

2018-10-22 Thread Olivier Moysan
Fixes: 8307b2afd386 ("ASoC: stm32: sai: set sai as mclk clock provider")

Add COMMON_CLK dependency for STM32 SAI,
as it is required by clock provider.

Signed-off-by: Olivier Moysan 
---
 sound/soc/stm/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 9b2681397dba..c66ffa72057e 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -3,6 +3,7 @@ menu "STMicroelectronics STM32 SOC audio support"
 config SND_SOC_STM32_SAI
tristate "STM32 SAI interface (Serial Audio Interface) support"
depends on (ARCH_STM32 && OF) || COMPILE_TEST
+   depends on COMMON_CLK
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
-- 
2.7.4



[PATCH 0/2] ASoC: stm32: sai: fix kbuild errors

2018-10-22 Thread Olivier Moysan
These patches fix following compilation errors:
- >> sound/soc/stm/stm32_sai_sub.c:260:16: error: field 'hw' has incomplete type
- >> sound/soc/stm/stm32_sai_sub.c:412:3: 
 warning: 'strncat' specified bound 6 equals source length 
[-Wstringop-overflow=]

Olivier Moysan (2):
  ASoC: stm32: add clock dependency for sai
  ASoC: stm32: sai: fix master clock naming

 sound/soc/stm/Kconfig | 1 +
 sound/soc/stm/stm32_sai_sub.c | 5 ++---
 2 files changed, 3 insertions(+), 3 deletions(-)

-- 
2.7.4



[PATCH 2/2] ASoC: stm32: sai: fix master clock naming

2018-10-22 Thread Olivier Moysan
Fixes: 8307b2afd386 ("ASoC: stm32: sai: set sai as mclk clock provider")

Fix warning issued by strncat when bound equals to source length.

Signed-off-by: Olivier Moysan 
---
 sound/soc/stm/stm32_sai_sub.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 31d22abd3204..ea05cc91aa05 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -404,12 +404,11 @@ static int stm32_sai_add_mclk_provider(struct 
stm32_sai_sub_data *sai)
 * String after "_" char is stripped in parent name.
 */
p = mclk_name;
-   while (*s && *s != '_' && (i < (SAI_MCLK_NAME_LEN - 6))) {
+   while (*s && *s != '_' && (i < (SAI_MCLK_NAME_LEN - 7))) {
*p++ = *s++;
i++;
}
-   STM_SAI_IS_SUB_A(sai) ?
-   strncat(p, "a_mclk", 6) : strncat(p, "b_mclk", 6);
+   STM_SAI_IS_SUB_A(sai) ? strcat(p, "a_mclk") : strcat(p, "b_mclk");
 
mclk->hw.init = CLK_HW_INIT(mclk_name, pname, _ops, 0);
mclk->sai_data = sai;
-- 
2.7.4



[PATCH 1/1] ASoC: cs42l51: fix mclk support

2018-10-19 Thread Olivier Moysan
Fixes: 5e8d63a726f8 ("ASoC: cs42l51: add mclk support")

The MCLK clock is made optional for cs42l51 codec.
However, ASoC DAPM clock supply widget, expects the clock to be defined
unconditionally.
Register MCLK DAPM conditionally in codec driver,
depending on clock presence in DT.

Signed-off-by: Olivier Moysan 
---
 sound/soc/codecs/cs42l51.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index eb40bff54cec..fd2bd74024c1 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -21,6 +21,7 @@
  *  - master mode *NOT* supported
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -41,6 +42,7 @@ enum master_slave_mode {
 
 struct cs42l51_private {
unsigned int mclk;
+   struct clk *mclk_handle;
unsigned int audio_mode;/* The mode (I2S or left-justified) */
enum master_slave_mode func;
 };
@@ -492,9 +494,13 @@ static int cs42l51_component_probe(struct 
snd_soc_component *component)
 {
int ret, reg;
struct snd_soc_dapm_context *dapm;
+   struct cs42l51_private *cs42l51;
 
+   cs42l51 = snd_soc_component_get_drvdata(component);
dapm = snd_soc_component_get_dapm(component);
-   snd_soc_dapm_new_controls(dapm, cs42l51_dapm_mclk_widgets, 1);
+
+   if (cs42l51->mclk_handle)
+   snd_soc_dapm_new_controls(dapm, cs42l51_dapm_mclk_widgets, 1);
 
/*
 * DAC configuration
@@ -548,6 +554,13 @@ int cs42l51_probe(struct device *dev, struct regmap 
*regmap)
 
dev_set_drvdata(dev, cs42l51);
 
+   cs42l51->mclk_handle = devm_clk_get(dev, "MCLK");
+   if (IS_ERR(cs42l51->mclk_handle)) {
+   if (PTR_ERR(cs42l51->mclk_handle) != -ENOENT)
+   return PTR_ERR(cs42l51->mclk_handle);
+   cs42l51->mclk_handle = NULL;
+   }
+
/* Verify that we have a CS42L51 */
ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, );
if (ret < 0) {
-- 
2.7.4



[PATCH 0/3] ASoC: stm32: sai: add support of iec958 controls

2018-03-13 Thread Olivier Moysan
This patchset adds support of iec958 controls to STM32 SAI driver.

The patch makes use of iec958 control status helpers previously proposed
and discussed through the following threads:
https://patchwork.kernel.org/patch/8062601/
https://patchwork.kernel.org/patch/8091551/ (v2)
https://patchwork.kernel.org/patch/8462961/ (v3)
https://patchwork.kernel.org/patch/8533731/ (v4)

Olivier Moysan (3):
  ALSA: pcm: add IEC958 channel status control helper
  ASoC: stm32: sai: add iec958 controls support
  ASoC: dmaengine_pcm: document process callback

 include/sound/dmaengine_pcm.h |   2 +
 include/sound/pcm_iec958.h|  19 +++
 sound/core/pcm_iec958.c   | 114 ++
 sound/soc/stm/Kconfig |   1 +
 sound/soc/stm/stm32_sai_sub.c | 101 -
 5 files changed, 225 insertions(+), 12 deletions(-)

-- 
1.9.1



[PATCH 2/3] ASoC: stm32: sai: add iec958 controls support

2018-03-13 Thread Olivier Moysan
Add support of iec958 controls for STM32 SAI.

Signed-off-by: Olivier Moysan 
---
 sound/core/pcm_iec958.c   |   1 +
 sound/soc/stm/Kconfig |   1 +
 sound/soc/stm/stm32_sai_sub.c | 101 +-
 3 files changed, 91 insertions(+), 12 deletions(-)

diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
index aba1f522e98a..c34735ac3c48 100644
--- a/sound/core/pcm_iec958.c
+++ b/sound/core/pcm_iec958.c
@@ -19,6 +19,7 @@ static int snd_pcm_iec958_info(struct snd_kcontrol *kcontrol,
 {
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
+
return 0;
 }
 
diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 48f9ddd94016..9b2681397dba 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -6,6 +6,7 @@ config SND_SOC_STM32_SAI
depends on SND_SOC
select SND_SOC_GENERIC_DMAENGINE_PCM
select REGMAP_MMIO
+   select SND_PCM_IEC958
help
  Say Y if you want to enable SAI for STM32
 
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index cfeb219e1d78..c2e487e133aa 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "stm32_sai.h"
@@ -96,7 +97,7 @@
  * @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
+ * @snd_aes_iec958: iec958 data
  */
 struct stm32_sai_sub_data {
struct platform_device *pdev;
@@ -125,7 +126,7 @@ struct stm32_sai_sub_data {
int slot_mask;
int data_size;
unsigned int spdif_frm_cnt;
-   unsigned char spdif_status_bits[SAI_IEC60958_STATUS_BYTES];
+   struct snd_aes_iec958 iec958;
 };
 
 enum stm32_sai_fifo_th {
@@ -184,10 +185,6 @@ 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,
@@ -619,6 +616,59 @@ static void stm32_sai_set_frame(struct snd_soc_dai 
*cpu_dai)
}
 }
 
+static void stm32_sai_set_channel_status(struct stm32_sai_sub_data *sai,
+struct snd_pcm_runtime *runtime)
+{
+   if (!runtime)
+   return;
+
+   /* Force the sample rate according to runtime rate */
+   switch (runtime->rate) {
+   case 22050:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_22050;
+   break;
+   case 44100:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_44100;
+   break;
+   case 88200:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_88200;
+   break;
+   case 176400:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_176400;
+   break;
+   case 24000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_24000;
+   break;
+   case 48000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_48000;
+   break;
+   case 96000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_96000;
+   break;
+   case 192000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_192000;
+   break;
+   case 32000:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_32000;
+   break;
+   default:
+   sai->iec958.status[3] = IEC958_AES3_CON_FS_NOTID;
+   break;
+   }
+}
+
+static int stm32_sai_iec958_set(struct snd_pcm_iec958_params *iec_param)
+{
+   struct stm32_sai_sub_data *sai = iec_param->private_data;
+
+   if (!sai->substream)
+   return 0;
+
+   stm32_sai_set_channel_status(sai, sai->substream->runtime);
+
+   return 0;
+}
+
 static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
 struct snd_pcm_hw_params *params)
 {
@@ -709,7 +759,11 @@ static int stm32_sai_hw_params(struct snd_pcm_substream 
*substream,
 
sai->data_size = params_width(params);
 
-   if (!STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+   if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+   /* Rate not already set in runtime structure */
+   substream->runtime->rate = params_rate(params);
+   stm32_sai_set_channel_status(sai, substream->runtime);
+   } else {
ret = stm32_sai_set_slots(cpu_dai);
if (ret < 0)
return ret;
@@ -789,6 +843,28 @@ static void stm32_sai_shutdown(struct snd_pcm_substream 
*substream,
sai->subst

[PATCH 1/3] ALSA: pcm: add IEC958 channel status control helper

2018-03-13 Thread Olivier Moysan
From: Arnaud Pouliquen 

Add IEC958 channel status helper that creates control to handle the
IEC60958 status bits.

Signed-off-by: Arnaud Pouliquen 
Signed-off-by: Olivier Moysan 
---
 include/sound/pcm_iec958.h |  19 
 sound/core/pcm_iec958.c| 113 +
 2 files changed, 132 insertions(+)

diff --git a/include/sound/pcm_iec958.h b/include/sound/pcm_iec958.h
index 0939aa45e2fe..3c9701a9b1b0 100644
--- a/include/sound/pcm_iec958.h
+++ b/include/sound/pcm_iec958.h
@@ -4,9 +4,28 @@
 
 #include 
 
+/**
+ * struct snd_pcm_iec958_params: IEC 60958 controls parameters
+ * @ctrl_set: control set callback
+ * This callback is optional and shall be used to set associated driver
+ * configuration.
+ * @iec: Mandatory pointer to iec958 structure.
+ * @cs: Mandatory pointer to AES/IEC958  channel status bits.
+ * @cs_len: size in byte of the AES/IEC958  channel status bits.
+ * @private_data: Optional private pointer to driver context.
+ */
+struct snd_pcm_iec958_params {
+   int (*ctrl_set)(struct snd_pcm_iec958_params *iec_param);
+   unsigned char *cs;
+   unsigned char cs_len;
+   void *private_data;
+};
+
 int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
size_t len);
 
 int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
 u8 *cs, size_t len);
+int snd_pcm_add_iec958_ctl(struct snd_pcm *pcm, int subdevice, int stream,
+  struct snd_pcm_iec958_params *params);
 #endif
diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
index 5e6aed64f451..aba1f522e98a 100644
--- a/sound/core/pcm_iec958.c
+++ b/sound/core/pcm_iec958.c
@@ -7,11 +7,88 @@
  */
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
+static int snd_pcm_iec958_info(struct snd_kcontrol *kcontrol,
+  struct snd_ctl_elem_info *uinfo)
+{
+   uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+   uinfo->count = 1;
+   return 0;
+}
+
+/*
+ * IEC958 channel status default controls callbacks
+ */
+static int snd_pcm_iec958_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uctl)
+{
+   struct snd_pcm_iec958_params *params = snd_kcontrol_chip(kcontrol);
+   int i;
+
+   for (i = 0; i < params->cs_len; i++)
+   uctl->value.iec958.status[i] = params->cs[i];
+
+   return 0;
+}
+
+static int snd_pcm_iec958_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uctl)
+{
+   struct snd_pcm_iec958_params *params = snd_kcontrol_chip(kcontrol);
+   int err = 0;
+   unsigned int i, updated = 0;
+   unsigned char old_status[5];
+
+   for (i = 0; i < params->cs_len; i++) {
+   if (params->cs[i] != uctl->value.iec958.status[i])
+   updated = 1;
+   }
+
+   if (!updated)
+   return 0;
+
+   /* Store current status to restore them in error case */
+   for (i = 0; i < params->cs_len; i++) {
+   old_status[i] = params->cs[i];
+   params->cs[i] = uctl->value.iec958.status[i];
+   }
+
+   if (params->ctrl_set)
+   err = params->ctrl_set(params);
+   if (err < 0) {
+   for (i = 0; i < params->cs_len; i++)
+   params->cs[i] = old_status[i];
+   }
+
+   return err;
+}
+
+static const struct snd_kcontrol_new iec958_ctls[] = {
+   {
+   .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+  SNDRV_CTL_ELEM_ACCESS_VOLATILE),
+   .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+   .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+   .info = snd_pcm_iec958_info,
+   .get = snd_pcm_iec958_get,
+   .put = snd_pcm_iec958_put,
+   },
+   {
+   .access = (SNDRV_CTL_ELEM_ACCESS_READ |
+  SNDRV_CTL_ELEM_ACCESS_VOLATILE),
+   .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+   .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
+   .info = snd_pcm_iec958_info,
+   .get = snd_pcm_iec958_get,
+   },
+};
+
 static int create_iec958_consumer(uint rate, uint sample_width,
  u8 *cs, size_t len)
 {
@@ -21,6 +98,9 @@ static int create_iec958_consumer(uint rate, uint 
sample_width,
return -EINVAL;
 
switch (rate) {
+   case 0:
+   fs = IEC958_AES3_CON_FS_NOTID;
+   break;
case 32000:
fs = IEC958_AES3_CON_FS_32000;
break;
@@ -48,6 +128,9 @@ static int create_iec958_consumer(uint rate, uint 
sample_width,
 
if (len > 4) {
switch (sample_width) {
+   case 0:
+  

[PATCH 3/3] ASoC: dmaengine_pcm: document process callback

2018-03-13 Thread Olivier Moysan
Add missing description of process callback.

Fixes: 78648092ef46 ("ASoC: dmaengine_pcm: add processing support")
Signed-off-by: Olivier Moysan 
---
 include/sound/dmaengine_pcm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index 47ef486852ed..e3481eebdd98 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -118,6 +118,8 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
  *   PCM substream. Will be called from the PCM drivers hwparams callback.
  * @compat_request_channel: Callback to request a DMA channel for platforms
  *   which do not use devicetree.
+ * @process: Callback used to apply processing on samples transferred from/to
+ *   user space.
  * @compat_filter_fn: Will be used as the filter function when requesting a
  *  channel for platforms which do not use devicetree. The filter parameter
  *  will be the DAI's DMA data.
-- 
1.9.1



  1   2   3   4   >