linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/13] Extend AHUB audio support for Tegra210 and later
@ 2021-08-27  9:33 Sameer Pujar
  2021-08-27  9:33 ` [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE Sameer Pujar
                   ` (13 more replies)
  0 siblings, 14 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

Earlier as part of series [0], support for ADMAIF and I/O modules (such
as I2S, DMIC and DSPK) was added. This series aims at exposing some of
the AHUB internal modules (listed below), which can be used for audio
pre or post processing.

  * SFC (Sampling Frequency Converter)
  * MVC (Master Volume Control)
  * AMX (Audio Multiplexer)
  * ADX (Audio Demultiplexer)
  * Mixer

These modules can be plugged into audio paths and relevant processing
can be done. The MUX routes are extended to allow add or remove above
modules in the path via mixer controls. This is similar to how specific
ADMAIF channels are connected to relevant I/O module instances at the
moment.

Some of these modules can alter PCM parameters. Consider example of
resampler (44.1 -> 48 kHz) in the path.

  aplay(44.1 kHz) -> ADMAIF -> SFC -> (48 kHz) I2S -> (48kHz) Codec

The modules following SFC should be using converted sample rate and DAIs
need to be configured accordingly. The audio-graph driver provides a
mechanism to fixup the new parameters which can be specified in DT for a
given DAI. Then core uses these new values via fixup callback and then
pass it to respective DAIs hw_param() callback. The "convert-rate",
described in [1], property can be used when there is rate conversion in
the audio path. Similarly "convert-channels" can be used when there is
channel conversion in the path. There is no "convert-xxx" property for
sample size conversions. It can be added if necessary.

[0] https://www.lkml.org/lkml/2020/7/21/1357
[1] Documentation/devicetree/bindings/sound/audio-graph-port.yaml 

Sameer Pujar (13):
  ASoC: soc-pcm: Don't reconnect an already active BE
  ASoC: simple-card-utils: Increase maximum DAI links limit to 512
  ASoC: audio-graph: Fixup CPU endpoint hw_params in a BE<->BE link
  ASoC: dt-bindings: tegra: Few more Tegra210 AHUB modules
  ASoC: tegra: Add routes for few AHUB modules
  ASoC: tegra: Add Tegra210 based MVC driver
  ASoC: tegra: Add Tegra210 based SFC driver
  ASoC: tegra: Add Tegra210 based AMX driver
  ASoC: tegra: Add Tegra210 based ADX driver
  ASoC: tegra: Add Tegra210 based Mixer driver
  arm64: defconfig: Enable few Tegra210 based AHUB drivers
  arm64: tegra: Add few AHUB devices for Tegra210 and later
  arm64: tegra: Extend APE audio support on Jetson platforms

 .../bindings/sound/nvidia,tegra210-adx.yaml        |   74 +
 .../bindings/sound/nvidia,tegra210-ahub.yaml       |   20 +
 .../bindings/sound/nvidia,tegra210-amx.yaml        |   72 +
 .../bindings/sound/nvidia,tegra210-mixer.yaml      |   67 +
 .../bindings/sound/nvidia,tegra210-mvc.yaml        |   79 +
 .../bindings/sound/nvidia,tegra210-sfc.yaml        |   76 +
 arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts | 1554 ++++++++-
 arch/arm64/boot/dts/nvidia/tegra186.dtsi           |  120 +
 arch/arm64/boot/dts/nvidia/tegra194-p2972-0000.dts | 1493 ++++++++-
 .../arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi | 1520 ++++++++-
 arch/arm64/boot/dts/nvidia/tegra194.dtsi           |  116 +
 arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts |  876 +++++
 arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts |  876 +++++
 arch/arm64/boot/dts/nvidia/tegra210.dtsi           |   77 +
 arch/arm64/configs/defconfig                       |    5 +
 include/sound/simple_card_utils.h                  |    2 +-
 sound/soc/generic/audio-graph-card.c               |    4 +-
 sound/soc/soc-pcm.c                                |    4 +
 sound/soc/tegra/Kconfig                            |   48 +
 sound/soc/tegra/Makefile                           |   10 +
 sound/soc/tegra/tegra210_adx.c                     |  527 +++
 sound/soc/tegra/tegra210_adx.h                     |   72 +
 sound/soc/tegra/tegra210_ahub.c                    |  511 ++-
 sound/soc/tegra/tegra210_amx.c                     |  595 ++++
 sound/soc/tegra/tegra210_amx.h                     |   93 +
 sound/soc/tegra/tegra210_mixer.c                   |  667 ++++
 sound/soc/tegra/tegra210_mixer.h                   |  100 +
 sound/soc/tegra/tegra210_mvc.c                     |  629 ++++
 sound/soc/tegra/tegra210_mvc.h                     |  117 +
 sound/soc/tegra/tegra210_sfc.c                     | 3542 ++++++++++++++++++++
 sound/soc/tegra/tegra210_sfc.h                     |   78 +
 31 files changed, 13601 insertions(+), 423 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml
 create mode 100644 sound/soc/tegra/tegra210_adx.c
 create mode 100644 sound/soc/tegra/tegra210_adx.h
 create mode 100644 sound/soc/tegra/tegra210_amx.c
 create mode 100644 sound/soc/tegra/tegra210_amx.h
 create mode 100644 sound/soc/tegra/tegra210_mixer.c
 create mode 100644 sound/soc/tegra/tegra210_mixer.h
 create mode 100644 sound/soc/tegra/tegra210_mvc.c
 create mode 100644 sound/soc/tegra/tegra210_mvc.h
 create mode 100644 sound/soc/tegra/tegra210_sfc.c
 create mode 100644 sound/soc/tegra/tegra210_sfc.h

-- 
2.7.4


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

* [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-09-28 21:25   ` Pierre-Louis Bossart
  2021-08-27  9:33 ` [PATCH 02/13] ASoC: simple-card-utils: Increase maximum DAI links limit to 512 Sameer Pujar
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

In some cases, multiple FE components have the same BE component in their
respective DPCM paths. One such example would be a mixer component, which
can receive two or more inputs and sends a mixed output. In such cases,
to avoid reconfiguration of already active DAI (mixer output DAI in this
case), check the BE stream state to filter out the redundancy.

In summary, allow connection of BE if the respective current stream state
is either NEW or CLOSED.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 sound/soc/soc-pcm.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 48f71bb..e30cb5a 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1395,6 +1395,10 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
 		if (!fe->dpcm[stream].runtime && !fe->fe_compr)
 			continue;
 
+		if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
+		    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
+			continue;
+
 		/* newly connected FE and BE */
 		err = dpcm_be_connect(fe, be, stream);
 		if (err < 0) {
-- 
2.7.4


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

* [PATCH 02/13] ASoC: simple-card-utils: Increase maximum DAI links limit to 512
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
  2021-08-27  9:33 ` [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-08-27  9:33 ` [PATCH 03/13] ASoC: audio-graph: Fixup CPU endpoint hw_params in a BE<->BE link Sameer Pujar
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

The current limit of 128 is not sufficient when more components are
added to the audio map on Tegra210 and later platforms. Thus it is
resulting in probe failure.

The requirement is of nearly ~200 DAI links. To give sufficient room
for future additions the maximum limit is increased to 512 DAI links.
This is a preparatory patch to add more components like resampler,
mixer, multiplexers, demultiplexers and volume controllers to Tegra210
and later platforms.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 include/sound/simple_card_utils.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index 51b3b48..6b78034 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -115,7 +115,7 @@ struct asoc_simple_priv {
 		     ((codec) = simple_props_to_dai_codec(props, i));	\
 	     (i)++)
 
-#define SNDRV_MAX_LINKS 128
+#define SNDRV_MAX_LINKS 512
 
 struct link_info {
 	int link; /* number of link */
-- 
2.7.4


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

* [PATCH 03/13] ASoC: audio-graph: Fixup CPU endpoint hw_params in a BE<->BE link
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
  2021-08-27  9:33 ` [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE Sameer Pujar
  2021-08-27  9:33 ` [PATCH 02/13] ASoC: simple-card-utils: Increase maximum DAI links limit to 512 Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-08-27  9:33 ` [PATCH 04/13] ASoC: dt-bindings: tegra: Few more Tegra210 AHUB modules Sameer Pujar
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

When multiple components are connected back to back in an audio path,
hw_param fixup may be required for CPU or Codec endpoint of BE<->BE
DAI links. Currently fixup support is available for Codec and this
commit adds similar feature for CPU endpoint of a BE<->BE link.

For example a resampler component can be plugged into an audio path.
  [ FE -> BE1 -> ... -> resampler -> ... BEn ]

The resampler DAI links can be:
  BEx (CPU)              -> resampler input (Codec)
  resampler output (CPU) -> BEy (Codec)

Thus input and output sample rate parameters for resampler can be
fixed up as per the resample requirement.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/generic/audio-graph-card.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 5e71382..7439122 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -309,8 +309,10 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 		 * For example: FE <-> BE1 <-> BE2 <-> ... <-> BEn where
 		 * there are 'n' BE components in the path.
 		 */
-		if (card->component_chaining && !soc_component_is_pcm(cpus))
+		if (card->component_chaining && !soc_component_is_pcm(cpus)) {
 			dai_link->no_pcm = 1;
+			dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup;
+		}
 
 		asoc_simple_canonicalize_cpu(cpus, is_single_links);
 	} else {
-- 
2.7.4


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

* [PATCH 04/13] ASoC: dt-bindings: tegra: Few more Tegra210 AHUB modules
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (2 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 03/13] ASoC: audio-graph: Fixup CPU endpoint hw_params in a BE<->BE link Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-08-31 20:21   ` Rob Herring
  2021-08-27  9:33 ` [PATCH 05/13] ASoC: tegra: Add routes for few " Sameer Pujar
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

This patch adds YAML schema for DT bindings of few AHUB modules.
These devices will be registered as ASoC components and bindings
will be used on Tegra210 and later chips. The bindings for below
mentioned modules are added:

 * SFC (Sampling Frequency Converter)
 * MVC (Master Volume Control)
 * AMX (Audio Multiplexer)
 * ADX (Audio Demultiplexer)
 * Mixer

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
Cc: Rob Herring <robh+dt@kernel.org> 
---
 .../bindings/sound/nvidia,tegra210-adx.yaml        | 74 ++++++++++++++++++++
 .../bindings/sound/nvidia,tegra210-ahub.yaml       | 20 ++++++
 .../bindings/sound/nvidia,tegra210-amx.yaml        | 72 ++++++++++++++++++++
 .../bindings/sound/nvidia,tegra210-mixer.yaml      | 67 ++++++++++++++++++
 .../bindings/sound/nvidia,tegra210-mvc.yaml        | 79 ++++++++++++++++++++++
 .../bindings/sound/nvidia,tegra210-sfc.yaml        | 76 +++++++++++++++++++++
 6 files changed, 388 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml

diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
new file mode 100644
index 0000000..9950585
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/nvidia,tegra210-adx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Tegra210 ADX Device Tree Bindings
+
+description: |
+  The Audio Demultiplexer (ADX) block takes an input stream with   up to
+  16 channels and demultiplexes it into four output streams of up to 16
+  channels each. A byte RAM helps to form output frames by any combination
+  of bytes from the input frame. Its design is identical to that of byte
+  RAM in the AMX except that the data flow direction is reversed.
+
+maintainers:
+  - Jon Hunter <jonathanh@nvidia.com>
+  - Mohan Kumar <mkumard@nvidia.com>
+  - Sameer Pujar <spujar@nvidia.com>
+
+properties:
+  $nodename:
+    pattern: "^adx@[0-9a-f]*$"
+
+  compatible:
+    oneOf:
+      - const: nvidia,tegra210-adx
+      - items:
+          - enum:
+              - nvidia,tegra194-adx
+              - nvidia,tegra186-adx
+          - const: nvidia,tegra210-adx
+
+  reg:
+    maxItems: 1
+
+  sound-name-prefix:
+    pattern: "^ADX[1-9]$"
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      used as prefix for sink/source names of the component. Must be a
+      unique string among multiple instances of the same component.
+      The name can be "ADX1" or "ADX2" ... "ADXx", where x depends on
+      the maximum available instances on a Tegra SoC.
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+    description: |
+      ADX has one input and four output. Accordingly ACIF (Audio Client
+      Interface) RX and TX port nodes are defined to represent ADX inputs
+      and output respectively. These are connected to corresponding ports
+      on AHUB.
+
+    patternProperties:
+      '^port@[0-9]':
+        $ref: audio-graph-port.yaml#
+        unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+
+    adx@702d3800 {
+        compatible = "nvidia,tegra210-adx";
+        reg = <0x702d3800 0x100>;
+        sound-name-prefix = "ADX1";
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml
index 1118a94..4087eeb 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml
@@ -85,6 +85,26 @@ patternProperties:
     type: object
     $ref: nvidia,tegra186-dspk.yaml#
 
+  '^mvc@[0-9a-f]+$':
+    type: object
+    $ref: nvidia,tegra210-mvc.yaml#
+
+  '^sfc@[0-9a-f]+$':
+    type: object
+    $ref: nvidia,tegra210-sfc.yaml#
+
+  '^amx@[0-9a-f]+$':
+    type: object
+    $ref: nvidia,tegra210-amx.yaml#
+
+  '^adx@[0-9a-f]+$':
+    type: object
+    $ref: nvidia,tegra210-adx.yaml#
+
+  '^mixer@[0-9a-f]+$':
+    type: object
+    $ref: nvidia,tegra210-mixer.yaml#
+
 required:
   - compatible
   - reg
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
new file mode 100644
index 0000000..e6b365b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/nvidia,tegra210-amx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Tegra210 AMX Device Tree Bindings
+
+description: |
+  The Audio Multiplexer (AMX) block can multiplex up to four input streams
+  each of which can have maximum 16 channels and generate an output stream
+  with maximum 16 channels. A byte RAM helps to form an output frame by
+  any combination of bytes from the input frames.
+
+maintainers:
+  - Jon Hunter <jonathanh@nvidia.com>
+  - Mohan Kumar <mkumard@nvidia.com>
+  - Sameer Pujar <spujar@nvidia.com>
+
+properties:
+  $nodename:
+    pattern: "^amx@[0-9a-f]*$"
+
+  compatible:
+    oneOf:
+      - const: nvidia,tegra210-amx
+      - items:
+          - const: nvidia,tegra186-amx
+          - const: nvidia,tegra210-amx
+      - const: nvidia,tegra194-amx
+
+  reg:
+    maxItems: 1
+
+  sound-name-prefix:
+    pattern: "^AMX[1-9]$"
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      used as prefix for sink/source names of the component. Must be a
+      unique string among multiple instances of the same component.
+      The name can be "AMX1" or "AMX2" ... "AMXx", where x depends on
+      the maximum available instances on a Tegra SoC.
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+    description: |
+      AMX has four inputs and one output. Accordingly ACIF (Audio Client
+      Interfaces) RX and TX port nodes are defined to represent AMX inputs
+      and output respectively. These are connected to corresponding ports
+      on AHUB.
+
+    patternProperties:
+      '^port@[0-9]':
+        $ref: audio-graph-port.yaml#
+        unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+
+    amx@702d3000 {
+        compatible = "nvidia,tegra210-amx";
+        reg = <0x702d3000 0x100>;
+        sound-name-prefix = "AMX1";
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
new file mode 100644
index 0000000..0808355
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/nvidia,tegra210-mixer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Tegra210 Mixer Device Tree Bindings
+
+description: |
+  The Mixer supports mixing of up to ten 7.1 audio input streams and
+  generate five outputs (each of which can be any combination of the
+  ten input streams).
+
+maintainers:
+  - Jon Hunter <jonathanh@nvidia.com>
+  - Mohan Kumar <mkumard@nvidia.com>
+  - Sameer Pujar <spujar@nvidia.com>
+
+properties:
+  $nodename:
+    pattern: "^mixer@[0-9a-f]*$"
+
+  compatible:
+    oneOf:
+      - const: nvidia,tegra210-amixer
+      - items:
+          - enum:
+              - nvidia,tegra194-amixer
+              - nvidia,tegra186-amixer
+          - const: nvidia,tegra210-amixer
+
+  reg:
+    maxItems: 1
+
+  sound-name-prefix:
+    const: "MIXER"
+    $ref: /schemas/types.yaml#/definitions/string
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+    description: |
+      Mixer has ten inputs and five outputs. Accordingly ACIF (Audio Client
+      Interfaces) RX and TX port nodes are defined to represent MIXER inputs
+      and outputs respectively. These are connected to corresponding ports
+      on AHUB.
+
+    patternProperties:
+      '^port@[0-9]':
+        $ref: audio-graph-port.yaml#
+        unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+
+    mixer@702dbb00 {
+        compatible = "nvidia,tegra210-amixer";
+        reg = <0x702dbb00 0x800>;
+        sound-name-prefix = "MIXER";
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
new file mode 100644
index 0000000..7d81b11
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/nvidia,tegra210-mvc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Tegra210 MVC Device Tree Bindings
+
+description: |
+  The Master Volume Control (MVC) provides gain or attenuation to a digital
+  signal path. It can be used in input or output signal path for per-stream
+  volume control or it can be used as master volume control. The MVC block
+  has one input and one output. The input digital stream can be mono or
+  multi-channel (up to 7.1 channels) stream. An independent mute control is
+  also included in the MVC block.
+
+maintainers:
+  - Jon Hunter <jonathanh@nvidia.com>
+  - Mohan Kumar <mkumard@nvidia.com>
+  - Sameer Pujar <spujar@nvidia.com>
+
+properties:
+  $nodename:
+    pattern: "^mvc@[0-9a-f]*$"
+
+  compatible:
+    oneOf:
+      - const: nvidia,tegra210-mvc
+      - items:
+          - enum:
+              - nvidia,tegra194-mvc
+              - nvidia,tegra186-mvc
+          - const: nvidia,tegra210-mvc
+
+  reg:
+    maxItems: 1
+
+  sound-name-prefix:
+    pattern: "^MVC[1-9]$"
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      used as prefix for sink/source names of the component. Must be a
+      unique string among multiple instances of the same component.
+      The name can be "MVC1" or "MVC2" ... "MVCx", where x depends on
+      the maximum available instances on a Tegra SoC.
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+    properties:
+      port@0:
+        $ref: audio-graph-port.yaml#
+        unevaluatedProperties: false
+        description: |
+          ACIF (Audio Client Interface) acting as MVC input (RX) port.
+          This is connected to corresponding ACIF port on AHUB.
+
+      port@1:
+        $ref: audio-graph-port.yaml#
+        unevaluatedProperties: false
+        description: |
+          ACIF (Audio Client Interface) acting as MVC output (TX) port.
+          This is connected to corresponding ACIF port on AHUB.
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+
+    mvc@702da000 {
+        compatible = "nvidia,tegra210-mvc";
+        reg = <0x702da000 0x200>;
+        sound-name-prefix = "MVC1";
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml
new file mode 100644
index 0000000..5f05e2a
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/nvidia,tegra210-sfc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Tegra210 SFC Device Tree Bindings
+
+description: |
+  The Sampling Frequency Converter (SFC) converts the sampling frequency
+  of the input signal from one frequency to another. It supports sampling
+  frequency conversions of streams of up to two channels (stereo).
+
+maintainers:
+  - Jon Hunter <jonathanh@nvidia.com>
+  - Mohan Kumar <mkumard@nvidia.com>
+  - Sameer Pujar <spujar@nvidia.com>
+
+properties:
+  $nodename:
+    pattern: "^sfc@[0-9a-f]*$"
+
+  compatible:
+    oneOf:
+      - const: nvidia,tegra210-sfc
+      - items:
+          - enum:
+              - nvidia,tegra194-sfc
+              - nvidia,tegra186-sfc
+          - const: nvidia,tegra210-sfc
+
+  reg:
+    maxItems: 1
+
+  sound-name-prefix:
+    pattern: "^SFC[1-9]$"
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      used as prefix for sink/source names of the component. Must be a
+      unique string among multiple instances of the same component.
+      The name can be "SFC1" or "SFC2" ... "SFCx", where x depends on
+      the maximum available instances on a Tegra SoC.
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+    properties:
+      port@0:
+        $ref: audio-graph-port.yaml#
+        unevaluatedProperties: false
+        description: |
+          ACIF (Audio Client Interface) acting as SFC input (RX) port.
+          This is connected to corresponding ACIF port on AHUB.
+
+      port@1:
+        $ref: audio-graph-port.yaml#
+        unevaluatedProperties: false
+        description: |
+          ACIF (Audio Client Interface) acting as SFC output (TX) port.
+          This is connected to corresponding ACIF port on AHUB.
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+
+    sfc@702d2000 {
+        compatible = "nvidia,tegra210-sfc";
+        reg = <0x702d2000 0x200>;
+        sound-name-prefix = "SFC1";
+    };
+
+...
-- 
2.7.4


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

* [PATCH 05/13] ASoC: tegra: Add routes for few AHUB modules
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (3 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 04/13] ASoC: dt-bindings: tegra: Few more Tegra210 AHUB modules Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-08-27  9:33 ` [PATCH 06/13] ASoC: tegra: Add Tegra210 based MVC driver Sameer Pujar
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

Add routing support for following modules of AHUB:
 * SFC (Sampling Frequency Converter)
 * MVC (Master Volume Control)
 * AMX (Audio Multiplexer)
 * ADX (Audio Demultiplexer)
 * Mixer

These modules can be plugged into audio path as per the need using
routing controls similar to the already existing routes to I/O modules
such as I2S, DMIC and DSPK.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 sound/soc/tegra/tegra210_ahub.c | 511 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 509 insertions(+), 2 deletions(-)

diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c
index 66287a7..44a1ee0 100644
--- a/sound/soc/tegra/tegra210_ahub.c
+++ b/sound/soc/tegra/tegra210_ahub.c
@@ -105,14 +105,68 @@ static struct snd_soc_dai_driver tegra210_ahub_dais[] = {
 	DAI(ADMAIF8),
 	DAI(ADMAIF9),
 	DAI(ADMAIF10),
+	/* XBAR <-> I2S <-> Codec */
 	DAI(I2S1),
 	DAI(I2S2),
 	DAI(I2S3),
 	DAI(I2S4),
 	DAI(I2S5),
+	/* XBAR <- DMIC <- Codec */
 	DAI(DMIC1),
 	DAI(DMIC2),
 	DAI(DMIC3),
+	/* XBAR -> SFC -> XBAR */
+	DAI(SFC1 RX),
+	DAI(SFC1 TX),
+	DAI(SFC2 RX),
+	DAI(SFC2 TX),
+	DAI(SFC3 RX),
+	DAI(SFC3 TX),
+	DAI(SFC4 RX),
+	DAI(SFC4 TX),
+	/* XBAR -> MVC -> XBAR */
+	DAI(MVC1 RX),
+	DAI(MVC1 TX),
+	DAI(MVC2 RX),
+	DAI(MVC2 TX),
+	/* XBAR -> AMX(4:1) -> XBAR */
+	DAI(AMX1 RX1),
+	DAI(AMX1 RX2),
+	DAI(AMX1 RX3),
+	DAI(AMX1 RX4),
+	DAI(AMX1),
+	DAI(AMX2 RX1),
+	DAI(AMX2 RX2),
+	DAI(AMX2 RX3),
+	DAI(AMX2 RX4),
+	DAI(AMX2),
+	/* XBAR -> ADX(1:4) -> XBAR */
+	DAI(ADX1),
+	DAI(ADX1 TX1),
+	DAI(ADX1 TX2),
+	DAI(ADX1 TX3),
+	DAI(ADX1 TX4),
+	DAI(ADX2),
+	DAI(ADX2 TX1),
+	DAI(ADX2 TX2),
+	DAI(ADX2 TX3),
+	DAI(ADX2 TX4),
+	/* XBAR -> MIXER(10:5) -> XBAR */
+	DAI(MIXER RX1),
+	DAI(MIXER RX2),
+	DAI(MIXER RX3),
+	DAI(MIXER RX4),
+	DAI(MIXER RX5),
+	DAI(MIXER RX6),
+	DAI(MIXER RX7),
+	DAI(MIXER RX8),
+	DAI(MIXER RX9),
+	DAI(MIXER RX10),
+	DAI(MIXER TX1),
+	DAI(MIXER TX2),
+	DAI(MIXER TX3),
+	DAI(MIXER TX4),
+	DAI(MIXER TX5),
 };
 
 static struct snd_soc_dai_driver tegra186_ahub_dais[] = {
@@ -136,18 +190,93 @@ static struct snd_soc_dai_driver tegra186_ahub_dais[] = {
 	DAI(ADMAIF18),
 	DAI(ADMAIF19),
 	DAI(ADMAIF20),
+	/* XBAR <-> I2S <-> Codec */
 	DAI(I2S1),
 	DAI(I2S2),
 	DAI(I2S3),
 	DAI(I2S4),
 	DAI(I2S5),
 	DAI(I2S6),
+	/* XBAR <- DMIC <- Codec */
 	DAI(DMIC1),
 	DAI(DMIC2),
 	DAI(DMIC3),
 	DAI(DMIC4),
+	/* XBAR -> DSPK -> Codec */
 	DAI(DSPK1),
 	DAI(DSPK2),
+	/* XBAR -> SFC -> XBAR */
+	DAI(SFC1 RX),
+	DAI(SFC1 TX),
+	DAI(SFC2 RX),
+	DAI(SFC2 TX),
+	DAI(SFC3 RX),
+	DAI(SFC3 TX),
+	DAI(SFC4 RX),
+	DAI(SFC4 TX),
+	/* XBAR -> MVC -> XBAR */
+	DAI(MVC1 RX),
+	DAI(MVC1 TX),
+	DAI(MVC2 RX),
+	DAI(MVC2 TX),
+	/* XBAR -> AMX(4:1) -> XBAR */
+	DAI(AMX1 RX1),
+	DAI(AMX1 RX2),
+	DAI(AMX1 RX3),
+	DAI(AMX1 RX4),
+	DAI(AMX1),
+	DAI(AMX2 RX1),
+	DAI(AMX2 RX2),
+	DAI(AMX2 RX3),
+	DAI(AMX2 RX4),
+	DAI(AMX2),
+	DAI(AMX3 RX1),
+	DAI(AMX3 RX2),
+	DAI(AMX3 RX3),
+	DAI(AMX3 RX4),
+	DAI(AMX3),
+	DAI(AMX4 RX1),
+	DAI(AMX4 RX2),
+	DAI(AMX4 RX3),
+	DAI(AMX4 RX4),
+	DAI(AMX4),
+	/* XBAR -> ADX(1:4) -> XBAR */
+	DAI(ADX1),
+	DAI(ADX1 TX1),
+	DAI(ADX1 TX2),
+	DAI(ADX1 TX3),
+	DAI(ADX1 TX4),
+	DAI(ADX2),
+	DAI(ADX2 TX1),
+	DAI(ADX2 TX2),
+	DAI(ADX2 TX3),
+	DAI(ADX2 TX4),
+	DAI(ADX3),
+	DAI(ADX3 TX1),
+	DAI(ADX3 TX2),
+	DAI(ADX3 TX3),
+	DAI(ADX3 TX4),
+	DAI(ADX4),
+	DAI(ADX4 TX1),
+	DAI(ADX4 TX2),
+	DAI(ADX4 TX3),
+	DAI(ADX4 TX4),
+	/* XBAR -> MIXER(10:5) -> XBAR */
+	DAI(MIXER RX1),
+	DAI(MIXER RX2),
+	DAI(MIXER RX3),
+	DAI(MIXER RX4),
+	DAI(MIXER RX5),
+	DAI(MIXER RX6),
+	DAI(MIXER RX7),
+	DAI(MIXER RX8),
+	DAI(MIXER RX9),
+	DAI(MIXER RX10),
+	DAI(MIXER TX1),
+	DAI(MIXER TX2),
+	DAI(MIXER TX3),
+	DAI(MIXER TX4),
+	DAI(MIXER TX5),
 };
 
 static const char * const tegra210_ahub_mux_texts[] = {
@@ -170,6 +299,27 @@ static const char * const tegra210_ahub_mux_texts[] = {
 	"DMIC1",
 	"DMIC2",
 	"DMIC3",
+	"SFC1",
+	"SFC2",
+	"SFC3",
+	"SFC4",
+	"MVC1",
+	"MVC2",
+	"AMX1",
+	"AMX2",
+	"ADX1 TX1",
+	"ADX1 TX2",
+	"ADX1 TX3",
+	"ADX1 TX4",
+	"ADX2 TX1",
+	"ADX2 TX2",
+	"ADX2 TX3",
+	"ADX2 TX4",
+	"MIXER TX1",
+	"MIXER TX2",
+	"MIXER TX3",
+	"MIXER TX4",
+	"MIXER TX5",
 };
 
 static const char * const tegra186_ahub_mux_texts[] = {
@@ -204,10 +354,42 @@ static const char * const tegra186_ahub_mux_texts[] = {
 	"DMIC2",
 	"DMIC3",
 	"DMIC4",
+	"SFC1",
+	"SFC2",
+	"SFC3",
+	"SFC4",
+	"MVC1",
+	"MVC2",
+	"AMX1",
+	"AMX2",
+	"AMX3",
+	"AMX4",
+	"ADX1 TX1",
+	"ADX1 TX2",
+	"ADX1 TX3",
+	"ADX1 TX4",
+	"ADX2 TX1",
+	"ADX2 TX2",
+	"ADX2 TX3",
+	"ADX2 TX4",
+	"ADX3 TX1",
+	"ADX3 TX2",
+	"ADX3 TX3",
+	"ADX3 TX4",
+	"ADX4 TX1",
+	"ADX4 TX2",
+	"ADX4 TX3",
+	"ADX4 TX4",
+	"MIXER TX1",
+	"MIXER TX2",
+	"MIXER TX3",
+	"MIXER TX4",
+	"MIXER TX5",
 };
 
 static const unsigned int tegra210_ahub_mux_values[] = {
 	0,
+	/* ADMAIF */
 	MUX_VALUE(0, 0),
 	MUX_VALUE(0, 1),
 	MUX_VALUE(0, 2),
@@ -218,18 +400,47 @@ static const unsigned int tegra210_ahub_mux_values[] = {
 	MUX_VALUE(0, 7),
 	MUX_VALUE(0, 8),
 	MUX_VALUE(0, 9),
+	/* I2S */
 	MUX_VALUE(0, 16),
 	MUX_VALUE(0, 17),
 	MUX_VALUE(0, 18),
 	MUX_VALUE(0, 19),
 	MUX_VALUE(0, 20),
+	/* DMIC */
 	MUX_VALUE(2, 18),
 	MUX_VALUE(2, 19),
 	MUX_VALUE(2, 20),
+	/* SFC */
+	MUX_VALUE(0, 24),
+	MUX_VALUE(0, 25),
+	MUX_VALUE(0, 26),
+	MUX_VALUE(0, 27),
+	/* MVC */
+	MUX_VALUE(2, 8),
+	MUX_VALUE(2, 9),
+	/* AMX */
+	MUX_VALUE(1, 8),
+	MUX_VALUE(1, 9),
+	/* ADX */
+	MUX_VALUE(2, 24),
+	MUX_VALUE(2, 25),
+	MUX_VALUE(2, 26),
+	MUX_VALUE(2, 27),
+	MUX_VALUE(2, 28),
+	MUX_VALUE(2, 29),
+	MUX_VALUE(2, 30),
+	MUX_VALUE(2, 31),
+	/* MIXER */
+	MUX_VALUE(1, 0),
+	MUX_VALUE(1, 1),
+	MUX_VALUE(1, 2),
+	MUX_VALUE(1, 3),
+	MUX_VALUE(1, 4),
 };
 
 static const unsigned int tegra186_ahub_mux_values[] = {
 	0,
+	/* ADMAIF */
 	MUX_VALUE(0, 0),
 	MUX_VALUE(0, 1),
 	MUX_VALUE(0, 2),
@@ -246,20 +457,59 @@ static const unsigned int tegra186_ahub_mux_values[] = {
 	MUX_VALUE(0, 13),
 	MUX_VALUE(0, 14),
 	MUX_VALUE(0, 15),
+	/* I2S */
 	MUX_VALUE(0, 16),
 	MUX_VALUE(0, 17),
 	MUX_VALUE(0, 18),
 	MUX_VALUE(0, 19),
 	MUX_VALUE(0, 20),
 	MUX_VALUE(0, 21),
+	/* ADMAIF */
 	MUX_VALUE(3, 16),
 	MUX_VALUE(3, 17),
 	MUX_VALUE(3, 18),
 	MUX_VALUE(3, 19),
+	/* DMIC */
 	MUX_VALUE(2, 18),
 	MUX_VALUE(2, 19),
 	MUX_VALUE(2, 20),
 	MUX_VALUE(2, 21),
+	/* SFC */
+	MUX_VALUE(0, 24),
+	MUX_VALUE(0, 25),
+	MUX_VALUE(0, 26),
+	MUX_VALUE(0, 27),
+	/* MVC */
+	MUX_VALUE(2, 8),
+	MUX_VALUE(2, 9),
+	/* AMX */
+	MUX_VALUE(1, 8),
+	MUX_VALUE(1, 9),
+	MUX_VALUE(1, 10),
+	MUX_VALUE(1, 11),
+	/* ADX */
+	MUX_VALUE(2, 24),
+	MUX_VALUE(2, 25),
+	MUX_VALUE(2, 26),
+	MUX_VALUE(2, 27),
+	MUX_VALUE(2, 28),
+	MUX_VALUE(2, 29),
+	MUX_VALUE(2, 30),
+	MUX_VALUE(2, 31),
+	MUX_VALUE(3, 0),
+	MUX_VALUE(3, 1),
+	MUX_VALUE(3, 2),
+	MUX_VALUE(3, 3),
+	MUX_VALUE(3, 4),
+	MUX_VALUE(3, 5),
+	MUX_VALUE(3, 6),
+	MUX_VALUE(3, 7),
+	/* MIXER */
+	MUX_VALUE(1, 0),
+	MUX_VALUE(1, 1),
+	MUX_VALUE(1, 2),
+	MUX_VALUE(1, 3),
+	MUX_VALUE(1, 4),
 };
 
 /* Controls for t210 */
@@ -278,6 +528,32 @@ MUX_ENUM_CTRL_DECL(t210_i2s2_tx, 0x11);
 MUX_ENUM_CTRL_DECL(t210_i2s3_tx, 0x12);
 MUX_ENUM_CTRL_DECL(t210_i2s4_tx, 0x13);
 MUX_ENUM_CTRL_DECL(t210_i2s5_tx, 0x14);
+MUX_ENUM_CTRL_DECL(t210_sfc1_tx, 0x18);
+MUX_ENUM_CTRL_DECL(t210_sfc2_tx, 0x19);
+MUX_ENUM_CTRL_DECL(t210_sfc3_tx, 0x1a);
+MUX_ENUM_CTRL_DECL(t210_sfc4_tx, 0x1b);
+MUX_ENUM_CTRL_DECL(t210_mvc1_tx, 0x48);
+MUX_ENUM_CTRL_DECL(t210_mvc2_tx, 0x49);
+MUX_ENUM_CTRL_DECL(t210_amx11_tx, 0x50);
+MUX_ENUM_CTRL_DECL(t210_amx12_tx, 0x51);
+MUX_ENUM_CTRL_DECL(t210_amx13_tx, 0x52);
+MUX_ENUM_CTRL_DECL(t210_amx14_tx, 0x53);
+MUX_ENUM_CTRL_DECL(t210_amx21_tx, 0x54);
+MUX_ENUM_CTRL_DECL(t210_amx22_tx, 0x55);
+MUX_ENUM_CTRL_DECL(t210_amx23_tx, 0x56);
+MUX_ENUM_CTRL_DECL(t210_amx24_tx, 0x57);
+MUX_ENUM_CTRL_DECL(t210_adx1_tx, 0x58);
+MUX_ENUM_CTRL_DECL(t210_adx2_tx, 0x59);
+MUX_ENUM_CTRL_DECL(t210_mixer11_tx, 0x20);
+MUX_ENUM_CTRL_DECL(t210_mixer12_tx, 0x21);
+MUX_ENUM_CTRL_DECL(t210_mixer13_tx, 0x22);
+MUX_ENUM_CTRL_DECL(t210_mixer14_tx, 0x23);
+MUX_ENUM_CTRL_DECL(t210_mixer15_tx, 0x24);
+MUX_ENUM_CTRL_DECL(t210_mixer16_tx, 0x25);
+MUX_ENUM_CTRL_DECL(t210_mixer17_tx, 0x26);
+MUX_ENUM_CTRL_DECL(t210_mixer18_tx, 0x27);
+MUX_ENUM_CTRL_DECL(t210_mixer19_tx, 0x28);
+MUX_ENUM_CTRL_DECL(t210_mixer110_tx, 0x29);
 
 /* Controls for t186 */
 MUX_ENUM_CTRL_DECL_186(t186_admaif1_tx, 0x00);
@@ -308,6 +584,42 @@ MUX_ENUM_CTRL_DECL_186(t186_admaif17_tx, 0x68);
 MUX_ENUM_CTRL_DECL_186(t186_admaif18_tx, 0x69);
 MUX_ENUM_CTRL_DECL_186(t186_admaif19_tx, 0x6a);
 MUX_ENUM_CTRL_DECL_186(t186_admaif20_tx, 0x6b);
+MUX_ENUM_CTRL_DECL_186(t186_sfc1_tx, 0x18);
+MUX_ENUM_CTRL_DECL_186(t186_sfc2_tx, 0x19);
+MUX_ENUM_CTRL_DECL_186(t186_sfc3_tx, 0x1a);
+MUX_ENUM_CTRL_DECL_186(t186_sfc4_tx, 0x1b);
+MUX_ENUM_CTRL_DECL_186(t186_mvc1_tx, 0x48);
+MUX_ENUM_CTRL_DECL_186(t186_mvc2_tx, 0x49);
+MUX_ENUM_CTRL_DECL_186(t186_amx11_tx, 0x50);
+MUX_ENUM_CTRL_DECL_186(t186_amx12_tx, 0x51);
+MUX_ENUM_CTRL_DECL_186(t186_amx13_tx, 0x52);
+MUX_ENUM_CTRL_DECL_186(t186_amx14_tx, 0x53);
+MUX_ENUM_CTRL_DECL_186(t186_amx21_tx, 0x54);
+MUX_ENUM_CTRL_DECL_186(t186_amx22_tx, 0x55);
+MUX_ENUM_CTRL_DECL_186(t186_amx23_tx, 0x56);
+MUX_ENUM_CTRL_DECL_186(t186_amx24_tx, 0x57);
+MUX_ENUM_CTRL_DECL_186(t186_amx31_tx, 0x58);
+MUX_ENUM_CTRL_DECL_186(t186_amx32_tx, 0x59);
+MUX_ENUM_CTRL_DECL_186(t186_amx33_tx, 0x5a);
+MUX_ENUM_CTRL_DECL_186(t186_amx34_tx, 0x5b);
+MUX_ENUM_CTRL_DECL_186(t186_amx41_tx, 0x64);
+MUX_ENUM_CTRL_DECL_186(t186_amx42_tx, 0x65);
+MUX_ENUM_CTRL_DECL_186(t186_amx43_tx, 0x66);
+MUX_ENUM_CTRL_DECL_186(t186_amx44_tx, 0x67);
+MUX_ENUM_CTRL_DECL_186(t186_adx1_tx, 0x60);
+MUX_ENUM_CTRL_DECL_186(t186_adx2_tx, 0x61);
+MUX_ENUM_CTRL_DECL_186(t186_adx3_tx, 0x62);
+MUX_ENUM_CTRL_DECL_186(t186_adx4_tx, 0x63);
+MUX_ENUM_CTRL_DECL_186(t186_mixer11_tx, 0x20);
+MUX_ENUM_CTRL_DECL_186(t186_mixer12_tx, 0x21);
+MUX_ENUM_CTRL_DECL_186(t186_mixer13_tx, 0x22);
+MUX_ENUM_CTRL_DECL_186(t186_mixer14_tx, 0x23);
+MUX_ENUM_CTRL_DECL_186(t186_mixer15_tx, 0x24);
+MUX_ENUM_CTRL_DECL_186(t186_mixer16_tx, 0x25);
+MUX_ENUM_CTRL_DECL_186(t186_mixer17_tx, 0x26);
+MUX_ENUM_CTRL_DECL_186(t186_mixer18_tx, 0x27);
+MUX_ENUM_CTRL_DECL_186(t186_mixer19_tx, 0x28);
+MUX_ENUM_CTRL_DECL_186(t186_mixer110_tx, 0x29);
 
 /*
  * The number of entries in, and order of, this array is closely tied to the
@@ -333,6 +645,47 @@ static const struct snd_soc_dapm_widget tegra210_ahub_widgets[] = {
 	TX_WIDGETS("DMIC1"),
 	TX_WIDGETS("DMIC2"),
 	TX_WIDGETS("DMIC3"),
+	WIDGETS("SFC1", t210_sfc1_tx),
+	WIDGETS("SFC2", t210_sfc2_tx),
+	WIDGETS("SFC3", t210_sfc3_tx),
+	WIDGETS("SFC4", t210_sfc4_tx),
+	WIDGETS("MVC1", t210_mvc1_tx),
+	WIDGETS("MVC2", t210_mvc2_tx),
+	WIDGETS("AMX1 RX1", t210_amx11_tx),
+	WIDGETS("AMX1 RX2", t210_amx12_tx),
+	WIDGETS("AMX1 RX3", t210_amx13_tx),
+	WIDGETS("AMX1 RX4", t210_amx14_tx),
+	WIDGETS("AMX2 RX1", t210_amx21_tx),
+	WIDGETS("AMX2 RX2", t210_amx22_tx),
+	WIDGETS("AMX2 RX3", t210_amx23_tx),
+	WIDGETS("AMX2 RX4", t210_amx24_tx),
+	TX_WIDGETS("AMX1"),
+	TX_WIDGETS("AMX2"),
+	WIDGETS("ADX1", t210_adx1_tx),
+	WIDGETS("ADX2", t210_adx2_tx),
+	TX_WIDGETS("ADX1 TX1"),
+	TX_WIDGETS("ADX1 TX2"),
+	TX_WIDGETS("ADX1 TX3"),
+	TX_WIDGETS("ADX1 TX4"),
+	TX_WIDGETS("ADX2 TX1"),
+	TX_WIDGETS("ADX2 TX2"),
+	TX_WIDGETS("ADX2 TX3"),
+	TX_WIDGETS("ADX2 TX4"),
+	WIDGETS("MIXER RX1", t210_mixer11_tx),
+	WIDGETS("MIXER RX2", t210_mixer12_tx),
+	WIDGETS("MIXER RX3", t210_mixer13_tx),
+	WIDGETS("MIXER RX4", t210_mixer14_tx),
+	WIDGETS("MIXER RX5", t210_mixer15_tx),
+	WIDGETS("MIXER RX6", t210_mixer16_tx),
+	WIDGETS("MIXER RX7", t210_mixer17_tx),
+	WIDGETS("MIXER RX8", t210_mixer18_tx),
+	WIDGETS("MIXER RX9", t210_mixer19_tx),
+	WIDGETS("MIXER RX10", t210_mixer110_tx),
+	TX_WIDGETS("MIXER TX1"),
+	TX_WIDGETS("MIXER TX2"),
+	TX_WIDGETS("MIXER TX3"),
+	TX_WIDGETS("MIXER TX4"),
+	TX_WIDGETS("MIXER TX5"),
 };
 
 static const struct snd_soc_dapm_widget tegra186_ahub_widgets[] = {
@@ -368,6 +721,67 @@ static const struct snd_soc_dapm_widget tegra186_ahub_widgets[] = {
 	TX_WIDGETS("DMIC4"),
 	WIDGETS("DSPK1", t186_dspk1_tx),
 	WIDGETS("DSPK2", t186_dspk2_tx),
+	WIDGETS("SFC1", t186_sfc1_tx),
+	WIDGETS("SFC2", t186_sfc2_tx),
+	WIDGETS("SFC3", t186_sfc3_tx),
+	WIDGETS("SFC4", t186_sfc4_tx),
+	WIDGETS("MVC1", t186_mvc1_tx),
+	WIDGETS("MVC2", t186_mvc2_tx),
+	WIDGETS("AMX1 RX1", t186_amx11_tx),
+	WIDGETS("AMX1 RX2", t186_amx12_tx),
+	WIDGETS("AMX1 RX3", t186_amx13_tx),
+	WIDGETS("AMX1 RX4", t186_amx14_tx),
+	WIDGETS("AMX2 RX1", t186_amx21_tx),
+	WIDGETS("AMX2 RX2", t186_amx22_tx),
+	WIDGETS("AMX2 RX3", t186_amx23_tx),
+	WIDGETS("AMX2 RX4", t186_amx24_tx),
+	WIDGETS("AMX3 RX1", t186_amx31_tx),
+	WIDGETS("AMX3 RX2", t186_amx32_tx),
+	WIDGETS("AMX3 RX3", t186_amx33_tx),
+	WIDGETS("AMX3 RX4", t186_amx34_tx),
+	WIDGETS("AMX4 RX1", t186_amx41_tx),
+	WIDGETS("AMX4 RX2", t186_amx42_tx),
+	WIDGETS("AMX4 RX3", t186_amx43_tx),
+	WIDGETS("AMX4 RX4", t186_amx44_tx),
+	TX_WIDGETS("AMX1"),
+	TX_WIDGETS("AMX2"),
+	TX_WIDGETS("AMX3"),
+	TX_WIDGETS("AMX4"),
+	WIDGETS("ADX1", t186_adx1_tx),
+	WIDGETS("ADX2", t186_adx2_tx),
+	WIDGETS("ADX3", t186_adx3_tx),
+	WIDGETS("ADX4", t186_adx4_tx),
+	TX_WIDGETS("ADX1 TX1"),
+	TX_WIDGETS("ADX1 TX2"),
+	TX_WIDGETS("ADX1 TX3"),
+	TX_WIDGETS("ADX1 TX4"),
+	TX_WIDGETS("ADX2 TX1"),
+	TX_WIDGETS("ADX2 TX2"),
+	TX_WIDGETS("ADX2 TX3"),
+	TX_WIDGETS("ADX2 TX4"),
+	TX_WIDGETS("ADX3 TX1"),
+	TX_WIDGETS("ADX3 TX2"),
+	TX_WIDGETS("ADX3 TX3"),
+	TX_WIDGETS("ADX3 TX4"),
+	TX_WIDGETS("ADX4 TX1"),
+	TX_WIDGETS("ADX4 TX2"),
+	TX_WIDGETS("ADX4 TX3"),
+	TX_WIDGETS("ADX4 TX4"),
+	WIDGETS("MIXER RX1", t186_mixer11_tx),
+	WIDGETS("MIXER RX2", t186_mixer12_tx),
+	WIDGETS("MIXER RX3", t186_mixer13_tx),
+	WIDGETS("MIXER RX4", t186_mixer14_tx),
+	WIDGETS("MIXER RX5", t186_mixer15_tx),
+	WIDGETS("MIXER RX6", t186_mixer16_tx),
+	WIDGETS("MIXER RX7", t186_mixer17_tx),
+	WIDGETS("MIXER RX8", t186_mixer18_tx),
+	WIDGETS("MIXER RX9", t186_mixer19_tx),
+	WIDGETS("MIXER RX10", t186_mixer110_tx),
+	TX_WIDGETS("MIXER TX1"),
+	TX_WIDGETS("MIXER TX2"),
+	TX_WIDGETS("MIXER TX3"),
+	TX_WIDGETS("MIXER TX4"),
+	TX_WIDGETS("MIXER TX5"),
 };
 
 #define TEGRA_COMMON_MUX_ROUTES(name)					\
@@ -389,7 +803,28 @@ static const struct snd_soc_dapm_widget tegra186_ahub_widgets[] = {
 	{ name " Mux",		"I2S5",		"I2S5 XBAR-RX" },	\
 	{ name " Mux",		"DMIC1",	"DMIC1 XBAR-RX" },	\
 	{ name " Mux",		"DMIC2",	"DMIC2 XBAR-RX" },	\
-	{ name " Mux",		"DMIC3",	"DMIC3 XBAR-RX" },
+	{ name " Mux",		"DMIC3",	"DMIC3 XBAR-RX" },	\
+	{ name " Mux",		"SFC1",		"SFC1 XBAR-RX" },	\
+	{ name " Mux",		"SFC2",		"SFC2 XBAR-RX" },	\
+	{ name " Mux",		"SFC3",		"SFC3 XBAR-RX" },	\
+	{ name " Mux",		"SFC4",		"SFC4 XBAR-RX" },	\
+	{ name " Mux",		"MVC1",		"MVC1 XBAR-RX" },	\
+	{ name " Mux",		"MVC2",		"MVC2 XBAR-RX" },	\
+	{ name " Mux",		"AMX1",		"AMX1 XBAR-RX" },	\
+	{ name " Mux",		"AMX2",		"AMX2 XBAR-RX" },	\
+	{ name " Mux",		"ADX1 TX1",	"ADX1 TX1 XBAR-RX" },	\
+	{ name " Mux",		"ADX1 TX2",	"ADX1 TX2 XBAR-RX" },	\
+	{ name " Mux",		"ADX1 TX3",	"ADX1 TX3 XBAR-RX" },	\
+	{ name " Mux",		"ADX1 TX4",	"ADX1 TX4 XBAR-RX" },	\
+	{ name " Mux",		"ADX2 TX1",	"ADX2 TX1 XBAR-RX" },	\
+	{ name " Mux",		"ADX2 TX2",	"ADX2 TX2 XBAR-RX" },	\
+	{ name " Mux",		"ADX2 TX3",	"ADX2 TX3 XBAR-RX" },	\
+	{ name " Mux",		"ADX2 TX4",	"ADX2 TX4 XBAR-RX" },	\
+	{ name " Mux",		"MIXER TX1",	"MIXER TX1 XBAR-RX" },	\
+	{ name " Mux",		"MIXER TX2",	"MIXER TX2 XBAR-RX" },	\
+	{ name " Mux",		"MIXER TX3",	"MIXER TX3 XBAR-RX" },	\
+	{ name " Mux",		"MIXER TX4",	"MIXER TX4 XBAR-RX" },	\
+	{ name " Mux",		"MIXER TX5",	"MIXER TX5 XBAR-RX" },
 
 #define TEGRA186_ONLY_MUX_ROUTES(name)					\
 	{ name " Mux",		"ADMAIF11",	"ADMAIF11 XBAR-RX" },	\
@@ -403,7 +838,17 @@ static const struct snd_soc_dapm_widget tegra186_ahub_widgets[] = {
 	{ name " Mux",		"ADMAIF19",	"ADMAIF19 XBAR-RX" },	\
 	{ name " Mux",		"ADMAIF20",	"ADMAIF20 XBAR-RX" },	\
 	{ name " Mux",		"I2S6",		"I2S6 XBAR-RX" },	\
-	{ name " Mux",		"DMIC4",	"DMIC4 XBAR-RX" },
+	{ name " Mux",		"DMIC4",	"DMIC4 XBAR-RX" },	\
+	{ name " Mux",		"AMX3",		"AMX3 XBAR-RX" },	\
+	{ name " Mux",		"AMX4",		"AMX4 XBAR-RX" },	\
+	{ name " Mux",		"ADX3 TX1",	"ADX3 TX1 XBAR-RX" },	\
+	{ name " Mux",		"ADX3 TX2",	"ADX3 TX2 XBAR-RX" },	\
+	{ name " Mux",		"ADX3 TX3",	"ADX3 TX3 XBAR-RX" },	\
+	{ name " Mux",		"ADX3 TX4",	"ADX3 TX4 XBAR-RX" },	\
+	{ name " Mux",		"ADX4 TX1",	"ADX4 TX1 XBAR-RX" },	\
+	{ name " Mux",		"ADX4 TX2",	"ADX4 TX2 XBAR-RX" },	\
+	{ name " Mux",		"ADX4 TX3",	"ADX4 TX3 XBAR-RX" },	\
+	{ name " Mux",		"ADX4 TX4",	"ADX4 TX4 XBAR-RX" },
 
 #define TEGRA210_MUX_ROUTES(name)						\
 	TEGRA_COMMON_MUX_ROUTES(name)
@@ -450,6 +895,32 @@ static const struct snd_soc_dapm_route tegra210_ahub_routes[] = {
 	TEGRA210_MUX_ROUTES("I2S3")
 	TEGRA210_MUX_ROUTES("I2S4")
 	TEGRA210_MUX_ROUTES("I2S5")
+	TEGRA210_MUX_ROUTES("SFC1")
+	TEGRA210_MUX_ROUTES("SFC2")
+	TEGRA210_MUX_ROUTES("SFC3")
+	TEGRA210_MUX_ROUTES("SFC4")
+	TEGRA210_MUX_ROUTES("MVC1")
+	TEGRA210_MUX_ROUTES("MVC2")
+	TEGRA210_MUX_ROUTES("AMX1 RX1")
+	TEGRA210_MUX_ROUTES("AMX1 RX2")
+	TEGRA210_MUX_ROUTES("AMX1 RX3")
+	TEGRA210_MUX_ROUTES("AMX1 RX4")
+	TEGRA210_MUX_ROUTES("AMX2 RX1")
+	TEGRA210_MUX_ROUTES("AMX2 RX2")
+	TEGRA210_MUX_ROUTES("AMX2 RX3")
+	TEGRA210_MUX_ROUTES("AMX2 RX4")
+	TEGRA210_MUX_ROUTES("ADX1")
+	TEGRA210_MUX_ROUTES("ADX2")
+	TEGRA210_MUX_ROUTES("MIXER RX1")
+	TEGRA210_MUX_ROUTES("MIXER RX2")
+	TEGRA210_MUX_ROUTES("MIXER RX3")
+	TEGRA210_MUX_ROUTES("MIXER RX4")
+	TEGRA210_MUX_ROUTES("MIXER RX5")
+	TEGRA210_MUX_ROUTES("MIXER RX6")
+	TEGRA210_MUX_ROUTES("MIXER RX7")
+	TEGRA210_MUX_ROUTES("MIXER RX8")
+	TEGRA210_MUX_ROUTES("MIXER RX9")
+	TEGRA210_MUX_ROUTES("MIXER RX10")
 };
 
 static const struct snd_soc_dapm_route tegra186_ahub_routes[] = {
@@ -501,6 +972,42 @@ static const struct snd_soc_dapm_route tegra186_ahub_routes[] = {
 	TEGRA186_MUX_ROUTES("I2S6")
 	TEGRA186_MUX_ROUTES("DSPK1")
 	TEGRA186_MUX_ROUTES("DSPK2")
+	TEGRA186_MUX_ROUTES("SFC1")
+	TEGRA186_MUX_ROUTES("SFC2")
+	TEGRA186_MUX_ROUTES("SFC3")
+	TEGRA186_MUX_ROUTES("SFC4")
+	TEGRA186_MUX_ROUTES("MVC1")
+	TEGRA186_MUX_ROUTES("MVC2")
+	TEGRA186_MUX_ROUTES("AMX1 RX1")
+	TEGRA186_MUX_ROUTES("AMX1 RX2")
+	TEGRA186_MUX_ROUTES("AMX1 RX3")
+	TEGRA186_MUX_ROUTES("AMX1 RX4")
+	TEGRA186_MUX_ROUTES("AMX2 RX1")
+	TEGRA186_MUX_ROUTES("AMX2 RX2")
+	TEGRA186_MUX_ROUTES("AMX2 RX3")
+	TEGRA186_MUX_ROUTES("AMX2 RX4")
+	TEGRA186_MUX_ROUTES("AMX3 RX1")
+	TEGRA186_MUX_ROUTES("AMX3 RX2")
+	TEGRA186_MUX_ROUTES("AMX3 RX3")
+	TEGRA186_MUX_ROUTES("AMX3 RX4")
+	TEGRA186_MUX_ROUTES("AMX4 RX1")
+	TEGRA186_MUX_ROUTES("AMX4 RX2")
+	TEGRA186_MUX_ROUTES("AMX4 RX3")
+	TEGRA186_MUX_ROUTES("AMX4 RX4")
+	TEGRA186_MUX_ROUTES("ADX1")
+	TEGRA186_MUX_ROUTES("ADX2")
+	TEGRA186_MUX_ROUTES("ADX3")
+	TEGRA186_MUX_ROUTES("ADX4")
+	TEGRA186_MUX_ROUTES("MIXER RX1")
+	TEGRA186_MUX_ROUTES("MIXER RX2")
+	TEGRA186_MUX_ROUTES("MIXER RX3")
+	TEGRA186_MUX_ROUTES("MIXER RX4")
+	TEGRA186_MUX_ROUTES("MIXER RX5")
+	TEGRA186_MUX_ROUTES("MIXER RX6")
+	TEGRA186_MUX_ROUTES("MIXER RX7")
+	TEGRA186_MUX_ROUTES("MIXER RX8")
+	TEGRA186_MUX_ROUTES("MIXER RX9")
+	TEGRA186_MUX_ROUTES("MIXER RX10")
 };
 
 static const struct snd_soc_component_driver tegra210_ahub_component = {
-- 
2.7.4


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

* [PATCH 06/13] ASoC: tegra: Add Tegra210 based MVC driver
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (4 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 05/13] ASoC: tegra: Add routes for few " Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-09-03 18:13   ` Mark Brown
  2021-08-27  9:33 ` [PATCH 07/13] ASoC: tegra: Add Tegra210 based SFC driver Sameer Pujar
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

The Master Volume Control (MVC) provides gain or attenuation to a digital
signal path. It can be used in input or output signal path for per-stream
volume control or it can be used as master volume control. The MVC block
has one input and one output. The input digital stream can be mono or
multi-channel (up to 7.1 channels) stream. An independent mute control is
also included in the MVC block.

This patch registers MVC driver with ASoC framework. The component driver
exposes DAPM widgets, routes and kcontrols for the device. The DAI driver
exposes MVC interfaces, which can be used to connect different components
in the ASoC layer. Makefile and Kconfig support is added to allow build
the driver. It can be enabled in the DT via "nvidia,tegra210-mvc"
compatible binding.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 sound/soc/tegra/Kconfig        |   9 +
 sound/soc/tegra/Makefile       |   2 +
 sound/soc/tegra/tegra210_mvc.c | 629 +++++++++++++++++++++++++++++++++++++++++
 sound/soc/tegra/tegra210_mvc.h | 117 ++++++++
 4 files changed, 757 insertions(+)
 create mode 100644 sound/soc/tegra/tegra210_mvc.c
 create mode 100644 sound/soc/tegra/tegra210_mvc.h

diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 83c87f3..b8825e9 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -108,6 +108,15 @@ config SND_SOC_TEGRA210_ADMAIF
 	  channel. Buffer size is configurable for each ADMAIIF channel.
 	  Say Y or M if you want to add support for Tegra210 ADMAIF module.
 
+config SND_SOC_TEGRA210_MVC
+	tristate "Tegra210 MVC module"
+	help
+	  Config to enable the digital Master Volume Controller (MVC) which
+	  provides gain or attenuation to a digital signal path. It can be
+	  used in input or output signal path. It can be used either for
+	  per-stream volume control or for master volume control.
+	  Say Y or M if you want to add support for Tegra210 MVC module.
+
 config SND_SOC_TEGRA_AUDIO_GRAPH_CARD
 	tristate "Audio Graph Card based Tegra driver"
 	depends on SND_AUDIO_GRAPH_CARD
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index e2cec9a..b58d041 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -13,6 +13,7 @@ snd-soc-tegra210-dmic-objs := tegra210_dmic.o
 snd-soc-tegra210-i2s-objs := tegra210_i2s.o
 snd-soc-tegra186-dspk-objs := tegra186_dspk.o
 snd-soc-tegra210-admaif-objs := tegra210_admaif.o
+snd-soc-tegra210-mvc-objs := tegra210_mvc.o
 
 obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
 obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o
@@ -26,6 +27,7 @@ obj-$(CONFIG_SND_SOC_TEGRA210_AHUB) += snd-soc-tegra210-ahub.o
 obj-$(CONFIG_SND_SOC_TEGRA210_I2S) += snd-soc-tegra210-i2s.o
 obj-$(CONFIG_SND_SOC_TEGRA186_DSPK) += snd-soc-tegra186-dspk.o
 obj-$(CONFIG_SND_SOC_TEGRA210_ADMAIF) += snd-soc-tegra210-admaif.o
+obj-$(CONFIG_SND_SOC_TEGRA210_MVC) += snd-soc-tegra210-mvc.o
 
 # Tegra machine Support
 snd-soc-tegra-wm8903-objs := tegra_wm8903.o
diff --git a/sound/soc/tegra/tegra210_mvc.c b/sound/soc/tegra/tegra210_mvc.c
new file mode 100644
index 0000000..4942813
--- /dev/null
+++ b/sound/soc/tegra/tegra210_mvc.c
@@ -0,0 +1,629 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// tegra210_mvc.c - Tegra210 MVC driver
+//
+// Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra210_mvc.h"
+#include "tegra_cif.h"
+
+static const struct reg_default tegra210_mvc_reg_defaults[] = {
+	{ TEGRA210_MVC_RX_INT_MASK, 0x00000001},
+	{ TEGRA210_MVC_RX_CIF_CTRL, 0x00007700},
+	{ TEGRA210_MVC_TX_INT_MASK, 0x00000001},
+	{ TEGRA210_MVC_TX_CIF_CTRL, 0x00007700},
+	{ TEGRA210_MVC_CG, 0x1},
+	{ TEGRA210_MVC_CTRL, TEGRA210_MVC_CTRL_DEFAULT},
+	{ TEGRA210_MVC_INIT_VOL, 0x00800000},
+	{ TEGRA210_MVC_TARGET_VOL, 0x00800000},
+	{ TEGRA210_MVC_DURATION, 0x000012c0},
+	{ TEGRA210_MVC_DURATION_INV, 0x0006d3a0},
+	{ TEGRA210_MVC_POLY_N1, 0x0000007d},
+	{ TEGRA210_MVC_POLY_N2, 0x00000271},
+	{ TEGRA210_MVC_PEAK_CTRL, 0x000012c0},
+	{ TEGRA210_MVC_CFG_RAM_CTRL, 0x00004000},
+};
+
+static const struct tegra210_mvc_gain_params gain_params = {
+	.poly_coeff = { 23738319, 659403, -3680,
+			15546680, 2530732, -120985,
+			12048422, 5527252, -785042 },
+	.poly_n1 = 16,
+	.poly_n2 = 63,
+	.duration = 150,
+	.duration_inv = 14316558,
+};
+
+static int __maybe_unused tegra210_mvc_runtime_suspend(struct device *dev)
+{
+	struct tegra210_mvc *mvc = dev_get_drvdata(dev);
+
+	regmap_read(mvc->regmap, TEGRA210_MVC_CTRL, &(mvc->ctrl_value));
+
+	regcache_cache_only(mvc->regmap, true);
+	regcache_mark_dirty(mvc->regmap);
+
+	return 0;
+}
+
+static int __maybe_unused tegra210_mvc_runtime_resume(struct device *dev)
+{
+	struct tegra210_mvc *mvc = dev_get_drvdata(dev);
+
+	regcache_cache_only(mvc->regmap, false);
+	regcache_sync(mvc->regmap);
+
+	regmap_write(mvc->regmap, TEGRA210_MVC_CTRL, mvc->ctrl_value);
+	regmap_update_bits(mvc->regmap,
+			   TEGRA210_MVC_SWITCH,
+			   TEGRA210_MVC_VOLUME_SWITCH_MASK,
+			   TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
+
+	return 0;
+}
+
+static int tegra210_mvc_write_ram(struct tegra210_mvc *mvc,
+				  unsigned int addr, unsigned int coef)
+{
+	unsigned int reg, val;
+	int err;
+
+	err = regmap_read_poll_timeout(mvc->regmap,
+				       TEGRA210_MVC_CFG_RAM_CTRL,
+				       val, !(val & 0x80000000), 10, 10000);
+	if (err < 0)
+		return err;
+
+	reg = (addr << TEGRA210_MVC_CFG_RAM_CTRL_ADDR_SHIFT) &
+	      TEGRA210_MVC_CFG_RAM_CTRL_ADDR_MASK;
+	reg |= TEGRA210_MVC_CFG_RAM_CTRL_ADDR_INIT_EN;
+	reg |= TEGRA210_MVC_CFG_RAM_CTRL_RW_WRITE;
+	reg |= TEGRA210_MVC_CFG_RAM_CTRL_SEQ_ACCESS_EN;
+
+	regmap_write(mvc->regmap, TEGRA210_MVC_CFG_RAM_CTRL, reg);
+	regmap_write(mvc->regmap, TEGRA210_MVC_CFG_RAM_DATA,
+		     coef);
+
+	return 0;
+}
+
+static int tegra210_mvc_get_vol(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt);
+	unsigned int reg = mc->reg;
+
+	if (reg == TEGRA210_MVC_CTRL) {
+		u32 val;
+		u8 mute_mask;
+
+		pm_runtime_get_sync(cmpnt->dev);
+		regmap_read(mvc->regmap, TEGRA210_MVC_CTRL, &val);
+		pm_runtime_put(cmpnt->dev);
+
+		mute_mask = (val >>  TEGRA210_MVC_MUTE_SHIFT) &
+			TEGRA210_MUTE_MASK_EN;
+
+		ucontrol->value.integer.value[0] = mute_mask;
+	} else {
+		u8 chan = (reg - TEGRA210_MVC_TARGET_VOL) / REG_SIZE;
+		s32 val = mvc->volume[chan];
+
+		if (mvc->curve_type == CURVE_POLY)
+			val = ((val >> 16) * 100) >> 8;
+		else {
+			val = (val * 100) >> 8;
+			val += 12000;
+		}
+
+		ucontrol->value.integer.value[0] = val;
+	}
+
+	return 0;
+}
+
+static void tegra210_mvc_conv_vol(struct tegra210_mvc *mvc, u8 chan, s32 val)
+{
+	/*
+	 * Volume control read from mixer control is with
+	 * 100x scaling; for CURVE_POLY the reg range
+	 * is 0-100 (linear, Q24) and for CURVE_LINEAR
+	 * it is -120dB to +40dB (Q8)
+	 */
+	if (mvc->curve_type == CURVE_POLY) {
+		if (val > 10000)
+			val = 10000;
+		mvc->volume[chan] = ((val * (1<<8)) / 100) << 16;
+	} else {
+		val -= 12000;
+		mvc->volume[chan] = (val * (1<<8)) / 100;
+	}
+}
+
+static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt);
+	unsigned int reg = mc->reg;
+	unsigned int value;
+	int err;
+
+	pm_runtime_get_sync(cmpnt->dev);
+
+	/* Check if VOLUME_SWITCH is triggered */
+	err = regmap_read_poll_timeout(mvc->regmap, TEGRA210_MVC_SWITCH,
+			value, !(value & TEGRA210_MVC_VOLUME_SWITCH_MASK),
+			10, 10000);
+	if (err < 0)
+		goto end;
+
+	if (reg == TEGRA210_MVC_CTRL) {
+		u8 mute_mask;
+
+		mute_mask = ucontrol->value.integer.value[0];
+
+		err = regmap_update_bits(mvc->regmap, reg,
+					 TEGRA210_MVC_MUTE_MASK,
+					 mute_mask << TEGRA210_MVC_MUTE_SHIFT);
+	} else {
+		u8 chan;
+
+		chan = (reg - TEGRA210_MVC_TARGET_VOL) / REG_SIZE;
+
+		tegra210_mvc_conv_vol(mvc, chan,
+				      ucontrol->value.integer.value[0]);
+
+		/* Configure init volume same as target volume */
+		regmap_write(mvc->regmap,
+			TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_INIT_VOL, chan),
+			mvc->volume[chan]);
+
+		err = regmap_write(mvc->regmap, reg, mvc->volume[chan]);
+	}
+
+	err |= regmap_update_bits(mvc->regmap, TEGRA210_MVC_SWITCH,
+			TEGRA210_MVC_VOLUME_SWITCH_MASK,
+			TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
+
+end:
+	pm_runtime_put(cmpnt->dev);
+	return err;
+}
+
+static void tegra210_mvc_reset_vol_settings(struct tegra210_mvc *mvc,
+					    struct device *dev)
+{
+	int i;
+
+	/* Change volume to default init for new curve type */
+	if (mvc->curve_type == CURVE_POLY) {
+		for (i = 0; i < TEGRA210_MVC_MAX_CHAN_COUNT; i++)
+			mvc->volume[i] = TEGRA210_MVC_INIT_VOL_DEFAULT_POLY;
+	} else {
+		for (i = 0; i < TEGRA210_MVC_MAX_CHAN_COUNT; i++)
+			mvc->volume[i] = TEGRA210_MVC_INIT_VOL_DEFAULT_LINEAR;
+	}
+
+	pm_runtime_get_sync(dev);
+
+	/* Program curve type */
+	regmap_update_bits(mvc->regmap, TEGRA210_MVC_CTRL,
+			   TEGRA210_MVC_CURVE_TYPE_MASK,
+			   mvc->curve_type <<
+			   TEGRA210_MVC_CURVE_TYPE_SHIFT);
+
+	/* Init volume for all channels */
+	for (i = 0; i < TEGRA210_MVC_MAX_CHAN_COUNT; i++) {
+		regmap_write(mvc->regmap,
+			TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_INIT_VOL, i),
+			mvc->volume[i]);
+		regmap_write(mvc->regmap,
+			TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_TARGET_VOL, i),
+			mvc->volume[i]);
+	}
+
+	/* Trigger volume switch */
+	regmap_update_bits(mvc->regmap, TEGRA210_MVC_SWITCH,
+			   TEGRA210_MVC_VOLUME_SWITCH_MASK,
+			   TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
+
+	pm_runtime_put(dev);
+}
+
+static int tegra210_mvc_get_curve_type(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt);
+
+	ucontrol->value.integer.value[0] = mvc->curve_type;
+
+	return 0;
+}
+
+static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt);
+	int value;
+
+	regmap_read(mvc->regmap, TEGRA210_MVC_ENABLE, &value);
+	if (value & TEGRA210_MVC_EN) {
+		dev_err(cmpnt->dev,
+			"Curve type can't be set when MVC is running\n");
+		return -EINVAL;
+	}
+
+	if (mvc->curve_type == ucontrol->value.integer.value[0])
+		return 0;
+
+	mvc->curve_type = ucontrol->value.integer.value[0];
+
+	tegra210_mvc_reset_vol_settings(mvc, cmpnt->dev);
+
+	return 0;
+}
+
+static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc,
+				      struct snd_pcm_hw_params *params,
+				      unsigned int reg)
+{
+	unsigned int channels, audio_bits;
+	struct tegra_cif_conf cif_conf;
+
+	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
+
+	channels = params_channels(params);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		audio_bits = TEGRA_ACIF_BITS_16;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		audio_bits = TEGRA_ACIF_BITS_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cif_conf.audio_ch = channels;
+	cif_conf.client_ch = channels;
+	cif_conf.audio_bits = audio_bits;
+	cif_conf.client_bits = audio_bits;
+
+	tegra_set_cif(mvc->regmap, reg, &cif_conf);
+
+	return 0;
+}
+
+static int tegra210_mvc_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_soc_dai *dai)
+{
+	struct device *dev = dai->dev;
+	struct tegra210_mvc *mvc = snd_soc_dai_get_drvdata(dai);
+	int i, err, val;
+
+	/* SW reset */
+	regmap_write(mvc->regmap, TEGRA210_MVC_SOFT_RESET, 1);
+
+	err = regmap_read_poll_timeout(mvc->regmap, TEGRA210_MVC_SOFT_RESET,
+				       val, !val, 10, 10000);
+	if (err < 0) {
+		dev_err(dev, "SW reset failed, err = %d\n", err);
+		return err;
+	}
+
+	/* Set RX CIF */
+	err = tegra210_mvc_set_audio_cif(mvc, params, TEGRA210_MVC_RX_CIF_CTRL);
+	if (err) {
+		dev_err(dev, "Can't set MVC RX CIF: %d\n", err);
+		return err;
+	}
+
+	/* Set TX CIF */
+	err = tegra210_mvc_set_audio_cif(mvc, params, TEGRA210_MVC_TX_CIF_CTRL);
+	if (err) {
+		dev_err(dev, "Can't set MVC TX CIF: %d\n", err);
+		return err;
+	}
+
+	/* Program the poly coefficients */
+	for (i = 0; i < NUM_GAIN_POLY_COEFFS; i++) {
+		err = tegra210_mvc_write_ram(mvc, i, gain_params.poly_coeff[i]);
+		if (err < 0) {
+			dev_err(dai->dev, "failed to write coefs, err = %d\n",
+				err);
+			return err;
+		}
+	}
+
+	/* Program poly_n1, poly_n2, duration */
+	regmap_write(mvc->regmap, TEGRA210_MVC_POLY_N1, gain_params.poly_n1);
+	regmap_write(mvc->regmap, TEGRA210_MVC_POLY_N2, gain_params.poly_n2);
+	regmap_write(mvc->regmap, TEGRA210_MVC_DURATION, gain_params.duration);
+
+	/* Program duration_inv */
+	regmap_write(mvc->regmap, TEGRA210_MVC_DURATION_INV,
+		     gain_params.duration_inv);
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops tegra210_mvc_dai_ops = {
+	.hw_params	= tegra210_mvc_hw_params,
+};
+
+static const char * const tegra210_mvc_curve_type_text[] = {
+	"Poly",
+	"Linear",
+};
+
+static const struct soc_enum tegra210_mvc_curve_type_ctrl =
+	SOC_ENUM_SINGLE_EXT(2, tegra210_mvc_curve_type_text);
+
+#define TEGRA210_MVC_VOL_CTRL(chan)					\
+	SOC_SINGLE_EXT("Channel" #chan " Volume",			\
+		       TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_TARGET_VOL, \
+					       (chan - 1)),		\
+		       0, 16000, 0, tegra210_mvc_get_vol,		\
+		       tegra210_mvc_put_vol)
+
+static const struct snd_kcontrol_new tegra210_mvc_vol_ctrl[] = {
+	/* Per channel volume control */
+	TEGRA210_MVC_VOL_CTRL(1),
+	TEGRA210_MVC_VOL_CTRL(2),
+	TEGRA210_MVC_VOL_CTRL(3),
+	TEGRA210_MVC_VOL_CTRL(4),
+	TEGRA210_MVC_VOL_CTRL(5),
+	TEGRA210_MVC_VOL_CTRL(6),
+	TEGRA210_MVC_VOL_CTRL(7),
+	TEGRA210_MVC_VOL_CTRL(8),
+
+	/* Per channel mute */
+	SOC_SINGLE_EXT("Per Chan Mute Mask",
+		       TEGRA210_MVC_CTRL, 0, TEGRA210_MUTE_MASK_EN, 0,
+		       tegra210_mvc_get_vol, tegra210_mvc_put_vol),
+
+	SOC_ENUM_EXT("Curve Type", tegra210_mvc_curve_type_ctrl,
+		     tegra210_mvc_get_curve_type, tegra210_mvc_put_curve_type),
+};
+
+static struct snd_soc_dai_driver tegra210_mvc_dais[] = {
+	/* Input */
+	{
+		.name = "MVC-RX-CIF",
+		.playback = {
+			.stream_name = "RX-CIF-Playback",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S8 |
+				SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.capture = {
+			.stream_name = "RX-CIF-Capture",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S8 |
+				SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S32_LE,
+		},
+	},
+
+	/* Output */
+	{
+		.name = "MVC-TX-CIF",
+		.playback = {
+			.stream_name = "TX-CIF-Playback",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S8 |
+				SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.capture = {
+			.stream_name = "TX-CIF-Capture",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S8 |
+				SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &tegra210_mvc_dai_ops,
+	}
+};
+
+static const struct snd_soc_dapm_widget tegra210_mvc_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("RX", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("TX", NULL, 0, TEGRA210_MVC_ENABLE,
+			     TEGRA210_MVC_EN_SHIFT, 0),
+};
+
+#define MVC_ROUTES(sname)					\
+	{ "RX XBAR-" sname,	NULL,	"XBAR-TX" },		\
+	{ "RX-CIF-" sname,	NULL,	"RX XBAR-" sname },	\
+	{ "RX",			NULL,	"RX-CIF-" sname },	\
+	{ "TX-CIF-" sname,	NULL,	"TX" },			\
+	{ "TX XBAR-" sname,	NULL,	"TX-CIF-" sname },	\
+	{ "XBAR-RX",            NULL,   "TX XBAR-" sname }
+
+static const struct snd_soc_dapm_route tegra210_mvc_routes[] = {
+	{ "TX", NULL, "RX" },
+	MVC_ROUTES("Playback"),
+	MVC_ROUTES("Capture"),
+};
+
+static const struct snd_soc_component_driver tegra210_mvc_cmpnt = {
+	.dapm_widgets		= tegra210_mvc_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(tegra210_mvc_widgets),
+	.dapm_routes		= tegra210_mvc_routes,
+	.num_dapm_routes	= ARRAY_SIZE(tegra210_mvc_routes),
+	.controls		= tegra210_mvc_vol_ctrl,
+	.num_controls		= ARRAY_SIZE(tegra210_mvc_vol_ctrl),
+};
+
+static bool tegra210_mvc_rd_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_MVC_RX_STATUS ... TEGRA210_MVC_CONFIG_ERR_TYPE:
+		return true;
+	default:
+		return false;
+	};
+}
+
+static bool tegra210_mvc_wr_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_MVC_RX_INT_MASK ... TEGRA210_MVC_RX_CIF_CTRL:
+	case TEGRA210_MVC_TX_INT_MASK ... TEGRA210_MVC_TX_CIF_CTRL:
+	case TEGRA210_MVC_ENABLE ... TEGRA210_MVC_CG:
+	case TEGRA210_MVC_CTRL ... TEGRA210_MVC_CFG_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra210_mvc_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_MVC_RX_STATUS:
+	case TEGRA210_MVC_RX_INT_STATUS:
+	case TEGRA210_MVC_RX_INT_SET:
+
+	case TEGRA210_MVC_TX_STATUS:
+	case TEGRA210_MVC_TX_INT_STATUS:
+	case TEGRA210_MVC_TX_INT_SET:
+
+	case TEGRA210_MVC_SOFT_RESET:
+	case TEGRA210_MVC_STATUS:
+	case TEGRA210_MVC_INT_STATUS:
+	case TEGRA210_MVC_SWITCH:
+	case TEGRA210_MVC_CFG_RAM_CTRL:
+	case TEGRA210_MVC_CFG_RAM_DATA:
+	case TEGRA210_MVC_PEAK_VALUE:
+	case TEGRA210_MVC_CTRL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config tegra210_mvc_regmap_config = {
+	.reg_bits		= 32,
+	.reg_stride		= 4,
+	.val_bits		= 32,
+	.max_register		= TEGRA210_MVC_CONFIG_ERR_TYPE,
+	.writeable_reg		= tegra210_mvc_wr_reg,
+	.readable_reg		= tegra210_mvc_rd_reg,
+	.volatile_reg		= tegra210_mvc_volatile_reg,
+	.reg_defaults		= tegra210_mvc_reg_defaults,
+	.num_reg_defaults	= ARRAY_SIZE(tegra210_mvc_reg_defaults),
+	.cache_type		= REGCACHE_FLAT,
+};
+
+static const struct of_device_id tegra210_mvc_of_match[] = {
+	{ .compatible = "nvidia,tegra210-mvc" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tegra210_mvc_of_match);
+
+static int tegra210_mvc_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra210_mvc *mvc;
+	void __iomem *regs;
+	int err;
+
+	mvc = devm_kzalloc(dev, sizeof(*mvc), GFP_KERNEL);
+	if (!mvc)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, mvc);
+
+	mvc->curve_type = CURVE_LINEAR;
+	mvc->ctrl_value = TEGRA210_MVC_CTRL_DEFAULT;
+
+	regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	mvc->regmap = devm_regmap_init_mmio(dev, regs,
+					    &tegra210_mvc_regmap_config);
+	if (IS_ERR(mvc->regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(mvc->regmap);
+	}
+
+	regcache_cache_only(mvc->regmap, true);
+
+	err = devm_snd_soc_register_component(dev, &tegra210_mvc_cmpnt,
+					      tegra210_mvc_dais,
+					      ARRAY_SIZE(tegra210_mvc_dais));
+	if (err) {
+		dev_err(dev, "can't register MVC component, err: %d\n", err);
+		return err;
+	}
+
+	pm_runtime_enable(dev);
+
+	tegra210_mvc_reset_vol_settings(mvc, &pdev->dev);
+
+	return 0;
+}
+
+static int tegra210_mvc_platform_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops tegra210_mvc_pm_ops = {
+	SET_RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend,
+			   tegra210_mvc_runtime_resume, NULL)
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				     pm_runtime_force_resume)
+};
+
+static struct platform_driver tegra210_mvc_driver = {
+	.driver = {
+		.name = "tegra210-mvc",
+		.of_match_table = tegra210_mvc_of_match,
+		.pm = &tegra210_mvc_pm_ops,
+	},
+	.probe = tegra210_mvc_platform_probe,
+	.remove = tegra210_mvc_platform_remove,
+};
+module_platform_driver(tegra210_mvc_driver)
+
+MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>");
+MODULE_DESCRIPTION("Tegra210 MVC ASoC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/tegra/tegra210_mvc.h b/sound/soc/tegra/tegra210_mvc.h
new file mode 100644
index 0000000..def29c4
--- /dev/null
+++ b/sound/soc/tegra/tegra210_mvc.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * tegra210_mvc.h - Definitions for Tegra210 MVC driver
+ *
+ * Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+ *
+ */
+
+#ifndef __TEGRA210_MVC_H__
+#define __TEGRA210_MVC_H__
+
+/*
+ * MVC_RX registers are with respect to XBAR.
+ * The data comes from XBAR to MVC.
+ */
+#define TEGRA210_MVC_RX_STATUS			0x0c
+#define TEGRA210_MVC_RX_INT_STATUS		0x10
+#define TEGRA210_MVC_RX_INT_MASK		0x14
+#define TEGRA210_MVC_RX_INT_SET			0x18
+#define TEGRA210_MVC_RX_INT_CLEAR		0x1c
+#define TEGRA210_MVC_RX_CIF_CTRL		0x20
+
+/*
+ * MVC_TX registers are with respect to XBAR.
+ * The data goes out of MVC.
+ */
+#define TEGRA210_MVC_TX_STATUS			0x4c
+#define TEGRA210_MVC_TX_INT_STATUS		0x50
+#define TEGRA210_MVC_TX_INT_MASK		0x54
+#define TEGRA210_MVC_TX_INT_SET			0x58
+#define TEGRA210_MVC_TX_INT_CLEAR		0x5c
+#define TEGRA210_MVC_TX_CIF_CTRL		0x60
+
+/* Register offsets from TEGRA210_MVC*_BASE */
+#define TEGRA210_MVC_ENABLE			0x80
+#define TEGRA210_MVC_SOFT_RESET			0x84
+#define TEGRA210_MVC_CG				0x88
+#define TEGRA210_MVC_STATUS			0x90
+#define TEGRA210_MVC_INT_STATUS			0x94
+#define TEGRA210_MVC_CTRL			0xa8
+#define TEGRA210_MVC_SWITCH			0xac
+#define TEGRA210_MVC_INIT_VOL			0xb0
+#define TEGRA210_MVC_TARGET_VOL			0xd0
+#define TEGRA210_MVC_DURATION			0xf0
+#define TEGRA210_MVC_DURATION_INV		0xf4
+#define TEGRA210_MVC_POLY_N1			0xf8
+#define TEGRA210_MVC_POLY_N2			0xfc
+#define TEGRA210_MVC_PEAK_CTRL			0x100
+#define TEGRA210_MVC_CFG_RAM_CTRL		0x104
+#define TEGRA210_MVC_CFG_RAM_DATA		0x108
+#define TEGRA210_MVC_PEAK_VALUE			0x10c
+#define TEGRA210_MVC_CONFIG_ERR_TYPE		0x12c
+
+/* Fields in TEGRA210_MVC_ENABLE */
+#define TEGRA210_MVC_EN_SHIFT			0
+#define TEGRA210_MVC_EN				(1 << TEGRA210_MVC_EN_SHIFT)
+
+#define TEGRA210_MVC_MUTE_SHIFT			8
+#define TEGRA210_MUTE_MASK_EN			0xff
+#define TEGRA210_MVC_MUTE_MASK			(TEGRA210_MUTE_MASK_EN << TEGRA210_MVC_MUTE_SHIFT)
+#define TEGRA210_MVC_MUTE_EN			(TEGRA210_MUTE_MASK_EN << TEGRA210_MVC_MUTE_SHIFT)
+
+#define TEGRA210_MVC_PER_CHAN_CTRL_EN_SHIFT	30
+#define TEGRA210_MVC_PER_CHAN_CTRL_EN_MASK	(1 << TEGRA210_MVC_PER_CHAN_CTRL_EN_SHIFT)
+#define TEGRA210_MVC_PER_CHAN_CTRL_EN		(1 << TEGRA210_MVC_PER_CHAN_CTRL_EN_SHIFT)
+
+#define TEGRA210_MVC_CURVE_TYPE_SHIFT		1
+#define TEGRA210_MVC_CURVE_TYPE_MASK		(1 << TEGRA210_MVC_CURVE_TYPE_SHIFT)
+
+#define TEGRA210_MVC_VOLUME_SWITCH_SHIFT	2
+#define TEGRA210_MVC_VOLUME_SWITCH_MASK		(1 << TEGRA210_MVC_VOLUME_SWITCH_SHIFT)
+#define TEGRA210_MVC_VOLUME_SWITCH_TRIGGER	(1 << TEGRA210_MVC_VOLUME_SWITCH_SHIFT)
+#define TEGRA210_MVC_CTRL_DEFAULT	0x40000003
+
+#define TEGRA210_MVC_INIT_VOL_DEFAULT_POLY	0x01000000
+#define TEGRA210_MVC_INIT_VOL_DEFAULT_LINEAR	0x00000000
+
+/* Fields in TEGRA210_MVC ram ctrl */
+#define TEGRA210_MVC_CFG_RAM_CTRL_RW_SHIFT		14
+#define TEGRA210_MVC_CFG_RAM_CTRL_RW_WRITE		(1 << TEGRA210_MVC_CFG_RAM_CTRL_RW_SHIFT)
+
+#define TEGRA210_MVC_CFG_RAM_CTRL_ADDR_INIT_EN_SHIFT	13
+#define TEGRA210_MVC_CFG_RAM_CTRL_ADDR_INIT_EN		(1 << TEGRA210_MVC_CFG_RAM_CTRL_ADDR_INIT_EN_SHIFT)
+
+#define TEGRA210_MVC_CFG_RAM_CTRL_SEQ_ACCESS_EN_SHIFT	12
+#define TEGRA210_MVC_CFG_RAM_CTRL_SEQ_ACCESS_EN		(1 << TEGRA210_MVC_CFG_RAM_CTRL_SEQ_ACCESS_EN_SHIFT)
+
+#define TEGRA210_MVC_CFG_RAM_CTRL_ADDR_SHIFT		0
+#define TEGRA210_MVC_CFG_RAM_CTRL_ADDR_MASK		(0x1ff << TEGRA210_MVC_CFG_RAM_CTRL_ADDR_SHIFT)
+
+#define REG_SIZE 4
+#define TEGRA210_MVC_MAX_CHAN_COUNT 8
+#define TEGRA210_MVC_REG_OFFSET(reg, i) (reg + (REG_SIZE * i))
+
+#define NUM_GAIN_POLY_COEFFS 9
+
+enum {
+	CURVE_POLY,
+	CURVE_LINEAR,
+};
+
+struct tegra210_mvc_gain_params {
+	int poly_coeff[NUM_GAIN_POLY_COEFFS];
+	int poly_n1;
+	int poly_n2;
+	int duration;
+	int duration_inv;
+};
+
+struct tegra210_mvc {
+	int volume[TEGRA210_MVC_MAX_CHAN_COUNT];
+	unsigned int curve_type;
+	unsigned int ctrl_value;
+	struct regmap *regmap;
+};
+
+#endif
-- 
2.7.4


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

* [PATCH 07/13] ASoC: tegra: Add Tegra210 based SFC driver
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (5 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 06/13] ASoC: tegra: Add Tegra210 based MVC driver Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-08-27  9:33 ` [PATCH 08/13] ASoC: tegra: Add Tegra210 based AMX driver Sameer Pujar
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

The Sampling Frequency Converter (SFC) converts the sampling frequency
of the input signal from one frequency to another. It supports sampling
frequency conversions of streams of up to two channels (stereo).

This patch registers SFC driver with ASoC framework. The component driver
exposes DAPM widgets, routes and kcontrols for the device. The DAI driver
exposes SFC interfaces, which can be used to connect different components
in the ASoC layer. Makefile and Kconfig support is added to allow build
the driver. It can be enabled in the DT via "nvidia,tegra210-sfc"
compatible binding.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 sound/soc/tegra/Kconfig        |    9 +
 sound/soc/tegra/Makefile       |    2 +
 sound/soc/tegra/tegra210_sfc.c | 3542 ++++++++++++++++++++++++++++++++++++++++
 sound/soc/tegra/tegra210_sfc.h |   78 +
 4 files changed, 3631 insertions(+)
 create mode 100644 sound/soc/tegra/tegra210_sfc.c
 create mode 100644 sound/soc/tegra/tegra210_sfc.h

diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index b8825e9..102564e 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -117,6 +117,15 @@ config SND_SOC_TEGRA210_MVC
 	  per-stream volume control or for master volume control.
 	  Say Y or M if you want to add support for Tegra210 MVC module.
 
+config SND_SOC_TEGRA210_SFC
+	tristate "Tegra210 SFC module"
+	help
+	  Config to enable the Sampling Frequency Converter (SFC) which
+	  converts the sampling frequency of input signal to another
+	  frequency. It supports sampling frequency conversion of streams
+	  upto 2 channels (stereo).
+	  Say Y or M if you want to add support for Tegra210 SFC module.
+
 config SND_SOC_TEGRA_AUDIO_GRAPH_CARD
 	tristate "Audio Graph Card based Tegra driver"
 	depends on SND_AUDIO_GRAPH_CARD
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index b58d041..bb0cf3a 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -14,6 +14,7 @@ snd-soc-tegra210-i2s-objs := tegra210_i2s.o
 snd-soc-tegra186-dspk-objs := tegra186_dspk.o
 snd-soc-tegra210-admaif-objs := tegra210_admaif.o
 snd-soc-tegra210-mvc-objs := tegra210_mvc.o
+snd-soc-tegra210-sfc-objs := tegra210_sfc.o
 
 obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
 obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o
@@ -28,6 +29,7 @@ obj-$(CONFIG_SND_SOC_TEGRA210_I2S) += snd-soc-tegra210-i2s.o
 obj-$(CONFIG_SND_SOC_TEGRA186_DSPK) += snd-soc-tegra186-dspk.o
 obj-$(CONFIG_SND_SOC_TEGRA210_ADMAIF) += snd-soc-tegra210-admaif.o
 obj-$(CONFIG_SND_SOC_TEGRA210_MVC) += snd-soc-tegra210-mvc.o
+obj-$(CONFIG_SND_SOC_TEGRA210_SFC) += snd-soc-tegra210-sfc.o
 
 # Tegra machine Support
 snd-soc-tegra-wm8903-objs := tegra_wm8903.o
diff --git a/sound/soc/tegra/tegra210_sfc.c b/sound/soc/tegra/tegra210_sfc.c
new file mode 100644
index 0000000..a23e8fd1
--- /dev/null
+++ b/sound/soc/tegra/tegra210_sfc.c
@@ -0,0 +1,3542 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// tegra210_sfc.c - Tegra210 SFC driver
+//
+// Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra210_sfc.h"
+#include "tegra_cif.h"
+
+#define UNSUPP_CONV ((void *)(-EOPNOTSUPP))
+#define BYPASS_CONV NULL
+
+static const struct reg_default tegra210_sfc_reg_defaults[] = {
+	{ TEGRA210_SFC_RX_INT_MASK, 0x00000001},
+	{ TEGRA210_SFC_RX_CIF_CTRL, 0x00007700},
+	{ TEGRA210_SFC_TX_INT_MASK, 0x00000001},
+	{ TEGRA210_SFC_TX_CIF_CTRL, 0x00007700},
+	{ TEGRA210_SFC_CG, 0x1},
+	{ TEGRA210_SFC_CFG_RAM_CTRL, 0x00004000},
+};
+
+static const int tegra210_sfc_rates[TEGRA210_SFC_NUM_RATES] = {
+	8000,
+	11025,
+	16000,
+	22050,
+	24000,
+	32000,
+	44100,
+	48000,
+	88200,
+	96000,
+	176400,
+	192000,
+};
+
+/* coeff RAM tables required for SFC */
+static u32 coef_8to11[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x0018a102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000003,//output gain
+	0x00235204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0000015f,//input gain
+	0x00a7909c, 0xff241c71, 0x005f5e00,
+	0xffca77f4, 0xff20dd50, 0x006855eb,
+	0xff86c552, 0xff18137a, 0x00773648,
+	0x00000001//output gain
+};
+
+static u32 coef_8to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00006102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002//output gain
+};
+
+static u32 coef_8to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x0018a102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000003,//output gain
+	0x00230204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x000005f3,//input gain
+	0x00d816d6, 0xff385383, 0x004fe566,
+	0x003c548d, 0xff38c23d, 0x005d0b1c,
+	0xfff02f7d, 0xff31e983, 0x0072d65d,
+	0x00000001//output gain
+};
+
+static u32 coef_8to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x0000a105,//header
+	0x000005e1,//input gain
+	0x00dca92f, 0xff45647a, 0x0046b59c,
+	0x00429d1e, 0xff4fec62, 0x00516d30,
+	0xffdea779, 0xff5e08ba, 0x0060185e,
+	0xffafbab2, 0xff698d5a, 0x006ce3ae,
+	0xff9a82d2, 0xff704674, 0x007633c5,
+	0xff923433, 0xff721128, 0x007cff42,
+	0x00000003//output gain
+};
+
+static u32 coef_8to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00006102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002//output gain
+};
+
+static u32 coef_8to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x0156105,//interpolation + IIR filter
+	0x0000d649,//input gain
+	0x00e87afb, 0xff5f69d0, 0x003df3cf,
+	0x007ce488, 0xff99a5c8, 0x0056a6a0,
+	0x00344928, 0xffcba3e5, 0x006be470,
+	0x00137aa7, 0xffe60276, 0x00773410,
+	0x0005fa2a, 0xfff1ac11, 0x007c795b,
+	0x00012d36, 0xfff5eca2, 0x007f10ef,
+	0x00000002,//ouptut gain
+	0x0021a102,//interpolation + IIR filter
+	0x00000e00,//input gain
+	0x00e2e000, 0xff6e1a00, 0x002aaa00,
+	0x00610a00, 0xff5dda00, 0x003ccc00,
+	0x00163a00, 0xff3c0400, 0x00633200,
+	0x00000003,//Output gain
+	0x00000204,//Farrow filter
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_8to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00156105,//interpolation + IIR Filter
+	0x0000d649,//input gain
+	0x00e87afb, 0xff5f69d0, 0x003df3cf,
+	0x007ce488, 0xff99a5c8, 0x0056a6a0,
+	0x00344928, 0xffcba3e5, 0x006be470,
+	0x00137aa7, 0xffe60276, 0x00773410,
+	0x0005fa2a, 0xfff1ac11, 0x007c795b,
+	0x00012d36, 0xfff5eca2, 0x007f10ef,
+	0x00000002,//ouptut gain
+	0x0000a102,//interpolation + IIR filter
+	0x00000e00,//input gain
+	0x00e2e000, 0xff6e1a00, 0x002aaa00,
+	0x00610a00, 0xff5dda00, 0x003ccc00,
+	0x00163a00, 0xff3c0400, 0x00633200,
+	0x00000003//output gain
+};
+
+static u32 coef_8to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x0024a102,//header
+	0x0000007d,//input gain
+	0x007d1f20, 0xff1a540e, 0x00678bf9,
+	0xff916625, 0xff16b0ff, 0x006e433a,
+	0xff5af660, 0xff0eb91f, 0x00797356,
+	0x00000003,//output gain
+	0x00000204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_8to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x0000a102,//header
+	0x0000007d,//input gain
+	0x007d1f20, 0xff1a540e, 0x00678bf9,
+	0xff916625, 0xff16b0ff, 0x006e433a,
+	0xff5af660, 0xff0eb91f, 0x00797356,
+	0x00000003//output gain
+};
+
+static u32 coef_11to8[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0000015f,//input gain
+	0x00a7909c, 0xff241c71, 0x005f5e00,
+	0xffca77f4, 0xff20dd50, 0x006855eb,
+	0xff86c552, 0xff18137a, 0x00773648,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000005f3,//input gain
+	0x00d816d6, 0xff385383, 0x004fe566,
+	0x003c548d, 0xff38c23d, 0x005d0b1c,
+	0xfff02f7d, 0xff31e983, 0x0072d65d,
+	0x00000002,//output gain
+	0x00239204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_11to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00009204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_11to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00006102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002//output gain
+};
+
+static u32 coef_11to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00005204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_11to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00246102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x00009204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_11to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00006102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002//output gain
+};
+
+static u32 coef_11to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00246102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x00005204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_11to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00006102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002//output gain
+};
+
+static u32 coef_11to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00246102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x00000204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_16to8[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_16to11[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000fa103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000003,//output gain
+	0x001a5204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_16to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x0018a102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000003,//output gain
+	0x00235204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0000015f,//input gain
+	0x00a7909c, 0xff241c71, 0x005f5e00,
+	0xffca77f4, 0xff20dd50, 0x006855eb,
+	0xff86c552, 0xff18137a, 0x00773648,
+	0x00000001//output gain
+};
+
+static u32 coef_16to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x0015a105,//header
+	0x00000292,//input gain
+	0x00e4320a, 0xff41d2d9, 0x004911ac,
+	0x005dd9e3, 0xff4c7d80, 0x0052103e,
+	0xfff8ebef, 0xff5b6fab, 0x005f0a0d,
+	0xffc4b414, 0xff68582c, 0x006b38e5,
+	0xffabb861, 0xff704bec, 0x0074de52,
+	0xffa19f4c, 0xff729059, 0x007c7e90,
+	0x00000003,//output gain
+	0x00005105,//header
+	0x00000292,//input gain
+	0x00e4320a, 0xff41d2d9, 0x004911ac,
+	0x005dd9e3, 0xff4c7d80, 0x0052103e,
+	0xfff8ebef, 0xff5b6fab, 0x005f0a0d,
+	0xffc4b414, 0xff68582c, 0x006b38e5,
+	0xffabb861, 0xff704bec, 0x0074de52,
+	0xffa19f4c, 0xff729059, 0x007c7e90,
+	0x00000001//output gain
+};
+
+static u32 coef_16to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00006102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002//output gain
+};
+
+static u32 coef_16to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00156105,//interpolation + IIR filter
+	0x0000d649,//input gain
+	0x00e87afb, 0xff5f69d0, 0x003df3cf,
+	0x007ce488, 0xff99a5c8, 0x0056a6a0,
+	0x00344928, 0xffcba3e5, 0x006be470,
+	0x00137aa7, 0xffe60276, 0x00773410,
+	0x0005fa2a, 0xfff1ac11, 0x007c795b,
+	0x00012d36, 0xfff5eca2, 0x007f10ef,
+	0x00000002,//output gain
+	0x0021a102,//interpolation + IIR filter
+	0x00000e00,//input gain
+	0x00e2e000, 0xff6e1a00, 0x002aaa00,
+	0x00610a00, 0xff5dda00, 0x003ccc00,
+	0x00163a00, 0xff3c0400, 0x00633200,
+	0x00000003,//output gain
+	0x002c0204,//Farrow Filter
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005101,//IIR Filter + Decimator
+	0x0000203c,//input gain
+	0x00f52d35, 0xff2e2162, 0x005a21e0,
+	0x00c6f0f0, 0xff2ecd69, 0x006fa78d,
+	0x00000001//output gain
+};
+
+static u32 coef_16to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x0000a105,//interpolation + IIR Filter
+	0x00000784,//input gain
+	0x00cc516e, 0xff2c9639, 0x005ad5b3,
+	0x0013ad0d, 0xff3d4799, 0x0063ce75,
+	0xffb6f398, 0xff5138d1, 0x006e9e1f,
+	0xff9186e5, 0xff5f96a4, 0x0076a86e,
+	0xff82089c, 0xff676b81, 0x007b9f8a,
+	0xff7c48a5, 0xff6a31e7, 0x007ebb7b,
+	0x00000003//output gain
+};
+
+static u32 coef_16to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x0018a102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000003,//output gain
+	0x00000204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_16to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x0000a102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000003//output gain
+};
+
+static u32 coef_16to176[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x0024a102,//header
+	0x0000007d,//input gain
+	0x007d1f20, 0xff1a540e, 0x00678bf9,
+	0xff916625, 0xff16b0ff, 0x006e433a,
+	0xff5af660, 0xff0eb91f, 0x00797356,
+	0x00000003,//output gain
+	0x00000204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_16to192[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x0000a102,//header
+	0x0000007d,//input gain
+	0x007d1f20, 0xff1a540e, 0x00678bf9,
+	0xff916625, 0xff16b0ff, 0x006e433a,
+	0xff5af660, 0xff0eb91f, 0x00797356,
+	0x00000003//output gain
+};
+
+static u32 coef_22to8[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x000005f3,//input gain
+	0x00d816d6, 0xff385383, 0x004fe566,
+	0x003c548d, 0xff38c23d, 0x005d0b1c,
+	0xfff02f7d, 0xff31e983, 0x0072d65d,
+	0x00000002,//output gain
+	0x00179204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_22to11[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_22to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0000015f,//input gain
+	0x00a7909c, 0xff241c71, 0x005f5e00,
+	0xffca77f4, 0xff20dd50, 0x006855eb,
+	0xff86c552, 0xff18137a, 0x00773648,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000005f3,//input gain
+	0x00d816d6, 0xff385383, 0x004fe566,
+	0x003c548d, 0xff38c23d, 0x005d0b1c,
+	0xfff02f7d, 0xff31e983, 0x0072d65d,
+	0x00000002,//output gain
+	0x00239204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_22to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00235204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d029,//input gain
+	0x00f2a98b, 0xff92aa71, 0x001fcd16,
+	0x00ae9004, 0xffb85140, 0x0041813a,
+	0x007f8ed1, 0xffd585fc, 0x006a69e6,
+	0x00000001//output gain
+};
+
+static u32 coef_22to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00009204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_22to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00006102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002//output gain
+};
+
+static u32 coef_22to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00005204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_22to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00006102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002//output gain
+};
+
+static u32 coef_22to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00246102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x00005204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_22to176[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00006102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002//output gain
+};
+
+static u32 coef_22to192[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00246102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x00000204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_24to8[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00009105,//header
+	0x000005e1,//input gain
+	0x00dca92f, 0xff45647a, 0x0046b59c,
+	0x00429d1e, 0xff4fec62, 0x00516d30,
+	0xffdea779, 0xff5e08ba, 0x0060185e,
+	0xffafbab2, 0xff698d5a, 0x006ce3ae,
+	0xff9a82d2, 0xff704674, 0x007633c5,
+	0xff923433, 0xff721128, 0x007cff42,
+	0x00000001//output gain
+};
+
+static u32 coef_24to11[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000f6103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000002,//output gain
+	0x001a5204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_24to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00156105,//header
+	0x00000292,//input gain
+	0x00e4320a, 0xff41d2d9, 0x004911ac,
+	0x005dd9e3, 0xff4c7d80, 0x0052103e,
+	0xfff8ebef, 0xff5b6fab, 0x005f0a0d,
+	0xffc4b414, 0xff68582c, 0x006b38e5,
+	0xffabb861, 0xff704bec, 0x0074de52,
+	0xffa19f4c, 0xff729059, 0x007c7e90,
+	0x00000002,//output gain
+	0x00009105,//header
+	0x00000292,//input gain
+	0x00e4320a, 0xff41d2d9, 0x004911ac,
+	0x005dd9e3, 0xff4c7d80, 0x0052103e,
+	0xfff8ebef, 0xff5b6fab, 0x005f0a0d,
+	0xffc4b414, 0xff68582c, 0x006b38e5,
+	0xffabb861, 0xff704bec, 0x0074de52,
+	0xffa19f4c, 0xff729059, 0x007c7e90,
+	0x00000001//output gain
+};
+
+static u32 coef_24to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d029,//input gain
+	0x00f2a98b, 0xff92aa71, 0x001fcd16,
+	0x00ae9004, 0xffb85140, 0x0041813a,
+	0x007f8ed1, 0xffd585fc, 0x006a69e6,
+	0x00000002,//output gain
+	0x001b6103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000002,//output gain
+	0x00265204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_24to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00009102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001//output gain
+};
+
+static u32 coef_24to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00230204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x00001685,//input gain
+	0x00f53ae9, 0xff52f196, 0x003e3e08,
+	0x00b9f857, 0xff5d8985, 0x0050070a,
+	0x008c3e86, 0xff6053f0, 0x006d98ef,
+	0x00000001//output gain
+};
+
+static u32 coef_24to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00006102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002//output gain
+};
+
+static u32 coef_24to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00246102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x002f0204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x00000138,//input gain
+	0x00d5d232, 0xff2a3bf8, 0x005a785c,
+	0x0034001b, 0xff283109, 0x006462a6,
+	0xffe6746a, 0xff1fb09c, 0x00758a91,
+	0x00000001//output gain
+};
+
+static u32 coef_24to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00006102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002//output gain
+};
+
+static u32 coef_24to176[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00246102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x00000204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_24to192[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00006102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002//output gain
+};
+
+static u32 coef_32to8[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c5102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_32to11[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000ca102,//header
+	0x000000af,//input gain
+	0x00c65663, 0xff23d2ce, 0x005f97d6,
+	0x00086ad6, 0xff20ec4f, 0x00683201,
+	0xffbbbef6, 0xff184447, 0x00770963,
+	0x00000003,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x0000d102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001//output gain
+};
+
+static u32 coef_32to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_32to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000fa103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000003,//output gain
+	0x001a5204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_32to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000ca102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000003,//output gain
+	0x0000d102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001//output gain
+};
+
+static u32 coef_32to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x0018a102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000003,//output gain
+	0x00235204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0000015f,//input gain
+	0x00a7909c, 0xff241c71, 0x005f5e00,
+	0xffca77f4, 0xff20dd50, 0x006855eb,
+	0xff86c552, 0xff18137a, 0x00773648,
+	0x00000001//output gain
+};
+
+static u32 coef_32to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x0015a105,//header
+	0x00000292,//input gain
+	0x00e4320a, 0xff41d2d9, 0x004911ac,
+	0x005dd9e3, 0xff4c7d80, 0x0052103e,
+	0xfff8ebef, 0xff5b6fab, 0x005f0a0d,
+	0xffc4b414, 0xff68582c, 0x006b38e5,
+	0xffabb861, 0xff704bec, 0x0074de52,
+	0xffa19f4c, 0xff729059, 0x007c7e90,
+	0x00000003,//output gain
+	0x00005105,//header
+	0x00000292,//input gain
+	0x00e4320a, 0xff41d2d9, 0x004911ac,
+	0x005dd9e3, 0xff4c7d80, 0x0052103e,
+	0xfff8ebef, 0xff5b6fab, 0x005f0a0d,
+	0xffc4b414, 0xff68582c, 0x006b38e5,
+	0xffabb861, 0xff704bec, 0x0074de52,
+	0xffa19f4c, 0xff729059, 0x007c7e90,
+	0x00000001//output gain
+};
+
+static u32 coef_32to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x0018a102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000003,//output gain
+	0x00230204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x000005f3,//input gain
+	0x00d816d6, 0xff385383, 0x004fe566,
+	0x003c548d, 0xff38c23d, 0x005d0b1c,
+	0xfff02f7d, 0xff31e983, 0x0072d65d,
+	0x00000001//output gain
+};
+
+static u32 coef_32to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x0000a105,//header
+	0x00000292,//input gain
+	0x00e4320a, 0xff41d2d9, 0x004911ac,
+	0x005dd9e3, 0xff4c7d80, 0x0052103e,
+	0xfff8ebef, 0xff5b6fab, 0x005f0a0d,
+	0xffc4b414, 0xff68582c, 0x006b38e5,
+	0xffabb861, 0xff704bec, 0x0074de52,
+	0xffa19f4c, 0xff729059, 0x007c7e90,
+	0x00000003//output gain
+};
+
+static u32 coef_32to176[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x0018a102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000003,//output gain
+	0x00000204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_32to192[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x0000a102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000003//output gain
+};
+
+static u32 coef_44to8[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00120104,//IIR Filter
+	0x00000af2,//input gain
+	0x0057eebe, 0xff1e9863, 0x00652604,
+	0xff7206ea, 0xff22ad7e, 0x006d47e1,
+	0xff42a4d7, 0xff26e722, 0x0075fd83,
+	0xff352f66, 0xff29312b, 0x007b986b,
+	0xff310a07, 0xff296f51, 0x007eca7c,
+	0x00000001,//output gain
+	0x001d9204,//Farrow Filter + decimation
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005105,//IIR Filter + Decimator
+	0x0000d649,//input gain
+	0x00e87afb, 0xff5f69d0, 0x003df3cf,
+	0x007ce488, 0xff99a5c8, 0x0056a6a0,
+	0x00344928, 0xffcba3e5, 0x006be470,
+	0x00137aa7, 0xffe60276, 0x00773410,
+	0x0005fa2a, 0xfff1ac11, 0x007c795b,
+	0x00012d36, 0xfff5eca2, 0x007f10ef,
+	0x00000001//output gain
+};
+
+static u32 coef_44to11[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c5102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_44to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00126104,//IIR Filter + interpolation
+	0x00000af2,//input gain
+	0x0057eebe, 0xff1e9863, 0x00652604,
+	0xff7206ea, 0xff22ad7e, 0x006d47e1,
+	0xff42a4d7, 0xff26e722, 0x0075fd83,
+	0xff352f66, 0xff29312b, 0x007b986b,
+	0xff310a07, 0xff296f51, 0x007eca7c,
+	0x00000002,//output gain
+	0x001d9204,//Farrow Filter + decimation
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005105,//IIR Filter + Decimator
+	0x0000d649,//input gain
+	0x00e87afb, 0xff5f69d0, 0x003df3cf,
+	0x007ce488, 0xff99a5c8, 0x0056a6a0,
+	0x00344928, 0xffcba3e5, 0x006be470,
+	0x00137aa7, 0xffe60276, 0x00773410,
+	0x0005fa2a, 0xfff1ac11, 0x007c795b,
+	0x00012d36, 0xfff5eca2, 0x007f10ef,
+	0x00000001//output gain
+};
+
+static u32 coef_44to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_44to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x00001685,//input gain
+	0x00f53ae9, 0xff52f196, 0x003e3e08,
+	0x00b9f857, 0xff5d8985, 0x0050070a,
+	0x008c3e86, 0xff6053f0, 0x006d98ef,
+	0x00000002,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_44to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0000015f,//input gain
+	0x00a7909c, 0xff241c71, 0x005f5e00,
+	0xffca77f4, 0xff20dd50, 0x006855eb,
+	0xff86c552, 0xff18137a, 0x00773648,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000005f3,//input gain
+	0x00d816d6, 0xff385383, 0x004fe566,
+	0x003c548d, 0xff38c23d, 0x005d0b1c,
+	0xfff02f7d, 0xff31e983, 0x0072d65d,
+	0x00000002,//output gain
+	0x00239204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_44to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00235204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d029,//input gain
+	0x00f2a98b, 0xff92aa71, 0x001fcd16,
+	0x00ae9004, 0xffb85140, 0x0041813a,
+	0x007f8ed1, 0xffd585fc, 0x006a69e6,
+	0x00000001//output gain
+};
+
+static u32 coef_44to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00006102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002//output gain
+};
+
+static u32 coef_44to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00005204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_44to176[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00006102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002//output gain
+};
+
+static u32 coef_44to192[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00246102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x00005204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_48to8[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c9102,//IIR Filter + Decimator
+	0x00000e00,//input gain
+	0x00e2e000, 0xff6e1a00, 0x002aaa00,
+	0x00610a00, 0xff5dda00, 0x003ccc00,
+	0x00163a00, 0xff3c0400, 0x00633200,
+	0x00000001,//output gain
+	0x00005105,//IIR Filter + Decimator
+	0x0000d649,//input gain
+	0x00e87afb, 0xff5f69d0, 0x003df3cf,
+	0x007ce488, 0xff99a5c8, 0x0056a6a0,
+	0x00344928, 0xffcba3e5, 0x006be470,
+	0x00137aa7, 0xffe60276, 0x00773410,
+	0x0005fa2a, 0xfff1ac11, 0x007c795b,
+	0x00012d36, 0xfff5eca2, 0x007f10ef,
+	0x00000001//output gain
+};
+
+static u32 coef_48to11[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x000000af,//input gain
+	0x00c65663, 0xff23d2ce, 0x005f97d6,
+	0x00086ad6, 0xff20ec4f, 0x00683201,
+	0xffbbbef6, 0xff184447, 0x00770963,
+	0x00000002,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00235102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_48to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00009105,//IIR Filter + Decimator
+	0x00000784,//input gain
+	0x00cc516e, 0xff2c9639, 0x005ad5b3,
+	0x0013ad0d, 0xff3d4799, 0x0063ce75,
+	0xffb6f398, 0xff5138d1, 0x006e9e1f,
+	0xff9186e5, 0xff5f96a4, 0x0076a86e,
+	0xff82089c, 0xff676b81, 0x007b9f8a,
+	0xff7c48a5, 0xff6a31e7, 0x007ebb7b,
+	0x00000001//output gain
+};
+
+static u32 coef_48to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000f6103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000002,//output gain
+	0x001a5204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_48to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_48to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00156105,//header
+	0x00000292,//input gain
+	0x00e4320a, 0xff41d2d9, 0x004911ac,
+	0x005dd9e3, 0xff4c7d80, 0x0052103e,
+	0xfff8ebef, 0xff5b6fab, 0x005f0a0d,
+	0xffc4b414, 0xff68582c, 0x006b38e5,
+	0xffabb861, 0xff704bec, 0x0074de52,
+	0xffa19f4c, 0xff729059, 0x007c7e90,
+	0x00000002,//output gain
+	0x00009105,//header
+	0x00000292,//input gain
+	0x00e4320a, 0xff41d2d9, 0x004911ac,
+	0x005dd9e3, 0xff4c7d80, 0x0052103e,
+	0xfff8ebef, 0xff5b6fab, 0x005f0a0d,
+	0xffc4b414, 0xff68582c, 0x006b38e5,
+	0xffabb861, 0xff704bec, 0x0074de52,
+	0xffa19f4c, 0xff729059, 0x007c7e90,
+	0x00000001//output gain
+};
+
+static u32 coef_48to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d029,//input gain
+	0x00f2a98b, 0xff92aa71, 0x001fcd16,
+	0x00ae9004, 0xffb85140, 0x0041813a,
+	0x007f8ed1, 0xffd585fc, 0x006a69e6,
+	0x00000002,//output gain
+	0x001b6103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000002,//output gain
+	0x00265204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_48to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00230204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x00001685,//input gain
+	0x00f53ae9, 0xff52f196, 0x003e3e08,
+	0x00b9f857, 0xff5d8985, 0x0050070a,
+	0x008c3e86, 0xff6053f0, 0x006d98ef,
+	0x00000001//output gain
+};
+
+static u32 coef_48to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00006102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002//output gain
+};
+
+static u32 coef_48to176[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00246102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x002f0204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x00000138,//input gain
+	0x00d5d232, 0xff2a3bf8, 0x005a785c,
+	0x0034001b, 0xff283109, 0x006462a6,
+	0xffe6746a, 0xff1fb09c, 0x00758a91,
+	0x00000001//output gain
+};
+
+static u32 coef_48to192[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000002,//output gain
+	0x00006102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002//output gain
+};
+
+static u32 coef_88to8[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c0102,//header
+	0x00000057,//input gain
+	0x00a8e717, 0xff1c748d, 0x0065b976,
+	0xffcbccab, 0xff190aff, 0x006cc1cf,
+	0xff871ce1, 0xff10d878, 0x0078cfc5,
+	0x00000001,//output gain
+	0x00179204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00235102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_88to11[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c5102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000001,//output gain
+	0x00185102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_88to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c0102,//header
+	0x000005f3,//input gain
+	0x00d816d6, 0xff385383, 0x004fe566,
+	0x003c548d, 0xff38c23d, 0x005d0b1c,
+	0xfff02f7d, 0xff31e983, 0x0072d65d,
+	0x00000001,//output gain
+	0x00179204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_88to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c5102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_88to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c0102,//header
+	0x00001685,//input gain
+	0x00f53ae9, 0xff52f196, 0x003e3e08,
+	0x00b9f857, 0xff5d8985, 0x0050070a,
+	0x008c3e86, 0xff6053f0, 0x006d98ef,
+	0x00000001,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_88to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x000005f3,//input gain
+	0x00d816d6, 0xff385383, 0x004fe566,
+	0x003c548d, 0xff38c23d, 0x005d0b1c,
+	0xfff02f7d, 0xff31e983, 0x0072d65d,
+	0x00000002,//output gain
+	0x00179204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_88to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_88to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x00001685,//input gain
+	0x00f53ae9, 0xff52f196, 0x003e3e08,
+	0x00b9f857, 0xff5d8985, 0x0050070a,
+	0x008c3e86, 0xff6053f0, 0x006d98ef,
+	0x00000002,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_88to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00005204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_88to176[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00006102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002//output gain
+};
+
+static u32 coef_88to192[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000002,//output gain
+	0x00186102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x00005204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_96to8[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c9102,//header
+	0x0000007d,//input gain
+	0x007d1f20, 0xff1a540e, 0x00678bf9,
+	0xff916625, 0xff16b0ff, 0x006e433a,
+	0xff5af660, 0xff0eb91f, 0x00797356,
+	0x00000001,//output gain
+	0x00185102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_96to11[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c0102,//header
+	0x000000af,//input gain
+	0x00c65663, 0xff23d2ce, 0x005f97d6,
+	0x00086ad6, 0xff20ec4f, 0x00683201,
+	0xffbbbef6, 0xff184447, 0x00770963,
+	0x00000001,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00235102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_96to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c9102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_96to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x000000af,//input gain
+	0x00c65663, 0xff23d2ce, 0x005f97d6,
+	0x00086ad6, 0xff20ec4f, 0x00683201,
+	0xffbbbef6, 0xff184447, 0x00770963,
+	0x00000002,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00235102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_96to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c5102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_96to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00009105,//header
+	0x00000292,//input gain
+	0x00e4320a, 0xff41d2d9, 0x004911ac,
+	0x005dd9e3, 0xff4c7d80, 0x0052103e,
+	0xfff8ebef, 0xff5b6fab, 0x005f0a0d,
+	0xffc4b414, 0xff68582c, 0x006b38e5,
+	0xffabb861, 0xff704bec, 0x0074de52,
+	0xffa19f4c, 0xff729059, 0x007c7e90,
+	0x00000001//output gain
+};
+
+static u32 coef_96to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000f6103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000002,//output gain
+	0x001a5204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_96to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_96to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000f6103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000002,//output gain
+	0x001a0204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001//output gain
+};
+
+static u32 coef_96to176[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000f6103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000002,//output gain
+	0x001b6102,//header
+	0x000000af,//input gain
+	0x00c65663, 0xff23d2ce, 0x005f97d6,
+	0x00086ad6, 0xff20ec4f, 0x00683201,
+	0xffbbbef6, 0xff184447, 0x00770963,
+	0x00000002,//output gain
+	0x00260204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000001//output gain
+};
+
+static u32 coef_96to192[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00006103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000002//output gain
+};
+
+static u32 coef_176to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c0102,//header
+	0x00000057,//input gain
+	0x00a8e717, 0xff1c748d, 0x0065b976,
+	0xffcbccab, 0xff190aff, 0x006cc1cf,
+	0xff871ce1, 0xff10d878, 0x0078cfc5,
+	0x00000001,//output gain
+	0x00179204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00235102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_176to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c5102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000001,//output gain
+	0x00185102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_176to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c0102,//header
+	0x00000138,//input gain
+	0x00d5d232, 0xff2a3bf8, 0x005a785c,
+	0x0034001b, 0xff283109, 0x006462a6,
+	0xffe6746a, 0xff1fb09c, 0x00758a91,
+	0x00000001,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00235102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_176to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c0102,//header
+	0x000005f3,//input gain
+	0x00d816d6, 0xff385383, 0x004fe566,
+	0x003c548d, 0xff38c23d, 0x005d0b1c,
+	0xfff02f7d, 0xff31e983, 0x0072d65d,
+	0x00000001,//output gain
+	0x00179204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_176to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c5102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_176to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c0102,//header
+	0x00001685,//input gain
+	0x00f53ae9, 0xff52f196, 0x003e3e08,
+	0x00b9f857, 0xff5d8985, 0x0050070a,
+	0x008c3e86, 0xff6053f0, 0x006d98ef,
+	0x00000001,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_176to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00005102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001//output gain
+};
+
+static u32 coef_176to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000001//output gain
+};
+
+static u32 coef_176to192[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000002,//output gain
+	0x00005204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000
+};
+
+static u32 coef_192to16[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c9102,//header
+	0x0000007d,//input gain
+	0x007d1f20, 0xff1a540e, 0x00678bf9,
+	0xff916625, 0xff16b0ff, 0x006e433a,
+	0xff5af660, 0xff0eb91f, 0x00797356,
+	0x00000001,//output gain
+	0x00185102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_192to22[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c0102,//header
+	0x000000af,//input gain
+	0x00c65663, 0xff23d2ce, 0x005f97d6,
+	0x00086ad6, 0xff20ec4f, 0x00683201,
+	0xffbbbef6, 0xff184447, 0x00770963,
+	0x00000001,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00235102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_192to24[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c5102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000001,//output gain
+	0x00185102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_192to32[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c9102,//header
+	0x000005d6,//input gain
+	0x00c6543e, 0xff342935, 0x0052f116,
+	0x000a1d78, 0xff3330c0, 0x005f88a3,
+	0xffbee7c0, 0xff2b5ba5, 0x0073eb26,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_192to44[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x000000af,//input gain
+	0x00c65663, 0xff23d2ce, 0x005f97d6,
+	0x00086ad6, 0xff20ec4f, 0x00683201,
+	0xffbbbef6, 0xff184447, 0x00770963,
+	0x00000002,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00235102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_192to48[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c5102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001,//output gain
+	0x00005102,//header
+	0x0001d727,//input gain
+	0x00fc2fc7, 0xff9bb27b, 0x001c564c,
+	0x00e55557, 0xffcadd5b, 0x003d80ba,
+	0x00d13397, 0xfff232f8, 0x00683337,
+	0x00000001//output gain
+};
+
+static u32 coef_192to88[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x000000af,//input gain
+	0x00c65663, 0xff23d2ce, 0x005f97d6,
+	0x00086ad6, 0xff20ec4f, 0x00683201,
+	0xffbbbef6, 0xff184447, 0x00770963,
+	0x00000002,//output gain
+	0x00175204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x000013d9,//input gain
+	0x00ebd477, 0xff4ce383, 0x0042049d,
+	0x0089c278, 0xff54414d, 0x00531ded,
+	0x004a5e07, 0xff53cf41, 0x006efbdc,
+	0x00000001//output gain
+};
+
+static u32 coef_192to96[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x00005103,//header
+	0x000001e0,//input gain
+	0x00de44c0, 0xff380b7f, 0x004ffc73,
+	0x00494b44, 0xff3d493a, 0x005908bf,
+	0xffe9a3c8, 0xff425647, 0x006745f7,
+	0xffc42d61, 0xff40a6c7, 0x00776709,
+	0x00000001//output gain
+};
+
+static u32 coef_192to176[TEGRA210_SFC_COEF_RAM_DEPTH] = {
+	0x000c6102,//header
+	0x000000af,//input gain
+	0x00c65663, 0xff23d2ce, 0x005f97d6,
+	0x00086ad6, 0xff20ec4f, 0x00683201,
+	0xffbbbef6, 0xff184447, 0x00770963,
+	0x00000002,//output gain
+	0x00170204,//farrow
+	0x000aaaab,
+	0xffaaaaab,
+	0xfffaaaab,
+	0x00555555,
+	0xff600000,
+	0xfff55555,
+	0x00155555,
+	0x00055555,
+	0xffeaaaab,
+	0x00200000,
+	0x00005102,//header
+	0x0000010a,//input gain
+	0x00c93dc4, 0xff26f5f6, 0x005d1041,
+	0x001002c4, 0xff245b76, 0x00666002,
+	0xffc30a45, 0xff1baecd, 0x00765921,
+	0x00000001//output gain
+};
+
+/*
+ * Coefficient table for various sample rate conversions. The sample
+ * rates available are as per tegra210_sfc_rates[].
+ */
+static s32 *coef_addr_table[TEGRA210_SFC_NUM_RATES][TEGRA210_SFC_NUM_RATES] = {
+	/* Convertions from 8 kHz */
+	{
+		BYPASS_CONV,
+		coef_8to11,
+		coef_8to16,
+		coef_8to22,
+		coef_8to24,
+		coef_8to32,
+		coef_8to44,
+		coef_8to48,
+		coef_8to88,
+		coef_8to96,
+		UNSUPP_CONV,
+		UNSUPP_CONV,
+	},
+	/* Convertions from 11.025 kHz */
+	{
+		coef_11to8,
+		BYPASS_CONV,
+		coef_11to16,
+		coef_11to22,
+		coef_11to24,
+		coef_11to32,
+		coef_11to44,
+		coef_11to48,
+		coef_11to88,
+		coef_11to96,
+		UNSUPP_CONV,
+		UNSUPP_CONV,
+	},
+	/* Convertions from 16 kHz */
+	{
+		coef_16to8,
+		coef_16to11,
+		BYPASS_CONV,
+		coef_16to22,
+		coef_16to24,
+		coef_16to32,
+		coef_16to44,
+		coef_16to48,
+		coef_16to88,
+		coef_16to96,
+		coef_16to176,
+		coef_16to192,
+	},
+	/* Convertions from 22.05 kHz */
+	{
+		coef_22to8,
+		coef_22to11,
+		coef_22to16,
+		BYPASS_CONV,
+		coef_22to24,
+		coef_22to32,
+		coef_22to44,
+		coef_22to48,
+		coef_22to88,
+		coef_22to96,
+		coef_22to176,
+		coef_22to192,
+	},
+	/* Convertions from 24 kHz */
+	{
+		coef_24to8,
+		coef_24to11,
+		coef_24to16,
+		coef_24to22,
+		BYPASS_CONV,
+		coef_24to32,
+		coef_24to44,
+		coef_24to48,
+		coef_24to88,
+		coef_24to96,
+		coef_24to176,
+		coef_24to192,
+	},
+	/* Convertions from 32 kHz */
+	{
+		coef_32to8,
+		coef_32to11,
+		coef_32to16,
+		coef_32to22,
+		coef_32to24,
+		BYPASS_CONV,
+		coef_32to44,
+		coef_32to48,
+		coef_32to88,
+		coef_32to96,
+		coef_32to176,
+		coef_32to192,
+	},
+	/* Convertions from 44.1 kHz */
+	{
+		coef_44to8,
+		coef_44to11,
+		coef_44to16,
+		coef_44to22,
+		coef_44to24,
+		coef_44to32,
+		BYPASS_CONV,
+		coef_44to48,
+		coef_44to88,
+		coef_44to96,
+		coef_44to176,
+		coef_44to192,
+	},
+	/* Convertions from 48 kHz */
+	{
+		coef_48to8,
+		coef_48to11,
+		coef_48to16,
+		coef_48to22,
+		coef_48to24,
+		coef_48to32,
+		coef_48to44,
+		BYPASS_CONV,
+		coef_48to88,
+		coef_48to96,
+		coef_48to176,
+		coef_48to192,
+	},
+	/* Convertions from 88.2 kHz */
+	{
+		coef_88to8,
+		coef_88to11,
+		coef_88to16,
+		coef_88to22,
+		coef_88to24,
+		coef_88to32,
+		coef_88to44,
+		coef_88to48,
+		BYPASS_CONV,
+		coef_88to96,
+		coef_88to176,
+		coef_88to192,
+	},
+	/* Convertions from 96 kHz */
+	{	coef_96to8,
+		coef_96to11,
+		coef_96to16,
+		coef_96to22,
+		coef_96to24,
+		coef_96to32,
+		coef_96to44,
+		coef_96to48,
+		coef_96to88,
+		BYPASS_CONV,
+		coef_96to176,
+		coef_96to192,
+	},
+	/* Convertions from 176.4 kHz */
+	{
+		UNSUPP_CONV,
+		UNSUPP_CONV,
+		coef_176to16,
+		coef_176to22,
+		coef_176to24,
+		coef_176to32,
+		coef_176to44,
+		coef_176to48,
+		coef_176to88,
+		coef_176to96,
+		BYPASS_CONV,
+		coef_176to192,
+	},
+	/* Convertions from 192 kHz */
+	{
+		UNSUPP_CONV,
+		UNSUPP_CONV,
+		coef_192to16,
+		coef_192to22,
+		coef_192to24,
+		coef_192to32,
+		coef_192to44,
+		coef_192to48,
+		coef_192to88,
+		coef_192to96,
+		coef_192to176,
+		BYPASS_CONV,
+	},
+};
+
+static int __maybe_unused tegra210_sfc_runtime_suspend(struct device *dev)
+{
+	struct tegra210_sfc *sfc = dev_get_drvdata(dev);
+
+	regcache_cache_only(sfc->regmap, true);
+	regcache_mark_dirty(sfc->regmap);
+
+	return 0;
+}
+
+static int __maybe_unused tegra210_sfc_runtime_resume(struct device *dev)
+{
+	struct tegra210_sfc *sfc = dev_get_drvdata(dev);
+
+	regcache_cache_only(sfc->regmap, false);
+	regcache_sync(sfc->regmap);
+
+	return 0;
+}
+
+static inline void tegra210_sfc_write_ram(struct regmap *regmap,
+					  s32 *data)
+{
+	int i;
+
+	regmap_write(regmap, TEGRA210_SFC_CFG_RAM_CTRL,
+		     TEGRA210_SFC_RAM_CTRL_SEQ_ACCESS_EN |
+		     TEGRA210_SFC_RAM_CTRL_ADDR_INIT_EN |
+		     TEGRA210_SFC_RAM_CTRL_RW_WRITE);
+
+	for (i = 0; i < TEGRA210_SFC_COEF_RAM_DEPTH; i++)
+		regmap_write(regmap, TEGRA210_SFC_CFG_RAM_DATA, data[i]);
+}
+
+static int tegra210_sfc_write_coeff_ram(struct snd_soc_component *cmpnt)
+{
+	struct tegra210_sfc *sfc = dev_get_drvdata(cmpnt->dev);
+	s32 *coeff_ram;
+
+	/* Bypass */
+	if (sfc->srate_in == sfc->srate_out)
+		return 0;
+
+	coeff_ram = coef_addr_table[sfc->srate_in][sfc->srate_out];
+	if (IS_ERR_OR_NULL(coeff_ram)) {
+		dev_err(cmpnt->dev,
+			"Conversion from %d to %d Hz is not supported\n",
+			sfc->srate_in, sfc->srate_out);
+
+		return PTR_ERR_OR_ZERO(coeff_ram);
+	}
+
+	tegra210_sfc_write_ram(sfc->regmap, coeff_ram);
+
+	regmap_update_bits(sfc->regmap,
+			   TEGRA210_SFC_COEF_RAM,
+			   TEGRA210_SFC_COEF_RAM_EN,
+			   TEGRA210_SFC_COEF_RAM_EN);
+
+	return 0;
+}
+
+static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc,
+				      struct snd_pcm_hw_params *params,
+				      unsigned int reg)
+{
+	unsigned int channels, audio_bits, path;
+	struct tegra_cif_conf cif_conf;
+
+	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
+
+	channels = params_channels(params);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		audio_bits = TEGRA_ACIF_BITS_16;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		audio_bits = TEGRA_ACIF_BITS_32;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	cif_conf.audio_ch = channels;
+	cif_conf.client_ch = channels;
+	cif_conf.audio_bits = audio_bits;
+	cif_conf.client_bits = TEGRA_ACIF_BITS_32;
+
+	if (reg == TEGRA210_SFC_RX_CIF_CTRL)
+		path = SFC_RX_PATH;
+	else
+		path = SFC_TX_PATH;
+
+	cif_conf.stereo_conv = sfc->stereo_to_mono[path];
+	cif_conf.mono_conv = sfc->mono_to_stereo[path];
+
+	tegra_set_cif(sfc->regmap, reg, &cif_conf);
+
+	return 0;
+}
+
+static int tegra210_sfc_soft_reset(struct tegra210_sfc *sfc)
+{
+	u32 val;
+
+	/* SW reset */
+	regmap_update_bits(sfc->regmap, TEGRA210_SFC_SOFT_RESET,
+			   TEGRA210_SFC_SOFT_RESET_EN, 1);
+
+	return regmap_read_poll_timeout(sfc->regmap,
+					TEGRA210_SFC_SOFT_RESET,
+					val,
+					!(val & TEGRA210_SFC_SOFT_RESET_EN),
+					10, 10000);
+}
+
+static int tegra210_sfc_rate_to_idx(struct device *dev, int rate,
+				    int *rate_idx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tegra210_sfc_rates); i++) {
+		if (rate == tegra210_sfc_rates[i]) {
+			*rate_idx = i;
+
+			return 0;
+		}
+	}
+
+	dev_err(dev, "Sample rate %d Hz is not supported\n", rate);
+
+	return -EOPNOTSUPP;
+}
+
+static int tegra210_sfc_startup(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
+	int err;
+
+	regmap_update_bits(sfc->regmap, TEGRA210_SFC_COEF_RAM,
+			   TEGRA210_SFC_COEF_RAM_EN, 0);
+
+	err = tegra210_sfc_soft_reset(sfc);
+	if (err < 0) {
+		dev_err(dai->dev, "Failed to reset SFC in %s, err = %d\n",
+			__func__, err);
+
+		return err;
+	}
+
+	return 0;
+}
+
+static int tegra210_sfc_in_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params,
+				     struct snd_soc_dai *dai)
+{
+	struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
+	struct device *dev = dai->dev;
+	int err;
+
+	err = tegra210_sfc_rate_to_idx(dev, params_rate(params),
+				       &sfc->srate_in);
+	if (err < 0)
+		return err;
+
+	err = tegra210_sfc_set_audio_cif(sfc, params, TEGRA210_SFC_RX_CIF_CTRL);
+	if (err < 0) {
+		dev_err(dev, "Can't set SFC RX CIF: %d\n", err);
+		return err;
+	}
+
+	regmap_write(sfc->regmap, TEGRA210_SFC_RX_FREQ, sfc->srate_in);
+
+	return err;
+}
+
+static int tegra210_sfc_out_hw_params(struct snd_pcm_substream *substream,
+				      struct snd_pcm_hw_params *params,
+				      struct snd_soc_dai *dai)
+{
+	struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
+	struct device *dev = dai->dev;
+	int err;
+
+	err = tegra210_sfc_rate_to_idx(dev, params_rate(params),
+				       &sfc->srate_out);
+	if (err < 0)
+		return err;
+
+	err = tegra210_sfc_set_audio_cif(sfc, params, TEGRA210_SFC_TX_CIF_CTRL);
+	if (err < 0) {
+		dev_err(dev, "Can't set SFC TX CIF: %d\n", err);
+		return err;
+	}
+
+	regmap_write(sfc->regmap, TEGRA210_SFC_TX_FREQ, sfc->srate_out);
+
+	return 0;
+}
+
+static int tegra210_sfc_init(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+
+	return tegra210_sfc_write_coeff_ram(cmpnt);
+}
+
+static int tegra210_sfc_get_control(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
+
+	if (strstr(kcontrol->id.name, "Input Stereo To Mono"))
+		ucontrol->value.integer.value[0] =
+			sfc->stereo_to_mono[SFC_RX_PATH];
+	else if (strstr(kcontrol->id.name, "Input Mono To Stereo"))
+		ucontrol->value.integer.value[0] =
+			sfc->mono_to_stereo[SFC_RX_PATH];
+	else if (strstr(kcontrol->id.name, "Output Stereo To Mono"))
+		ucontrol->value.integer.value[0] =
+			sfc->stereo_to_mono[SFC_TX_PATH];
+	else if (strstr(kcontrol->id.name, "Output Mono To Stereo"))
+		ucontrol->value.integer.value[0] =
+			sfc->mono_to_stereo[SFC_TX_PATH];
+
+	return 0;
+}
+
+static int tegra210_sfc_put_control(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
+	int value = ucontrol->value.integer.value[0];
+
+	if (strstr(kcontrol->id.name, "Input Stereo To Mono"))
+		sfc->stereo_to_mono[SFC_RX_PATH] = value;
+	else if (strstr(kcontrol->id.name, "Input Mono To Stereo"))
+		sfc->mono_to_stereo[SFC_RX_PATH] = value;
+	else if (strstr(kcontrol->id.name, "Output Stereo To Mono"))
+		sfc->stereo_to_mono[SFC_TX_PATH] = value;
+	else if (strstr(kcontrol->id.name, "Output Mono To Stereo"))
+		sfc->mono_to_stereo[SFC_TX_PATH] = value;
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops tegra210_sfc_in_dai_ops = {
+	.hw_params	= tegra210_sfc_in_hw_params,
+	.startup	= tegra210_sfc_startup,
+};
+
+static struct snd_soc_dai_ops tegra210_sfc_out_dai_ops = {
+	.hw_params	= tegra210_sfc_out_hw_params,
+};
+
+static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
+	{
+		.name = "SFC-RX-CIF",
+		.playback = {
+			.stream_name = "RX-CIF-Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S8 |
+				SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.capture = {
+			.stream_name = "RX-CIF-Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S8 |
+				SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &tegra210_sfc_in_dai_ops,
+	},
+	{
+		.name = "SFC-TX-CIF",
+		.playback = {
+			.stream_name = "TX-CIF-Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S8 |
+				SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.capture = {
+			.stream_name = "TX-CIF-Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S8 |
+				SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &tegra210_sfc_out_dai_ops,
+	},
+};
+
+static const struct snd_soc_dapm_widget tegra210_sfc_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("RX", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT_E("TX", NULL, 0, TEGRA210_SFC_ENABLE,
+			       TEGRA210_SFC_EN_SHIFT, 0,
+			       tegra210_sfc_init, SND_SOC_DAPM_PRE_PMU),
+};
+
+#define RESAMPLE_ROUTE(sname)					\
+	{ "RX XBAR-" sname,	NULL,	"XBAR-TX" },		\
+	{ "RX-CIF-" sname,	NULL,	"RX XBAR-" sname },	\
+	{ "RX",			NULL,	"RX-CIF-" sname },	\
+	{ "TX-CIF-" sname,	NULL,	"TX" },			\
+	{ "TX XBAR-" sname,	NULL,	"TX-CIF-" sname },	\
+	{ "XBAR-RX",		NULL,	"TX XBAR-" sname }
+
+static const struct snd_soc_dapm_route tegra210_sfc_routes[] = {
+	{ "TX", NULL, "RX" },
+	RESAMPLE_ROUTE("Playback"),
+	RESAMPLE_ROUTE("Capture"),
+};
+
+static const char * const tegra210_sfc_stereo_conv_text[] = {
+	"CH0", "CH1", "AVG",
+};
+
+static const char * const tegra210_sfc_mono_conv_text[] = {
+	"Zero", "Copy",
+};
+
+static const struct soc_enum tegra210_sfc_stereo_conv_enum =
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+			ARRAY_SIZE(tegra210_sfc_stereo_conv_text),
+			tegra210_sfc_stereo_conv_text);
+
+static const struct soc_enum tegra210_sfc_mono_conv_enum =
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+			ARRAY_SIZE(tegra210_sfc_mono_conv_text),
+			tegra210_sfc_mono_conv_text);
+
+static const struct snd_kcontrol_new tegra210_sfc_controls[] = {
+	SOC_ENUM_EXT("Input Stereo To Mono", tegra210_sfc_stereo_conv_enum,
+		tegra210_sfc_get_control, tegra210_sfc_put_control),
+	SOC_ENUM_EXT("Input Mono To Stereo", tegra210_sfc_mono_conv_enum,
+		tegra210_sfc_get_control, tegra210_sfc_put_control),
+	SOC_ENUM_EXT("Output Stereo To Mono", tegra210_sfc_stereo_conv_enum,
+		tegra210_sfc_get_control, tegra210_sfc_put_control),
+	SOC_ENUM_EXT("Output Mono To Stereo", tegra210_sfc_mono_conv_enum,
+		tegra210_sfc_get_control, tegra210_sfc_put_control),
+};
+
+static const struct snd_soc_component_driver tegra210_sfc_cmpnt = {
+	.dapm_widgets		= tegra210_sfc_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(tegra210_sfc_widgets),
+	.dapm_routes		= tegra210_sfc_routes,
+	.num_dapm_routes	= ARRAY_SIZE(tegra210_sfc_routes),
+	.controls		= tegra210_sfc_controls,
+	.num_controls		= ARRAY_SIZE(tegra210_sfc_controls),
+};
+
+static bool tegra210_sfc_wr_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_SFC_RX_INT_MASK ... TEGRA210_SFC_RX_FREQ:
+	case TEGRA210_SFC_TX_INT_MASK ... TEGRA210_SFC_TX_FREQ:
+	case TEGRA210_SFC_ENABLE ... TEGRA210_SFC_CG:
+	case TEGRA210_SFC_COEF_RAM ... TEGRA210_SFC_CFG_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra210_sfc_rd_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_SFC_RX_STATUS ... TEGRA210_SFC_RX_FREQ:
+	case TEGRA210_SFC_TX_STATUS ... TEGRA210_SFC_TX_FREQ:
+	case TEGRA210_SFC_ENABLE ... TEGRA210_SFC_INT_STATUS:
+	case TEGRA210_SFC_COEF_RAM ... TEGRA210_SFC_CFG_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra210_sfc_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_SFC_RX_STATUS:
+	case TEGRA210_SFC_RX_INT_STATUS:
+	case TEGRA210_SFC_RX_INT_SET:
+
+	case TEGRA210_SFC_TX_STATUS:
+	case TEGRA210_SFC_TX_INT_STATUS:
+	case TEGRA210_SFC_TX_INT_SET:
+
+	case TEGRA210_SFC_SOFT_RESET:
+	case TEGRA210_SFC_STATUS:
+	case TEGRA210_SFC_INT_STATUS:
+	case TEGRA210_SFC_CFG_RAM_CTRL:
+	case TEGRA210_SFC_CFG_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra210_sfc_precious_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_SFC_CFG_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config tegra210_sfc_regmap_config = {
+	.reg_bits		= 32,
+	.reg_stride		= 4,
+	.val_bits		= 32,
+	.max_register		= TEGRA210_SFC_CFG_RAM_DATA,
+	.writeable_reg		= tegra210_sfc_wr_reg,
+	.readable_reg		= tegra210_sfc_rd_reg,
+	.volatile_reg		= tegra210_sfc_volatile_reg,
+	.precious_reg		= tegra210_sfc_precious_reg,
+	.reg_defaults		= tegra210_sfc_reg_defaults,
+	.num_reg_defaults	= ARRAY_SIZE(tegra210_sfc_reg_defaults),
+	.cache_type		= REGCACHE_FLAT,
+};
+
+static const struct of_device_id tegra210_sfc_of_match[] = {
+	{ .compatible = "nvidia,tegra210-sfc" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tegra210_sfc_of_match);
+
+static int tegra210_sfc_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra210_sfc *sfc;
+	void __iomem *regs;
+	int err;
+
+	sfc = devm_kzalloc(dev, sizeof(*sfc), GFP_KERNEL);
+	if (!sfc)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, sfc);
+
+	regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	sfc->regmap = devm_regmap_init_mmio(dev, regs,
+					    &tegra210_sfc_regmap_config);
+	if (IS_ERR(sfc->regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(sfc->regmap);
+	}
+
+	regcache_cache_only(sfc->regmap, true);
+
+	err = devm_snd_soc_register_component(dev, &tegra210_sfc_cmpnt,
+					      tegra210_sfc_dais,
+					      ARRAY_SIZE(tegra210_sfc_dais));
+	if (err) {
+		dev_err(dev, "can't register SFC component, err: %d\n", err);
+		return err;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+}
+
+static int tegra210_sfc_platform_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops tegra210_sfc_pm_ops = {
+	SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend,
+			   tegra210_sfc_runtime_resume, NULL)
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				     pm_runtime_force_resume)
+};
+
+static struct platform_driver tegra210_sfc_driver = {
+	.driver = {
+		.name = "tegra210-sfc",
+		.of_match_table = tegra210_sfc_of_match,
+		.pm = &tegra210_sfc_pm_ops,
+	},
+	.probe = tegra210_sfc_platform_probe,
+	.remove = tegra210_sfc_platform_remove,
+};
+module_platform_driver(tegra210_sfc_driver)
+
+MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>");
+MODULE_DESCRIPTION("Tegra210 SFC ASoC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/tegra/tegra210_sfc.h b/sound/soc/tegra/tegra210_sfc.h
new file mode 100644
index 0000000..5a6b66e
--- /dev/null
+++ b/sound/soc/tegra/tegra210_sfc.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * tegra210_sfc.h - Definitions for Tegra210 SFC driver
+ *
+ * Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+ *
+ */
+
+#ifndef __TEGRA210_SFC_H__
+#define __TEGRA210_SFC_H__
+
+/*
+ * SFC_RX registers are with respect to XBAR.
+ * The data comes from XBAR to SFC.
+ */
+#define TEGRA210_SFC_RX_STATUS			0x0c
+#define TEGRA210_SFC_RX_INT_STATUS		0x10
+#define TEGRA210_SFC_RX_INT_MASK		0x14
+#define TEGRA210_SFC_RX_INT_SET			0x18
+#define TEGRA210_SFC_RX_INT_CLEAR		0x1c
+#define TEGRA210_SFC_RX_CIF_CTRL		0x20
+#define TEGRA210_SFC_RX_FREQ			0x24
+
+/*
+ * SFC_TX registers are with respect to XBAR.
+ * The data goes out of SFC.
+ */
+#define TEGRA210_SFC_TX_STATUS			0x4c
+#define TEGRA210_SFC_TX_INT_STATUS		0x50
+#define TEGRA210_SFC_TX_INT_MASK		0x54
+#define TEGRA210_SFC_TX_INT_SET			0x58
+#define TEGRA210_SFC_TX_INT_CLEAR		0x5c
+#define TEGRA210_SFC_TX_CIF_CTRL		0x60
+#define TEGRA210_SFC_TX_FREQ			0x64
+
+/* Register offsets from TEGRA210_SFC*_BASE */
+#define TEGRA210_SFC_ENABLE			0x80
+#define TEGRA210_SFC_SOFT_RESET			0x84
+#define TEGRA210_SFC_CG				0x88
+#define TEGRA210_SFC_STATUS			0x8c
+#define TEGRA210_SFC_INT_STATUS			0x90
+#define TEGRA210_SFC_COEF_RAM			0xbc
+#define TEGRA210_SFC_CFG_RAM_CTRL		0xc0
+#define TEGRA210_SFC_CFG_RAM_DATA		0xc4
+
+/* Fields in TEGRA210_SFC_ENABLE */
+#define TEGRA210_SFC_EN_SHIFT			0
+#define TEGRA210_SFC_EN				(1 << TEGRA210_SFC_EN_SHIFT)
+
+#define TEGRA210_SFC_NUM_RATES 12
+
+/* Fields in TEGRA210_SFC_COEF_RAM */
+#define TEGRA210_SFC_COEF_RAM_EN		BIT(0)
+
+#define TEGRA210_SFC_SOFT_RESET_EN              BIT(0)
+
+/* Coefficients */
+#define TEGRA210_SFC_COEF_RAM_DEPTH		64
+#define TEGRA210_SFC_RAM_CTRL_RW_WRITE		(1 << 14)
+#define TEGRA210_SFC_RAM_CTRL_ADDR_INIT_EN	(1 << 13)
+#define TEGRA210_SFC_RAM_CTRL_SEQ_ACCESS_EN	(1 << 12)
+
+
+enum tegra210_sfc_path {
+	SFC_RX_PATH,
+	SFC_TX_PATH,
+	SFC_PATHS,
+};
+
+struct tegra210_sfc {
+	unsigned int mono_to_stereo[SFC_PATHS];
+	unsigned int stereo_to_mono[SFC_PATHS];
+	unsigned int srate_out;
+	unsigned int srate_in;
+	struct regmap *regmap;
+};
+
+#endif
-- 
2.7.4


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

* [PATCH 08/13] ASoC: tegra: Add Tegra210 based AMX driver
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (6 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 07/13] ASoC: tegra: Add Tegra210 based SFC driver Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-08-27  9:33 ` [PATCH 09/13] ASoC: tegra: Add Tegra210 based ADX driver Sameer Pujar
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

The Audio Multiplexer (AMX) block can multiplex up to four input streams
each of which can have maximum 16 channels and generate an output stream
with maximum 16 channels. A byte RAM helps to form an output frame by
any combination of bytes from the input frames.

This patch registers AMX driver with ASoC framework. The component driver
exposes DAPM widgets, routes and kcontrols for the device. The DAI driver
exposes AMX interfaces, which can be used to connect different components
in the ASoC layer. Makefile and Kconfig support is added to allow build
the driver. It can be enabled in the DT via "nvidia,tegra210-amx" for
Tegra210 and Tegra186. For Tegra194 and later, "nvidia,tegra194-amx" can
be used.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 sound/soc/tegra/Kconfig        |   9 +
 sound/soc/tegra/Makefile       |   2 +
 sound/soc/tegra/tegra210_amx.c | 595 +++++++++++++++++++++++++++++++++++++++++
 sound/soc/tegra/tegra210_amx.h |  93 +++++++
 4 files changed, 699 insertions(+)
 create mode 100644 sound/soc/tegra/tegra210_amx.c
 create mode 100644 sound/soc/tegra/tegra210_amx.h

diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 102564e..54d8342 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -126,6 +126,15 @@ config SND_SOC_TEGRA210_SFC
 	  upto 2 channels (stereo).
 	  Say Y or M if you want to add support for Tegra210 SFC module.
 
+config SND_SOC_TEGRA210_AMX
+	tristate "Tegra210 AMX module"
+	help
+	  Config to enable the Audio Multiplexer (AMX) which can multiplex
+	  four input streams (each of up to 16 channels) and generate
+	  output stream (of up to 16 channels). A byte RAM helps to form an
+	  output frame by any combination of bytes from the input frames.
+	  Say Y or M if you want to add support for Tegra210 AMX module.
+
 config SND_SOC_TEGRA_AUDIO_GRAPH_CARD
 	tristate "Audio Graph Card based Tegra driver"
 	depends on SND_AUDIO_GRAPH_CARD
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index bb0cf3a..549162b 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -15,6 +15,7 @@ snd-soc-tegra186-dspk-objs := tegra186_dspk.o
 snd-soc-tegra210-admaif-objs := tegra210_admaif.o
 snd-soc-tegra210-mvc-objs := tegra210_mvc.o
 snd-soc-tegra210-sfc-objs := tegra210_sfc.o
+snd-soc-tegra210-amx-objs := tegra210_amx.o
 
 obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
 obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o
@@ -30,6 +31,7 @@ obj-$(CONFIG_SND_SOC_TEGRA186_DSPK) += snd-soc-tegra186-dspk.o
 obj-$(CONFIG_SND_SOC_TEGRA210_ADMAIF) += snd-soc-tegra210-admaif.o
 obj-$(CONFIG_SND_SOC_TEGRA210_MVC) += snd-soc-tegra210-mvc.o
 obj-$(CONFIG_SND_SOC_TEGRA210_SFC) += snd-soc-tegra210-sfc.o
+obj-$(CONFIG_SND_SOC_TEGRA210_AMX) += snd-soc-tegra210-amx.o
 
 # Tegra machine Support
 snd-soc-tegra-wm8903-objs := tegra_wm8903.o
diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c
new file mode 100644
index 0000000..a6aa4f5
--- /dev/null
+++ b/sound/soc/tegra/tegra210_amx.c
@@ -0,0 +1,595 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// tegra210_amx.c - Tegra210 AMX driver
+//
+// Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra210_amx.h"
+#include "tegra_cif.h"
+
+/*
+ * The counter is in terms of AHUB clock cycles. If a frame is not
+ * received within these clock cycles, the AMX input channel gets
+ * automatically disabled. For now the counter is calculated as a
+ * function of sample rate (8 kHz) and AHUB clock (49.152 MHz).
+ * If later an accurate number is needed, the counter needs to be
+ * calculated at runtime.
+ *
+ *     count = ahub_clk / sample_rate
+ */
+#define TEGRA194_MAX_FRAME_IDLE_COUNT	0x1800
+
+#define AMX_CH_REG(id, reg) ((reg) + ((id) * TEGRA210_AMX_AUDIOCIF_CH_STRIDE))
+
+static const struct reg_default tegra210_amx_reg_defaults[] = {
+	{ TEGRA210_AMX_RX_INT_MASK, 0x0000000f},
+	{ TEGRA210_AMX_RX1_CIF_CTRL, 0x00007000},
+	{ TEGRA210_AMX_RX2_CIF_CTRL, 0x00007000},
+	{ TEGRA210_AMX_RX3_CIF_CTRL, 0x00007000},
+	{ TEGRA210_AMX_RX4_CIF_CTRL, 0x00007000},
+	{ TEGRA210_AMX_TX_INT_MASK, 0x00000001},
+	{ TEGRA210_AMX_TX_CIF_CTRL, 0x00007000},
+	{ TEGRA210_AMX_CG, 0x1},
+	{ TEGRA210_AMX_CFG_RAM_CTRL, 0x00004000},
+};
+
+static void tegra210_amx_write_map_ram(struct tegra210_amx *amx)
+{
+	int i;
+
+	regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_CTRL,
+		     TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
+		     TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN |
+		     TEGRA210_AMX_CFG_RAM_CTRL_RW_WRITE);
+
+	for (i = 0; i < TEGRA210_AMX_RAM_DEPTH; i++)
+		regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_DATA,
+			     amx->map[i]);
+
+	regmap_write(amx->regmap, TEGRA210_AMX_OUT_BYTE_EN0, amx->byte_mask[0]);
+	regmap_write(amx->regmap, TEGRA210_AMX_OUT_BYTE_EN1, amx->byte_mask[1]);
+}
+
+static int tegra210_amx_startup(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
+	unsigned int val;
+	int err;
+
+	/* Ensure if AMX is disabled */
+	err = regmap_read_poll_timeout(amx->regmap, TEGRA210_AMX_STATUS, val,
+				       !(val & 0x1), 10, 10000);
+	if (err < 0) {
+		dev_err(dai->dev, "failed to stop AMX, err = %d\n", err);
+		return err;
+	}
+
+	/* SW reset */
+	regmap_update_bits(amx->regmap, TEGRA210_AMX_SOFT_RESET,
+			   TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK,
+			   TEGRA210_AMX_SOFT_RESET_SOFT_EN);
+
+	err = regmap_read_poll_timeout(amx->regmap, TEGRA210_AMX_SOFT_RESET,
+				       val, !(val & 0x1), 10, 10000);
+	if (err < 0) {
+		dev_err(dai->dev, "failed to reset AMX, err = %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused tegra210_amx_runtime_suspend(struct device *dev)
+{
+	struct tegra210_amx *amx = dev_get_drvdata(dev);
+
+	regcache_cache_only(amx->regmap, true);
+	regcache_mark_dirty(amx->regmap);
+
+	return 0;
+}
+
+static int __maybe_unused tegra210_amx_runtime_resume(struct device *dev)
+{
+	struct tegra210_amx *amx = dev_get_drvdata(dev);
+
+	regcache_cache_only(amx->regmap, false);
+	regcache_sync(amx->regmap);
+
+	regmap_update_bits(amx->regmap,
+		TEGRA210_AMX_CTRL,
+		TEGRA210_AMX_CTRL_RX_DEP_MASK,
+		TEGRA210_AMX_WAIT_ON_ANY << TEGRA210_AMX_CTRL_RX_DEP_SHIFT);
+
+	tegra210_amx_write_map_ram(amx);
+
+	return 0;
+}
+
+static int tegra210_amx_set_audio_cif(struct snd_soc_dai *dai,
+				      struct snd_pcm_hw_params *params,
+				      unsigned int reg)
+{
+	struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
+	int channels, audio_bits;
+	struct tegra_cif_conf cif_conf;
+
+	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
+
+	channels = params_channels(params);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		audio_bits = TEGRA_ACIF_BITS_8;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		audio_bits = TEGRA_ACIF_BITS_16;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		audio_bits = TEGRA_ACIF_BITS_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cif_conf.audio_ch = channels;
+	cif_conf.client_ch = channels;
+	cif_conf.audio_bits = audio_bits;
+	cif_conf.client_bits = audio_bits;
+
+	tegra_set_cif(amx->regmap, reg, &cif_conf);
+
+	return 0;
+}
+
+static int tegra210_amx_in_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params,
+				     struct snd_soc_dai *dai)
+{
+	struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
+
+	if (amx->soc_data->auto_disable) {
+		regmap_write(amx->regmap,
+			     AMX_CH_REG(dai->id, TEGRA194_AMX_RX1_FRAME_PERIOD),
+			     TEGRA194_MAX_FRAME_IDLE_COUNT);
+		regmap_write(amx->regmap, TEGRA210_AMX_CYA, 1);
+	}
+
+	return tegra210_amx_set_audio_cif(dai, params,
+			AMX_CH_REG(dai->id, TEGRA210_AMX_RX1_CIF_CTRL));
+}
+
+static int tegra210_amx_out_hw_params(struct snd_pcm_substream *substream,
+				      struct snd_pcm_hw_params *params,
+				      struct snd_soc_dai *dai)
+{
+	return tegra210_amx_set_audio_cif(dai, params,
+					  TEGRA210_AMX_TX_CIF_CTRL);
+}
+
+static int tegra210_amx_get_byte_map(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	struct tegra210_amx *amx = snd_soc_component_get_drvdata(cmpnt);
+	unsigned char *bytes_map = (unsigned char *)&amx->map;
+	int reg = mc->reg;
+	int enabled;
+
+	if (reg > 31)
+		enabled = amx->byte_mask[1] & (1 << (reg - 32));
+	else
+		enabled = amx->byte_mask[0] & (1 << reg);
+
+	if (enabled)
+		ucontrol->value.integer.value[0] = bytes_map[reg];
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_amx *amx = snd_soc_component_get_drvdata(cmpnt);
+	unsigned char *bytes_map = (unsigned char *)&amx->map;
+	int reg = mc->reg;
+	int value = ucontrol->value.integer.value[0];
+
+	if (value >= 0 && value <= 255) {
+		/* Update byte map and enable slot */
+		bytes_map[reg] = value;
+		if (reg > 31)
+			amx->byte_mask[1] |= (1 << (reg - 32));
+		else
+			amx->byte_mask[0] |= (1 << reg);
+	} else {
+		/* Reset byte map and disable slot */
+		bytes_map[reg] = 0;
+		if (reg > 31)
+			amx->byte_mask[1] &= ~(1 << (reg - 32));
+		else
+			amx->byte_mask[0] &= ~(1 << reg);
+	}
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops tegra210_amx_out_dai_ops = {
+	.hw_params	= tegra210_amx_out_hw_params,
+	.startup	= tegra210_amx_startup,
+};
+
+static struct snd_soc_dai_ops tegra210_amx_in_dai_ops = {
+	.hw_params	= tegra210_amx_in_hw_params,
+};
+
+#define IN_DAI(id)						\
+	{							\
+		.name = "AMX-RX-CIF" #id,			\
+		.playback = {					\
+			.stream_name = "RX" #id "-CIF-Playback",\
+			.channels_min = 1,			\
+			.channels_max = 16,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				   SNDRV_PCM_FMTBIT_S16_LE |	\
+				   SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.capture = {					\
+			.stream_name = "RX" #id "-CIF-Capture",	\
+			.channels_min = 1,			\
+			.channels_max = 16,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				   SNDRV_PCM_FMTBIT_S16_LE |	\
+				   SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.ops = &tegra210_amx_in_dai_ops,		\
+	}
+
+#define OUT_DAI							\
+	{							\
+		.name = "AMX-TX-CIF",				\
+		.playback = {					\
+			.stream_name = "TX-CIF-Playback",	\
+			.channels_min = 1,			\
+			.channels_max = 16,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				   SNDRV_PCM_FMTBIT_S16_LE |	\
+				   SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.capture = {					\
+			.stream_name = "TX-CIF-Capture",	\
+			.channels_min = 1,			\
+			.channels_max = 16,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				   SNDRV_PCM_FMTBIT_S16_LE |	\
+				   SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.ops = &tegra210_amx_out_dai_ops,		\
+	}
+
+static struct snd_soc_dai_driver tegra210_amx_dais[] = {
+	IN_DAI(1),
+	IN_DAI(2),
+	IN_DAI(3),
+	IN_DAI(4),
+	OUT_DAI,
+};
+
+static const struct snd_soc_dapm_widget tegra210_amx_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("RX1", NULL, 0, TEGRA210_AMX_CTRL, 0, 0),
+	SND_SOC_DAPM_AIF_IN("RX2", NULL, 0, TEGRA210_AMX_CTRL, 1, 0),
+	SND_SOC_DAPM_AIF_IN("RX3", NULL, 0, TEGRA210_AMX_CTRL, 2, 0),
+	SND_SOC_DAPM_AIF_IN("RX4", NULL, 0, TEGRA210_AMX_CTRL, 3, 0),
+	SND_SOC_DAPM_AIF_OUT("TX", NULL, 0, TEGRA210_AMX_ENABLE,
+			     TEGRA210_AMX_ENABLE_SHIFT, 0),
+};
+
+#define STREAM_ROUTES(id, sname)					  \
+	{ "RX" #id " XBAR-" sname,	NULL,	"RX" #id " XBAR-TX" },	  \
+	{ "RX" #id "-CIF-" sname,	NULL,	"RX" #id " XBAR-" sname },\
+	{ "RX" #id,			NULL,	"RX" #id "-CIF-" sname }, \
+	{ "TX",				NULL,	"RX" #id },		  \
+	{ "TX-CIF-" sname,		NULL,	"TX" },			  \
+	{ "XBAR-" sname,		NULL,	"TX-CIF-" sname },	  \
+	{ "XBAR-RX",			NULL,	"XBAR-" sname }
+
+#define AMX_ROUTES(id)			\
+	STREAM_ROUTES(id, "Playback"),	\
+	STREAM_ROUTES(id, "Capture")
+
+static const struct snd_soc_dapm_route tegra210_amx_routes[] = {
+	AMX_ROUTES(1),
+	AMX_ROUTES(2),
+	AMX_ROUTES(3),
+	AMX_ROUTES(4),
+};
+
+#define TEGRA210_AMX_BYTE_MAP_CTRL(reg)					\
+	SOC_SINGLE_EXT("Byte Map " #reg, reg, 0, 256, 0,		\
+		       tegra210_amx_get_byte_map,			\
+		       tegra210_amx_put_byte_map)
+
+static struct snd_kcontrol_new tegra210_amx_controls[] = {
+	TEGRA210_AMX_BYTE_MAP_CTRL(0),
+	TEGRA210_AMX_BYTE_MAP_CTRL(1),
+	TEGRA210_AMX_BYTE_MAP_CTRL(2),
+	TEGRA210_AMX_BYTE_MAP_CTRL(3),
+	TEGRA210_AMX_BYTE_MAP_CTRL(4),
+	TEGRA210_AMX_BYTE_MAP_CTRL(5),
+	TEGRA210_AMX_BYTE_MAP_CTRL(6),
+	TEGRA210_AMX_BYTE_MAP_CTRL(7),
+	TEGRA210_AMX_BYTE_MAP_CTRL(8),
+	TEGRA210_AMX_BYTE_MAP_CTRL(9),
+	TEGRA210_AMX_BYTE_MAP_CTRL(10),
+	TEGRA210_AMX_BYTE_MAP_CTRL(11),
+	TEGRA210_AMX_BYTE_MAP_CTRL(12),
+	TEGRA210_AMX_BYTE_MAP_CTRL(13),
+	TEGRA210_AMX_BYTE_MAP_CTRL(14),
+	TEGRA210_AMX_BYTE_MAP_CTRL(15),
+	TEGRA210_AMX_BYTE_MAP_CTRL(16),
+	TEGRA210_AMX_BYTE_MAP_CTRL(17),
+	TEGRA210_AMX_BYTE_MAP_CTRL(18),
+	TEGRA210_AMX_BYTE_MAP_CTRL(19),
+	TEGRA210_AMX_BYTE_MAP_CTRL(20),
+	TEGRA210_AMX_BYTE_MAP_CTRL(21),
+	TEGRA210_AMX_BYTE_MAP_CTRL(22),
+	TEGRA210_AMX_BYTE_MAP_CTRL(23),
+	TEGRA210_AMX_BYTE_MAP_CTRL(24),
+	TEGRA210_AMX_BYTE_MAP_CTRL(25),
+	TEGRA210_AMX_BYTE_MAP_CTRL(26),
+	TEGRA210_AMX_BYTE_MAP_CTRL(27),
+	TEGRA210_AMX_BYTE_MAP_CTRL(28),
+	TEGRA210_AMX_BYTE_MAP_CTRL(29),
+	TEGRA210_AMX_BYTE_MAP_CTRL(30),
+	TEGRA210_AMX_BYTE_MAP_CTRL(31),
+	TEGRA210_AMX_BYTE_MAP_CTRL(32),
+	TEGRA210_AMX_BYTE_MAP_CTRL(33),
+	TEGRA210_AMX_BYTE_MAP_CTRL(34),
+	TEGRA210_AMX_BYTE_MAP_CTRL(35),
+	TEGRA210_AMX_BYTE_MAP_CTRL(36),
+	TEGRA210_AMX_BYTE_MAP_CTRL(37),
+	TEGRA210_AMX_BYTE_MAP_CTRL(38),
+	TEGRA210_AMX_BYTE_MAP_CTRL(39),
+	TEGRA210_AMX_BYTE_MAP_CTRL(40),
+	TEGRA210_AMX_BYTE_MAP_CTRL(41),
+	TEGRA210_AMX_BYTE_MAP_CTRL(42),
+	TEGRA210_AMX_BYTE_MAP_CTRL(43),
+	TEGRA210_AMX_BYTE_MAP_CTRL(44),
+	TEGRA210_AMX_BYTE_MAP_CTRL(45),
+	TEGRA210_AMX_BYTE_MAP_CTRL(46),
+	TEGRA210_AMX_BYTE_MAP_CTRL(47),
+	TEGRA210_AMX_BYTE_MAP_CTRL(48),
+	TEGRA210_AMX_BYTE_MAP_CTRL(49),
+	TEGRA210_AMX_BYTE_MAP_CTRL(50),
+	TEGRA210_AMX_BYTE_MAP_CTRL(51),
+	TEGRA210_AMX_BYTE_MAP_CTRL(52),
+	TEGRA210_AMX_BYTE_MAP_CTRL(53),
+	TEGRA210_AMX_BYTE_MAP_CTRL(54),
+	TEGRA210_AMX_BYTE_MAP_CTRL(55),
+	TEGRA210_AMX_BYTE_MAP_CTRL(56),
+	TEGRA210_AMX_BYTE_MAP_CTRL(57),
+	TEGRA210_AMX_BYTE_MAP_CTRL(58),
+	TEGRA210_AMX_BYTE_MAP_CTRL(59),
+	TEGRA210_AMX_BYTE_MAP_CTRL(60),
+	TEGRA210_AMX_BYTE_MAP_CTRL(61),
+	TEGRA210_AMX_BYTE_MAP_CTRL(62),
+	TEGRA210_AMX_BYTE_MAP_CTRL(63),
+};
+
+static const struct snd_soc_component_driver tegra210_amx_cmpnt = {
+	.dapm_widgets		= tegra210_amx_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(tegra210_amx_widgets),
+	.dapm_routes		= tegra210_amx_routes,
+	.num_dapm_routes	= ARRAY_SIZE(tegra210_amx_routes),
+	.controls		= tegra210_amx_controls,
+	.num_controls		= ARRAY_SIZE(tegra210_amx_controls),
+};
+
+static bool tegra210_amx_wr_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_AMX_RX_INT_MASK ... TEGRA210_AMX_RX4_CIF_CTRL:
+	case TEGRA210_AMX_TX_INT_MASK ... TEGRA210_AMX_CG:
+	case TEGRA210_AMX_CTRL ... TEGRA210_AMX_CYA:
+	case TEGRA210_AMX_CFG_RAM_CTRL ... TEGRA210_AMX_CFG_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra194_amx_wr_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA194_AMX_RX1_FRAME_PERIOD ... TEGRA194_AMX_RX4_FRAME_PERIOD:
+		return true;
+	default:
+		return tegra210_amx_wr_reg(dev, reg);
+	}
+}
+
+static bool tegra210_amx_rd_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_AMX_RX_STATUS ... TEGRA210_AMX_CFG_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra194_amx_rd_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA194_AMX_RX1_FRAME_PERIOD ... TEGRA194_AMX_RX4_FRAME_PERIOD:
+		return true;
+	default:
+		return tegra210_amx_rd_reg(dev, reg);
+	}
+}
+
+static bool tegra210_amx_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_AMX_RX_STATUS:
+	case TEGRA210_AMX_RX_INT_STATUS:
+	case TEGRA210_AMX_RX_INT_SET:
+	case TEGRA210_AMX_TX_STATUS:
+	case TEGRA210_AMX_TX_INT_STATUS:
+	case TEGRA210_AMX_TX_INT_SET:
+	case TEGRA210_AMX_SOFT_RESET:
+	case TEGRA210_AMX_STATUS:
+	case TEGRA210_AMX_INT_STATUS:
+	case TEGRA210_AMX_CFG_RAM_CTRL:
+	case TEGRA210_AMX_CFG_RAM_DATA:
+		return true;
+	default:
+		break;
+	}
+
+	return false;
+}
+
+static const struct regmap_config tegra210_amx_regmap_config = {
+	.reg_bits		= 32,
+	.reg_stride		= 4,
+	.val_bits		= 32,
+	.max_register		= TEGRA210_AMX_CFG_RAM_DATA,
+	.writeable_reg		= tegra210_amx_wr_reg,
+	.readable_reg		= tegra210_amx_rd_reg,
+	.volatile_reg		= tegra210_amx_volatile_reg,
+	.reg_defaults		= tegra210_amx_reg_defaults,
+	.num_reg_defaults	= ARRAY_SIZE(tegra210_amx_reg_defaults),
+	.cache_type		= REGCACHE_FLAT,
+};
+
+static const struct regmap_config tegra194_amx_regmap_config = {
+	.reg_bits		= 32,
+	.reg_stride		= 4,
+	.val_bits		= 32,
+	.max_register		= TEGRA194_AMX_RX4_LAST_FRAME_PERIOD,
+	.writeable_reg		= tegra194_amx_wr_reg,
+	.readable_reg		= tegra194_amx_rd_reg,
+	.volatile_reg		= tegra210_amx_volatile_reg,
+	.reg_defaults		= tegra210_amx_reg_defaults,
+	.num_reg_defaults	= ARRAY_SIZE(tegra210_amx_reg_defaults),
+	.cache_type		= REGCACHE_FLAT,
+};
+
+static const struct tegra210_amx_soc_data soc_data_tegra210 = {
+	.regmap_conf	= &tegra210_amx_regmap_config,
+};
+
+static const struct tegra210_amx_soc_data soc_data_tegra194 = {
+	.regmap_conf	= &tegra194_amx_regmap_config,
+	.auto_disable	= true,
+};
+
+static const struct of_device_id tegra210_amx_of_match[] = {
+	{ .compatible = "nvidia,tegra210-amx", .data = &soc_data_tegra210 },
+	{ .compatible = "nvidia,tegra194-amx", .data = &soc_data_tegra194 },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tegra210_amx_of_match);
+
+static int tegra210_amx_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra210_amx *amx;
+	void __iomem *regs;
+	int err;
+	const struct of_device_id *match;
+	struct tegra210_amx_soc_data *soc_data;
+
+	match = of_match_device(tegra210_amx_of_match, dev);
+
+	soc_data = (struct tegra210_amx_soc_data *)match->data;
+
+	amx = devm_kzalloc(dev, sizeof(*amx), GFP_KERNEL);
+	if (!amx)
+		return -ENOMEM;
+
+	amx->soc_data = soc_data;
+
+	dev_set_drvdata(dev, amx);
+
+	regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	amx->regmap = devm_regmap_init_mmio(dev, regs,
+					    soc_data->regmap_conf);
+	if (IS_ERR(amx->regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(amx->regmap);
+	}
+
+	regcache_cache_only(amx->regmap, true);
+
+	err = devm_snd_soc_register_component(dev, &tegra210_amx_cmpnt,
+					      tegra210_amx_dais,
+					      ARRAY_SIZE(tegra210_amx_dais));
+	if (err) {
+		dev_err(dev, "can't register AMX component, err: %d\n", err);
+		return err;
+	}
+
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+
+static int tegra210_amx_platform_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops tegra210_amx_pm_ops = {
+	SET_RUNTIME_PM_OPS(tegra210_amx_runtime_suspend,
+			   tegra210_amx_runtime_resume, NULL)
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				     pm_runtime_force_resume)
+};
+
+static struct platform_driver tegra210_amx_driver = {
+	.driver = {
+		.name = "tegra210-amx",
+		.of_match_table = tegra210_amx_of_match,
+		.pm = &tegra210_amx_pm_ops,
+	},
+	.probe = tegra210_amx_platform_probe,
+	.remove = tegra210_amx_platform_remove,
+};
+module_platform_driver(tegra210_amx_driver);
+
+MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
+MODULE_DESCRIPTION("Tegra210 AMX ASoC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/tegra/tegra210_amx.h b/sound/soc/tegra/tegra210_amx.h
new file mode 100644
index 0000000..e277741
--- /dev/null
+++ b/sound/soc/tegra/tegra210_amx.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * tegra210_amx.h - Definitions for Tegra210 AMX driver
+ *
+ * Copyright (c) 2021, NVIDIA CORPORATION.  All rights reserved.
+ *
+ */
+
+#ifndef __TEGRA210_AMX_H__
+#define __TEGRA210_AMX_H__
+
+/* Register offsets from TEGRA210_AMX*_BASE */
+#define TEGRA210_AMX_RX_STATUS			0x0c
+#define TEGRA210_AMX_RX_INT_STATUS		0x10
+#define TEGRA210_AMX_RX_INT_MASK		0x14
+#define TEGRA210_AMX_RX_INT_SET			0x18
+#define TEGRA210_AMX_RX_INT_CLEAR		0x1c
+#define TEGRA210_AMX_RX1_CIF_CTRL		0x20
+#define TEGRA210_AMX_RX2_CIF_CTRL		0x24
+#define TEGRA210_AMX_RX3_CIF_CTRL		0x28
+#define TEGRA210_AMX_RX4_CIF_CTRL		0x2c
+#define TEGRA210_AMX_TX_STATUS			0x4c
+#define TEGRA210_AMX_TX_INT_STATUS		0x50
+#define TEGRA210_AMX_TX_INT_MASK		0x54
+#define TEGRA210_AMX_TX_INT_SET			0x58
+#define TEGRA210_AMX_TX_INT_CLEAR		0x5c
+#define TEGRA210_AMX_TX_CIF_CTRL		0x60
+#define TEGRA210_AMX_ENABLE			0x80
+#define TEGRA210_AMX_SOFT_RESET			0x84
+#define TEGRA210_AMX_CG				0x88
+#define TEGRA210_AMX_STATUS			0x8c
+#define TEGRA210_AMX_INT_STATUS			0x90
+#define TEGRA210_AMX_CTRL			0xa4
+#define TEGRA210_AMX_OUT_BYTE_EN0		0xa8
+#define TEGRA210_AMX_OUT_BYTE_EN1		0xac
+#define TEGRA210_AMX_CYA			0xb0
+#define TEGRA210_AMX_CFG_RAM_CTRL		0xb8
+#define TEGRA210_AMX_CFG_RAM_DATA		0xbc
+
+#define TEGRA194_AMX_RX1_FRAME_PERIOD		0xc0
+#define TEGRA194_AMX_RX4_FRAME_PERIOD		0xcc
+#define TEGRA194_AMX_RX4_LAST_FRAME_PERIOD	0xdc
+
+/* Fields in TEGRA210_AMX_ENABLE */
+#define TEGRA210_AMX_ENABLE_SHIFT			0
+
+/* Fields in TEGRA210_AMX_CTRL */
+#define TEGRA210_AMX_CTRL_MSTR_RX_NUM_SHIFT		14
+#define TEGRA210_AMX_CTRL_MSTR_RX_NUM_MASK		(3 << TEGRA210_AMX_CTRL_MSTR_RX_NUM_SHIFT)
+
+#define TEGRA210_AMX_CTRL_RX_DEP_SHIFT			12
+#define TEGRA210_AMX_CTRL_RX_DEP_MASK			(3 << TEGRA210_AMX_CTRL_RX_DEP_SHIFT)
+
+/* Fields in TEGRA210_AMX_CFG_RAM_CTRL */
+#define TEGRA210_AMX_CFG_RAM_CTRL_RW_SHIFT		14
+#define TEGRA210_AMX_CFG_RAM_CTRL_RW_WRITE		(1 << TEGRA210_AMX_CFG_RAM_CTRL_RW_SHIFT)
+
+#define TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN_SHIFT	13
+#define TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN		(1 << TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN_SHIFT)
+
+#define TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN_SHIFT	12
+#define TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN		(1 << TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN_SHIFT)
+
+#define TEGRA210_AMX_CFG_CTRL_RAM_ADDR_SHIFT		0
+
+/* Fields in TEGRA210_AMX_SOFT_RESET */
+#define TEGRA210_AMX_SOFT_RESET_SOFT_EN			1
+#define TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK		TEGRA210_AMX_SOFT_RESET_SOFT_EN
+
+#define TEGRA210_AMX_AUDIOCIF_CH_STRIDE		4
+#define TEGRA210_AMX_RAM_DEPTH			16
+#define TEGRA210_AMX_MAP_STREAM_NUM_SHIFT	6
+#define TEGRA210_AMX_MAP_WORD_NUM_SHIFT		2
+#define TEGRA210_AMX_MAP_BYTE_NUM_SHIFT		0
+
+enum {
+	TEGRA210_AMX_WAIT_ON_ALL,
+	TEGRA210_AMX_WAIT_ON_ANY,
+};
+
+struct tegra210_amx_soc_data {
+	const struct regmap_config *regmap_conf;
+	bool auto_disable;
+};
+
+struct tegra210_amx {
+	const struct tegra210_amx_soc_data *soc_data;
+	unsigned int map[TEGRA210_AMX_RAM_DEPTH];
+	struct regmap *regmap;
+	unsigned int byte_mask[2];
+};
+
+#endif
-- 
2.7.4


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

* [PATCH 09/13] ASoC: tegra: Add Tegra210 based ADX driver
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (7 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 08/13] ASoC: tegra: Add Tegra210 based AMX driver Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-08-27  9:33 ` [PATCH 10/13] ASoC: tegra: Add Tegra210 based Mixer driver Sameer Pujar
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

The Audio Demultiplexer (ADX) block takes an input stream with up to
16 channels and demultiplexes it into four output streams of up to 16
channels each. A byte RAM helps to form output frames by any combination
of bytes from the input frame. Its design is identical to that of byte
RAM in the AMX except that the data flow direction is reversed.

This patch registers ADX driver with ASoC framework. The component driver
exposes DAPM widgets, routes and kcontrols for the device. The DAI driver
exposes ADX interfaces, which can be used to connect different components
in the ASoC layer. Makefile and Kconfig support is added to allow build
the driver. It can be enabled in the DT via "nvidia,tegra210-adx"
compatible binding.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 sound/soc/tegra/Kconfig        |  11 +
 sound/soc/tegra/Makefile       |   2 +
 sound/soc/tegra/tegra210_adx.c | 527 +++++++++++++++++++++++++++++++++++++++++
 sound/soc/tegra/tegra210_adx.h |  72 ++++++
 4 files changed, 612 insertions(+)
 create mode 100644 sound/soc/tegra/tegra210_adx.c
 create mode 100644 sound/soc/tegra/tegra210_adx.h

diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 54d8342..fd4a8d6 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -135,6 +135,17 @@ config SND_SOC_TEGRA210_AMX
 	  output frame by any combination of bytes from the input frames.
 	  Say Y or M if you want to add support for Tegra210 AMX module.
 
+config SND_SOC_TEGRA210_ADX
+	tristate "Tegra210 ADX module"
+	help
+	  Config to enable the Audio Demultiplexer (ADX) which takes an
+	  input stream (up to 16 channels) and demultiplexes it into four
+	  output streams (each of up to 16 channels). A byte RAM helps to
+	  form output frames by any combination of bytes from the input
+	  frame. Its design is identical to that of byte RAM in the AMX
+	  except that the data flow direction is reversed.
+	  Say Y or M if you want to add support for Tegra210 ADX module.
+
 config SND_SOC_TEGRA_AUDIO_GRAPH_CARD
 	tristate "Audio Graph Card based Tegra driver"
 	depends on SND_AUDIO_GRAPH_CARD
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 549162b..8eb17ad 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -16,6 +16,7 @@ snd-soc-tegra210-admaif-objs := tegra210_admaif.o
 snd-soc-tegra210-mvc-objs := tegra210_mvc.o
 snd-soc-tegra210-sfc-objs := tegra210_sfc.o
 snd-soc-tegra210-amx-objs := tegra210_amx.o
+snd-soc-tegra210-adx-objs := tegra210_adx.o
 
 obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
 obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o
@@ -32,6 +33,7 @@ obj-$(CONFIG_SND_SOC_TEGRA210_ADMAIF) += snd-soc-tegra210-admaif.o
 obj-$(CONFIG_SND_SOC_TEGRA210_MVC) += snd-soc-tegra210-mvc.o
 obj-$(CONFIG_SND_SOC_TEGRA210_SFC) += snd-soc-tegra210-sfc.o
 obj-$(CONFIG_SND_SOC_TEGRA210_AMX) += snd-soc-tegra210-amx.o
+obj-$(CONFIG_SND_SOC_TEGRA210_ADX) += snd-soc-tegra210-adx.o
 
 # Tegra machine Support
 snd-soc-tegra-wm8903-objs := tegra_wm8903.o
diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c
new file mode 100644
index 0000000..5effafc
--- /dev/null
+++ b/sound/soc/tegra/tegra210_adx.c
@@ -0,0 +1,527 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// tegra210_adx.c - Tegra210 ADX driver
+//
+// Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra210_adx.h"
+#include "tegra_cif.h"
+
+static const struct reg_default tegra210_adx_reg_defaults[] = {
+	{ TEGRA210_ADX_RX_INT_MASK, 0x00000001},
+	{ TEGRA210_ADX_RX_CIF_CTRL, 0x00007000},
+	{ TEGRA210_ADX_TX_INT_MASK, 0x0000000f },
+	{ TEGRA210_ADX_TX1_CIF_CTRL, 0x00007000},
+	{ TEGRA210_ADX_TX2_CIF_CTRL, 0x00007000},
+	{ TEGRA210_ADX_TX3_CIF_CTRL, 0x00007000},
+	{ TEGRA210_ADX_TX4_CIF_CTRL, 0x00007000},
+	{ TEGRA210_ADX_CG, 0x1},
+	{ TEGRA210_ADX_CFG_RAM_CTRL, 0x00004000},
+};
+
+static void tegra210_adx_write_map_ram(struct tegra210_adx *adx)
+{
+	int i;
+
+	regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL,
+		     TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
+		     TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN |
+		     TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE);
+
+	for (i = 0; i < TEGRA210_ADX_RAM_DEPTH; i++)
+		regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA,
+			     adx->map[i]);
+
+	regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN0, adx->byte_mask[0]);
+	regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN1, adx->byte_mask[1]);
+}
+
+static int tegra210_adx_startup(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
+	unsigned int val;
+	int err;
+
+	/* Ensure if ADX status is disabled */
+	err = regmap_read_poll_timeout_atomic(adx->regmap, TEGRA210_ADX_STATUS,
+					      val, !(val & 0x1), 10, 10000);
+	if (err < 0) {
+		dev_err(dai->dev, "failed to stop ADX, err = %d\n", err);
+		return err;
+	}
+
+	/* SW reset */
+	regmap_update_bits(adx->regmap, TEGRA210_ADX_SOFT_RESET,
+			   TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK,
+			   TEGRA210_ADX_SOFT_RESET_SOFT_EN);
+
+	err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_SOFT_RESET,
+				       val, !(val & 0x1), 10, 10000);
+	if (err < 0) {
+		dev_err(dai->dev, "failed to reset ADX, err = %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused tegra210_adx_runtime_suspend(struct device *dev)
+{
+	struct tegra210_adx *adx = dev_get_drvdata(dev);
+
+	regcache_cache_only(adx->regmap, true);
+	regcache_mark_dirty(adx->regmap);
+
+	return 0;
+}
+
+static int __maybe_unused tegra210_adx_runtime_resume(struct device *dev)
+{
+	struct tegra210_adx *adx = dev_get_drvdata(dev);
+
+	regcache_cache_only(adx->regmap, false);
+	regcache_sync(adx->regmap);
+
+	tegra210_adx_write_map_ram(adx);
+
+	return 0;
+}
+
+static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai,
+				      unsigned int channels,
+				      unsigned int format,
+				      unsigned int reg)
+{
+	struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
+	struct tegra_cif_conf cif_conf;
+	int audio_bits;
+
+	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
+
+	if (channels < 1 || channels > 16)
+		return -EINVAL;
+
+	switch (format) {
+	case SNDRV_PCM_FORMAT_S8:
+		audio_bits = TEGRA_ACIF_BITS_8;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		audio_bits = TEGRA_ACIF_BITS_16;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		audio_bits = TEGRA_ACIF_BITS_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cif_conf.audio_ch = channels;
+	cif_conf.client_ch = channels;
+	cif_conf.audio_bits = audio_bits;
+	cif_conf.client_bits = audio_bits;
+
+	tegra_set_cif(adx->regmap, reg, &cif_conf);
+
+	return 0;
+}
+
+static int tegra210_adx_out_hw_params(struct snd_pcm_substream *substream,
+				      struct snd_pcm_hw_params *params,
+				      struct snd_soc_dai *dai)
+{
+	return tegra210_adx_set_audio_cif(dai, params_channels(params),
+			params_format(params),
+			TEGRA210_ADX_TX1_CIF_CTRL + ((dai->id - 1) * TEGRA210_ADX_AUDIOCIF_CH_STRIDE));
+}
+
+static int tegra210_adx_in_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params,
+				     struct snd_soc_dai *dai)
+{
+	return tegra210_adx_set_audio_cif(dai, params_channels(params),
+					  params_format(params),
+					  TEGRA210_ADX_RX_CIF_CTRL);
+}
+
+static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
+	struct soc_mixer_control *mc;
+	unsigned char *bytes_map = (unsigned char *)&adx->map;
+	int enabled;
+
+	mc = (struct soc_mixer_control *)kcontrol->private_value;
+	enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32));
+
+	if (enabled)
+		ucontrol->value.integer.value[0] = bytes_map[mc->reg];
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
+	struct soc_mixer_control *mc;
+	unsigned char *bytes_map = (unsigned char *)&adx->map;
+	int value = ucontrol->value.integer.value[0];
+
+	mc = (struct soc_mixer_control *)kcontrol->private_value;
+
+	if (value >= 0 && value <= 255) {
+		/* update byte map and enable slot */
+		bytes_map[mc->reg] = value;
+		adx->byte_mask[mc->reg / 32] |= (1 << (mc->reg % 32));
+	} else {
+		/* reset byte map and disable slot */
+		bytes_map[mc->reg] = 0;
+		adx->byte_mask[mc->reg / 32] &= ~(1 << (mc->reg % 32));
+	}
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops tegra210_adx_in_dai_ops = {
+	.hw_params	= tegra210_adx_in_hw_params,
+	.startup	= tegra210_adx_startup,
+};
+
+static struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
+	.hw_params	= tegra210_adx_out_hw_params,
+};
+
+#define IN_DAI							\
+	{							\
+		.name = "ADX-RX-CIF",				\
+		.playback = {					\
+			.stream_name = "RX-CIF-Playback",	\
+			.channels_min = 1,			\
+			.channels_max = 16,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				   SNDRV_PCM_FMTBIT_S16_LE |	\
+				   SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.capture = {					\
+			.stream_name = "RX-CIF-Capture",	\
+			.channels_min = 1,			\
+			.channels_max = 16,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				   SNDRV_PCM_FMTBIT_S16_LE |	\
+				   SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.ops = &tegra210_adx_in_dai_ops,		\
+	}
+
+#define OUT_DAI(id)						\
+	{							\
+		.name = "ADX-TX" #id "-CIF",			\
+		.playback = {					\
+			.stream_name = "TX" #id "-CIF-Playback",\
+			.channels_min = 1,			\
+			.channels_max = 16,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				   SNDRV_PCM_FMTBIT_S16_LE |	\
+				   SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.capture = {					\
+			.stream_name = "TX" #id "-CIF-Capture",	\
+			.channels_min = 1,			\
+			.channels_max = 16,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				   SNDRV_PCM_FMTBIT_S16_LE |	\
+				   SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.ops = &tegra210_adx_out_dai_ops,		\
+	}
+
+static struct snd_soc_dai_driver tegra210_adx_dais[] = {
+	IN_DAI,
+	OUT_DAI(1),
+	OUT_DAI(2),
+	OUT_DAI(3),
+	OUT_DAI(4),
+};
+
+static const struct snd_soc_dapm_widget tegra210_adx_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA210_ADX_ENABLE,
+			    TEGRA210_ADX_ENABLE_SHIFT, 0),
+	SND_SOC_DAPM_AIF_OUT("TX1", NULL, 0, TEGRA210_ADX_CTRL, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("TX2", NULL, 0, TEGRA210_ADX_CTRL, 1, 0),
+	SND_SOC_DAPM_AIF_OUT("TX3", NULL, 0, TEGRA210_ADX_CTRL, 2, 0),
+	SND_SOC_DAPM_AIF_OUT("TX4", NULL, 0, TEGRA210_ADX_CTRL, 3, 0),
+};
+
+#define STREAM_ROUTES(id, sname)					  \
+	{ "XBAR-" sname,		NULL,	"XBAR-TX" },		  \
+	{ "RX-CIF-" sname,		NULL,	"XBAR-" sname },	  \
+	{ "RX",				NULL,	"RX-CIF-" sname },	  \
+	{ "TX" #id,			NULL,	"RX" },			  \
+	{ "TX" #id "-CIF-" sname,	NULL,	"TX" #id },		  \
+	{ "TX" #id " XBAR-" sname,	NULL,	"TX" #id "-CIF-" sname }, \
+	{ "TX" #id " XBAR-RX",		NULL,	"TX" #id " XBAR-" sname }
+
+#define ADX_ROUTES(id)			\
+	STREAM_ROUTES(id, "Playback"),	\
+	STREAM_ROUTES(id, "Capture")
+
+#define STREAM_ROUTES(id, sname)					  \
+	{ "XBAR-" sname,		NULL,	"XBAR-TX" },		  \
+	{ "RX-CIF-" sname,		NULL,	"XBAR-" sname },	  \
+	{ "RX",				NULL,	"RX-CIF-" sname },	  \
+	{ "TX" #id,			NULL,	"RX" },			  \
+	{ "TX" #id "-CIF-" sname,	NULL,	"TX" #id },		  \
+	{ "TX" #id " XBAR-" sname,	NULL,	"TX" #id "-CIF-" sname }, \
+	{ "TX" #id " XBAR-RX",		NULL,	"TX" #id " XBAR-" sname }
+
+#define ADX_ROUTES(id)			\
+	STREAM_ROUTES(id, "Playback"),	\
+	STREAM_ROUTES(id, "Capture")
+
+static const struct snd_soc_dapm_route tegra210_adx_routes[] = {
+	ADX_ROUTES(1),
+	ADX_ROUTES(2),
+	ADX_ROUTES(3),
+	ADX_ROUTES(4),
+};
+
+#define TEGRA210_ADX_BYTE_MAP_CTRL(reg)			 \
+	SOC_SINGLE_EXT("Byte Map " #reg, reg, 0, 256, 0, \
+		       tegra210_adx_get_byte_map,	 \
+		       tegra210_adx_put_byte_map)
+
+static struct snd_kcontrol_new tegra210_adx_controls[] = {
+	TEGRA210_ADX_BYTE_MAP_CTRL(0),
+	TEGRA210_ADX_BYTE_MAP_CTRL(1),
+	TEGRA210_ADX_BYTE_MAP_CTRL(2),
+	TEGRA210_ADX_BYTE_MAP_CTRL(3),
+	TEGRA210_ADX_BYTE_MAP_CTRL(4),
+	TEGRA210_ADX_BYTE_MAP_CTRL(5),
+	TEGRA210_ADX_BYTE_MAP_CTRL(6),
+	TEGRA210_ADX_BYTE_MAP_CTRL(7),
+	TEGRA210_ADX_BYTE_MAP_CTRL(8),
+	TEGRA210_ADX_BYTE_MAP_CTRL(9),
+	TEGRA210_ADX_BYTE_MAP_CTRL(10),
+	TEGRA210_ADX_BYTE_MAP_CTRL(11),
+	TEGRA210_ADX_BYTE_MAP_CTRL(12),
+	TEGRA210_ADX_BYTE_MAP_CTRL(13),
+	TEGRA210_ADX_BYTE_MAP_CTRL(14),
+	TEGRA210_ADX_BYTE_MAP_CTRL(15),
+	TEGRA210_ADX_BYTE_MAP_CTRL(16),
+	TEGRA210_ADX_BYTE_MAP_CTRL(17),
+	TEGRA210_ADX_BYTE_MAP_CTRL(18),
+	TEGRA210_ADX_BYTE_MAP_CTRL(19),
+	TEGRA210_ADX_BYTE_MAP_CTRL(20),
+	TEGRA210_ADX_BYTE_MAP_CTRL(21),
+	TEGRA210_ADX_BYTE_MAP_CTRL(22),
+	TEGRA210_ADX_BYTE_MAP_CTRL(23),
+	TEGRA210_ADX_BYTE_MAP_CTRL(24),
+	TEGRA210_ADX_BYTE_MAP_CTRL(25),
+	TEGRA210_ADX_BYTE_MAP_CTRL(26),
+	TEGRA210_ADX_BYTE_MAP_CTRL(27),
+	TEGRA210_ADX_BYTE_MAP_CTRL(28),
+	TEGRA210_ADX_BYTE_MAP_CTRL(29),
+	TEGRA210_ADX_BYTE_MAP_CTRL(30),
+	TEGRA210_ADX_BYTE_MAP_CTRL(31),
+	TEGRA210_ADX_BYTE_MAP_CTRL(32),
+	TEGRA210_ADX_BYTE_MAP_CTRL(33),
+	TEGRA210_ADX_BYTE_MAP_CTRL(34),
+	TEGRA210_ADX_BYTE_MAP_CTRL(35),
+	TEGRA210_ADX_BYTE_MAP_CTRL(36),
+	TEGRA210_ADX_BYTE_MAP_CTRL(37),
+	TEGRA210_ADX_BYTE_MAP_CTRL(38),
+	TEGRA210_ADX_BYTE_MAP_CTRL(39),
+	TEGRA210_ADX_BYTE_MAP_CTRL(40),
+	TEGRA210_ADX_BYTE_MAP_CTRL(41),
+	TEGRA210_ADX_BYTE_MAP_CTRL(42),
+	TEGRA210_ADX_BYTE_MAP_CTRL(43),
+	TEGRA210_ADX_BYTE_MAP_CTRL(44),
+	TEGRA210_ADX_BYTE_MAP_CTRL(45),
+	TEGRA210_ADX_BYTE_MAP_CTRL(46),
+	TEGRA210_ADX_BYTE_MAP_CTRL(47),
+	TEGRA210_ADX_BYTE_MAP_CTRL(48),
+	TEGRA210_ADX_BYTE_MAP_CTRL(49),
+	TEGRA210_ADX_BYTE_MAP_CTRL(50),
+	TEGRA210_ADX_BYTE_MAP_CTRL(51),
+	TEGRA210_ADX_BYTE_MAP_CTRL(52),
+	TEGRA210_ADX_BYTE_MAP_CTRL(53),
+	TEGRA210_ADX_BYTE_MAP_CTRL(54),
+	TEGRA210_ADX_BYTE_MAP_CTRL(55),
+	TEGRA210_ADX_BYTE_MAP_CTRL(56),
+	TEGRA210_ADX_BYTE_MAP_CTRL(57),
+	TEGRA210_ADX_BYTE_MAP_CTRL(58),
+	TEGRA210_ADX_BYTE_MAP_CTRL(59),
+	TEGRA210_ADX_BYTE_MAP_CTRL(60),
+	TEGRA210_ADX_BYTE_MAP_CTRL(61),
+	TEGRA210_ADX_BYTE_MAP_CTRL(62),
+	TEGRA210_ADX_BYTE_MAP_CTRL(63),
+};
+
+static const struct snd_soc_component_driver tegra210_adx_cmpnt = {
+	.dapm_widgets		= tegra210_adx_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(tegra210_adx_widgets),
+	.dapm_routes		= tegra210_adx_routes,
+	.num_dapm_routes	= ARRAY_SIZE(tegra210_adx_routes),
+	.controls		= tegra210_adx_controls,
+	.num_controls		= ARRAY_SIZE(tegra210_adx_controls),
+};
+
+static bool tegra210_adx_wr_reg(struct device *dev,
+				unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_ADX_TX_INT_MASK ... TEGRA210_ADX_TX4_CIF_CTRL:
+	case TEGRA210_ADX_RX_INT_MASK ... TEGRA210_ADX_RX_CIF_CTRL:
+	case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_CG:
+	case TEGRA210_ADX_CTRL ... TEGRA210_ADX_IN_BYTE_EN1:
+	case TEGRA210_ADX_CFG_RAM_CTRL ... TEGRA210_ADX_CFG_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra210_adx_rd_reg(struct device *dev,
+				unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_ADX_RX_STATUS ... TEGRA210_ADX_CFG_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra210_adx_volatile_reg(struct device *dev,
+				unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_ADX_RX_STATUS:
+	case TEGRA210_ADX_RX_INT_STATUS:
+	case TEGRA210_ADX_RX_INT_SET:
+	case TEGRA210_ADX_TX_STATUS:
+	case TEGRA210_ADX_TX_INT_STATUS:
+	case TEGRA210_ADX_TX_INT_SET:
+	case TEGRA210_ADX_SOFT_RESET:
+	case TEGRA210_ADX_STATUS:
+	case TEGRA210_ADX_INT_STATUS:
+	case TEGRA210_ADX_CFG_RAM_CTRL:
+	case TEGRA210_ADX_CFG_RAM_DATA:
+		return true;
+	default:
+		break;
+	}
+
+	return false;
+}
+
+static const struct regmap_config tegra210_adx_regmap_config = {
+	.reg_bits		= 32,
+	.reg_stride		= 4,
+	.val_bits		= 32,
+	.max_register		= TEGRA210_ADX_CFG_RAM_DATA,
+	.writeable_reg		= tegra210_adx_wr_reg,
+	.readable_reg		= tegra210_adx_rd_reg,
+	.volatile_reg		= tegra210_adx_volatile_reg,
+	.reg_defaults		= tegra210_adx_reg_defaults,
+	.num_reg_defaults	= ARRAY_SIZE(tegra210_adx_reg_defaults),
+	.cache_type		= REGCACHE_FLAT,
+};
+
+static const struct of_device_id tegra210_adx_of_match[] = {
+	{ .compatible = "nvidia,tegra210-adx" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tegra210_adx_of_match);
+
+static int tegra210_adx_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra210_adx *adx;
+	void __iomem *regs;
+	int err;
+
+	adx = devm_kzalloc(dev, sizeof(*adx), GFP_KERNEL);
+	if (!adx)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, adx);
+
+	regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	adx->regmap = devm_regmap_init_mmio(dev, regs,
+					    &tegra210_adx_regmap_config);
+	if (IS_ERR(adx->regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(adx->regmap);
+	}
+
+	regcache_cache_only(adx->regmap, true);
+
+	err = devm_snd_soc_register_component(dev, &tegra210_adx_cmpnt,
+					      tegra210_adx_dais,
+					      ARRAY_SIZE(tegra210_adx_dais));
+	if (err) {
+		dev_err(dev, "can't register ADX component, err: %d\n", err);
+		return err;
+	}
+
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+
+static int tegra210_adx_platform_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops tegra210_adx_pm_ops = {
+	SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend,
+			   tegra210_adx_runtime_resume, NULL)
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				     pm_runtime_force_resume)
+};
+
+static struct platform_driver tegra210_adx_driver = {
+	.driver = {
+		.name = "tegra210-adx",
+		.of_match_table = tegra210_adx_of_match,
+		.pm = &tegra210_adx_pm_ops,
+	},
+	.probe = tegra210_adx_platform_probe,
+	.remove = tegra210_adx_platform_remove,
+};
+module_platform_driver(tegra210_adx_driver);
+
+MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>");
+MODULE_DESCRIPTION("Tegra210 ADX ASoC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/tegra/tegra210_adx.h b/sound/soc/tegra/tegra210_adx.h
new file mode 100644
index 0000000..d7dcb64
--- /dev/null
+++ b/sound/soc/tegra/tegra210_adx.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * tegra210_adx.h - Definitions for Tegra210 ADX driver
+ *
+ * Copyright (c) 2021, NVIDIA CORPORATION.  All rights reserved.
+ *
+ */
+
+#ifndef __TEGRA210_ADX_H__
+#define __TEGRA210_ADX_H__
+
+/* Register offsets from TEGRA210_ADX*_BASE */
+#define TEGRA210_ADX_RX_STATUS		0x0c
+#define TEGRA210_ADX_RX_INT_STATUS	0x10
+#define TEGRA210_ADX_RX_INT_MASK	0x14
+#define TEGRA210_ADX_RX_INT_SET		0x18
+#define TEGRA210_ADX_RX_INT_CLEAR	0x1c
+#define TEGRA210_ADX_RX_CIF_CTRL	0x20
+#define TEGRA210_ADX_TX_STATUS		0x4c
+#define TEGRA210_ADX_TX_INT_STATUS	0x50
+#define TEGRA210_ADX_TX_INT_MASK	0x54
+#define TEGRA210_ADX_TX_INT_SET		0x58
+#define TEGRA210_ADX_TX_INT_CLEAR	0x5c
+#define TEGRA210_ADX_TX1_CIF_CTRL	0x60
+#define TEGRA210_ADX_TX2_CIF_CTRL	0x64
+#define TEGRA210_ADX_TX3_CIF_CTRL	0x68
+#define TEGRA210_ADX_TX4_CIF_CTRL	0x6c
+#define TEGRA210_ADX_ENABLE		0x80
+#define TEGRA210_ADX_SOFT_RESET		0x84
+#define TEGRA210_ADX_CG			0x88
+#define TEGRA210_ADX_STATUS		0x8c
+#define TEGRA210_ADX_INT_STATUS		0x90
+#define TEGRA210_ADX_CTRL		0xa4
+#define TEGRA210_ADX_IN_BYTE_EN0	0xa8
+#define TEGRA210_ADX_IN_BYTE_EN1	0xac
+#define TEGRA210_ADX_CFG_RAM_CTRL	0xb8
+#define TEGRA210_ADX_CFG_RAM_DATA	0xbc
+
+/* Fields in TEGRA210_ADX_ENABLE */
+#define TEGRA210_ADX_ENABLE_SHIFT			0
+
+/* Fields in TEGRA210_ADX_CFG_RAM_CTRL */
+#define TEGRA210_ADX_CFG_RAM_CTRL_RAM_ADDR_SHIFT	0
+
+#define TEGRA210_ADX_CFG_RAM_CTRL_RW_SHIFT		14
+#define TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE		(1 << TEGRA210_ADX_CFG_RAM_CTRL_RW_SHIFT)
+
+#define TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN_SHIFT	13
+#define TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN		(1 << TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN_SHIFT)
+
+#define TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN_SHIFT	12
+#define TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN		(1 << TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN_SHIFT)
+
+/* Fields in TEGRA210_ADX_SOFT_RESET */
+#define TEGRA210_ADX_SOFT_RESET_SOFT_RESET_SHIFT	0
+#define TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK		(1 << TEGRA210_ADX_SOFT_RESET_SOFT_RESET_SHIFT)
+#define TEGRA210_ADX_SOFT_RESET_SOFT_EN			(1 << TEGRA210_ADX_SOFT_RESET_SOFT_RESET_SHIFT)
+#define TEGRA210_ADX_SOFT_RESET_SOFT_DEFAULT		(0 << TEGRA210_ADX_SOFT_RESET_SOFT_RESET_SHIFT)
+
+#define TEGRA210_ADX_AUDIOCIF_CH_STRIDE		4
+#define TEGRA210_ADX_RAM_DEPTH			16
+#define TEGRA210_ADX_MAP_STREAM_NUMBER_SHIFT	6
+#define TEGRA210_ADX_MAP_WORD_NUMBER_SHIFT	2
+#define TEGRA210_ADX_MAP_BYTE_NUMBER_SHIFT	0
+
+struct tegra210_adx {
+	struct regmap *regmap;
+	unsigned int map[TEGRA210_ADX_RAM_DEPTH];
+	unsigned int byte_mask[2];
+};
+
+#endif
-- 
2.7.4


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

* [PATCH 10/13] ASoC: tegra: Add Tegra210 based Mixer driver
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (8 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 09/13] ASoC: tegra: Add Tegra210 based ADX driver Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-08-27  9:33 ` [PATCH 11/13] arm64: defconfig: Enable few Tegra210 based AHUB drivers Sameer Pujar
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

The Mixer supports mixing of up to ten 7.1 audio input streams and
generate five outputs (each of which can be any combination of the
ten input streams)

This patch registers Mixer driver with ASoC framework. The component
driver exposes DAPM widgets, routes and kcontrols for the device.
The DAI driver exposes Mixer interfaces, which can be used to connect
different components in the ASoC layer. Makefile and Kconfig support
is added to allow build the driver. It can be enabled in the DT via
"nvidia,tegra210-amixer" compatible binding.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 sound/soc/tegra/Kconfig          |  10 +
 sound/soc/tegra/Makefile         |   2 +
 sound/soc/tegra/tegra210_mixer.c | 667 +++++++++++++++++++++++++++++++++++++++
 sound/soc/tegra/tegra210_mixer.h | 100 ++++++
 4 files changed, 779 insertions(+)
 create mode 100644 sound/soc/tegra/tegra210_mixer.c
 create mode 100644 sound/soc/tegra/tegra210_mixer.h

diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index fd4a8d6..cd45487 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -146,6 +146,16 @@ config SND_SOC_TEGRA210_ADX
 	  except that the data flow direction is reversed.
 	  Say Y or M if you want to add support for Tegra210 ADX module.
 
+config SND_SOC_TEGRA210_MIXER
+	tristate "Tegra210 Mixer module"
+	help
+	  Config to enable the Mixer module which can help to mix multiple
+	  audio streams. It supports mixing of upto 10 input streams,
+	  where each stream can contain maximum of 8 channels. It supports
+	  5 output each of which can be a mix of any combination of 10
+	  input streams.
+	  Say Y or M if you want to add support for Tegra210 Mixer module.
+
 config SND_SOC_TEGRA_AUDIO_GRAPH_CARD
 	tristate "Audio Graph Card based Tegra driver"
 	depends on SND_AUDIO_GRAPH_CARD
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 8eb17ad..f19d566 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -17,6 +17,7 @@ snd-soc-tegra210-mvc-objs := tegra210_mvc.o
 snd-soc-tegra210-sfc-objs := tegra210_sfc.o
 snd-soc-tegra210-amx-objs := tegra210_amx.o
 snd-soc-tegra210-adx-objs := tegra210_adx.o
+snd-soc-tegra210-mixer-objs := tegra210_mixer.o
 
 obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
 obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_SND_SOC_TEGRA210_MVC) += snd-soc-tegra210-mvc.o
 obj-$(CONFIG_SND_SOC_TEGRA210_SFC) += snd-soc-tegra210-sfc.o
 obj-$(CONFIG_SND_SOC_TEGRA210_AMX) += snd-soc-tegra210-amx.o
 obj-$(CONFIG_SND_SOC_TEGRA210_ADX) += snd-soc-tegra210-adx.o
+obj-$(CONFIG_SND_SOC_TEGRA210_MIXER) += snd-soc-tegra210-mixer.o
 
 # Tegra machine Support
 snd-soc-tegra-wm8903-objs := tegra_wm8903.o
diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c
new file mode 100644
index 0000000..54a0d38
--- /dev/null
+++ b/sound/soc/tegra/tegra210_mixer.c
@@ -0,0 +1,667 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// tegra210_mixer.c - Tegra210 MIXER driver
+//
+// Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra210_mixer.h"
+#include "tegra_cif.h"
+
+#define MIXER_REG(reg, id)	((reg) + ((id) * TEGRA210_MIXER_REG_STRIDE))
+#define MIXER_REG_BASE(reg)	((reg) % TEGRA210_MIXER_REG_STRIDE)
+
+#define MIXER_GAIN_CFG_RAM_ADDR(id)					\
+	(TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_0 +				\
+	 ((id) * TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_STRIDE))
+
+#define MIXER_RX_REG_DEFAULTS(id)					\
+	{ MIXER_REG(TEGRA210_MIXER_RX1_CIF_CTRL, id), 0x00007700},	\
+	{ MIXER_REG(TEGRA210_MIXER_RX1_CTRL, id), 0x00010823},	\
+	{ MIXER_REG(TEGRA210_MIXER_RX1_PEAK_CTRL, id), 0x000012c0}
+
+#define MIXER_TX_REG_DEFAULTS(id)					\
+	{ MIXER_REG(TEGRA210_MIXER_TX1_INT_MASK, (id)), 0x00000001},	\
+	{ MIXER_REG(TEGRA210_MIXER_TX1_CIF_CTRL, (id)), 0x00007700}
+
+#define REG_DURATION_PARAM(reg, i) ((reg) + NUM_GAIN_POLY_COEFFS + 1 + (i))
+
+static const struct reg_default tegra210_mixer_reg_defaults[] = {
+	/* Inputs */
+	MIXER_RX_REG_DEFAULTS(0),
+	MIXER_RX_REG_DEFAULTS(1),
+	MIXER_RX_REG_DEFAULTS(2),
+	MIXER_RX_REG_DEFAULTS(3),
+	MIXER_RX_REG_DEFAULTS(4),
+	MIXER_RX_REG_DEFAULTS(5),
+	MIXER_RX_REG_DEFAULTS(6),
+	MIXER_RX_REG_DEFAULTS(7),
+	MIXER_RX_REG_DEFAULTS(8),
+	MIXER_RX_REG_DEFAULTS(9),
+	/* Outputs */
+	MIXER_TX_REG_DEFAULTS(0),
+	MIXER_TX_REG_DEFAULTS(1),
+	MIXER_TX_REG_DEFAULTS(2),
+	MIXER_TX_REG_DEFAULTS(3),
+	MIXER_TX_REG_DEFAULTS(4),
+
+	{ TEGRA210_MIXER_CG, 0x00000001},
+	{ TEGRA210_MIXER_GAIN_CFG_RAM_CTRL, 0x00004000},
+	{ TEGRA210_MIXER_PEAKM_RAM_CTRL, 0x00004000},
+	{ TEGRA210_MIXER_ENABLE, 0x1 },
+};
+
+/* Default gain parameters */
+static const struct tegra210_mixer_gain_params gain_params = {
+	/* Polynomial coefficients */
+	{ 0, 0, 0, 0, 0, 0, 0, 0x1000000, 0 },
+	/* Gain value */
+	0x10000,
+	/* Duration Parameters */
+	{ 0, 0, 0x400, 0x8000000 },
+};
+
+static int __maybe_unused tegra210_mixer_runtime_suspend(struct device *dev)
+{
+	struct tegra210_mixer *mixer = dev_get_drvdata(dev);
+
+	regcache_cache_only(mixer->regmap, true);
+	regcache_mark_dirty(mixer->regmap);
+
+	return 0;
+}
+
+static int __maybe_unused tegra210_mixer_runtime_resume(struct device *dev)
+{
+	struct tegra210_mixer *mixer = dev_get_drvdata(dev);
+
+	regcache_cache_only(mixer->regmap, false);
+	regcache_sync(mixer->regmap);
+
+	return 0;
+}
+
+static int tegra210_mixer_write_ram(struct tegra210_mixer *mixer,
+				    unsigned int addr,
+				    unsigned int coef)
+{
+	unsigned int reg, val;
+	int err;
+
+	/* Check if busy */
+	err = regmap_read_poll_timeout(mixer->regmap,
+				       TEGRA210_MIXER_GAIN_CFG_RAM_CTRL,
+				       val, !(val & 0x80000000), 10, 10000);
+	if (err < 0)
+		return err;
+
+	reg = (addr << TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_SHIFT) &
+	      TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_MASK;
+	reg |= TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_INIT_EN;
+	reg |= TEGRA210_MIXER_GAIN_CFG_RAM_RW_WRITE;
+	reg |= TEGRA210_MIXER_GAIN_CFG_RAM_SEQ_ACCESS_EN;
+
+	regmap_write(mixer->regmap,
+		     TEGRA210_MIXER_GAIN_CFG_RAM_CTRL,
+		     reg);
+	regmap_write(mixer->regmap,
+		     TEGRA210_MIXER_GAIN_CFG_RAM_DATA,
+		     coef);
+
+	return 0;
+}
+
+static int tegra210_mixer_configure_gain(struct snd_soc_component *cmpnt,
+					 unsigned int id, bool instant_gain)
+{
+	struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
+	unsigned int reg = MIXER_GAIN_CFG_RAM_ADDR(id);
+	int err, i;
+
+	pm_runtime_get_sync(cmpnt->dev);
+
+	/* Write default gain poly coefficients */
+	for (i = 0; i < NUM_GAIN_POLY_COEFFS; i++) {
+		err = tegra210_mixer_write_ram(mixer, reg + i,
+					       gain_params.poly_coeff[i]);
+
+		if (err < 0)
+			goto rpm_put;
+	}
+
+	/* Write stored gain value */
+	err = tegra210_mixer_write_ram(mixer, reg + NUM_GAIN_POLY_COEFFS,
+				       mixer->gain_value[id]);
+	if (err < 0)
+		goto rpm_put;
+
+	/* Write duration parameters */
+	for (i = 0; i < NUM_DURATION_PARMS; i++) {
+		int val;
+
+		if (instant_gain)
+			val = 1;
+		else
+			val = gain_params.duration[i];
+
+		err = tegra210_mixer_write_ram(mixer,
+					       REG_DURATION_PARAM(reg, i),
+					       val);
+		if (err < 0)
+			goto rpm_put;
+	}
+
+	/* Trigger to apply gain configurations */
+	err = tegra210_mixer_write_ram(mixer, reg + REG_CFG_DONE_TRIGGER,
+				       VAL_CFG_DONE_TRIGGER);
+
+rpm_put:
+	pm_runtime_put(cmpnt->dev);
+
+	return err;
+}
+
+static int tegra210_mixer_get_gain(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
+	unsigned int reg = mc->reg;
+	unsigned int i;
+
+	i = (reg - TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_0) /
+	    TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_STRIDE;
+
+	ucontrol->value.integer.value[0] = mixer->gain_value[i];
+
+	return 0;
+}
+
+static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
+	unsigned int reg = mc->reg, id;
+	bool instant_gain = false;
+
+	if (strstr(kcontrol->id.name, "Instant Gain Volume"))
+		instant_gain = true;
+
+	/* Save gain value for specific MIXER input */
+	id = (reg - TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_0) /
+	     TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_STRIDE;
+
+	mixer->gain_value[id] = ucontrol->value.integer.value[0];
+
+	return tegra210_mixer_configure_gain(cmpnt, id, instant_gain);
+}
+
+static int tegra210_mixer_set_audio_cif(struct tegra210_mixer *mixer,
+					struct snd_pcm_hw_params *params,
+					unsigned int reg,
+					unsigned int id)
+{
+	unsigned int channels, audio_bits;
+	struct tegra_cif_conf cif_conf;
+
+	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
+
+	channels = params_channels(params);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		audio_bits = TEGRA_ACIF_BITS_16;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		audio_bits = TEGRA_ACIF_BITS_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cif_conf.audio_ch = channels;
+	cif_conf.client_ch = channels;
+	cif_conf.audio_bits = audio_bits;
+	cif_conf.client_bits = audio_bits;
+
+	tegra_set_cif(mixer->regmap,
+		      reg + (id * TEGRA210_MIXER_REG_STRIDE),
+		      &cif_conf);
+
+	return 0;
+}
+
+static int tegra210_mixer_in_hw_params(struct snd_pcm_substream *substream,
+				       struct snd_pcm_hw_params *params,
+				       struct snd_soc_dai *dai)
+{
+	struct tegra210_mixer *mixer = snd_soc_dai_get_drvdata(dai);
+	int err;
+
+	err = tegra210_mixer_set_audio_cif(mixer, params,
+					   TEGRA210_MIXER_RX1_CIF_CTRL,
+					   dai->id);
+	if (err < 0)
+		return err;
+
+	return tegra210_mixer_configure_gain(dai->component, dai->id, false);
+}
+
+static int tegra210_mixer_out_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params,
+					struct snd_soc_dai *dai)
+{
+	struct tegra210_mixer *mixer = snd_soc_dai_get_drvdata(dai);
+
+	return tegra210_mixer_set_audio_cif(mixer, params,
+					    TEGRA210_MIXER_TX1_CIF_CTRL,
+					    dai->id - TEGRA210_MIXER_RX_MAX);
+}
+
+static struct snd_soc_dai_ops tegra210_mixer_out_dai_ops = {
+	.hw_params	= tegra210_mixer_out_hw_params,
+};
+
+static struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = {
+	.hw_params	= tegra210_mixer_in_hw_params,
+};
+
+#define IN_DAI(id)						\
+	{							\
+		.name = "MIXER-RX-CIF"#id,			\
+		.playback = {					\
+			.stream_name = "RX" #id "-CIF-Playback",\
+			.channels_min = 1,			\
+			.channels_max = 8,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				SNDRV_PCM_FMTBIT_S16_LE |	\
+				SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.capture = {					\
+			.stream_name = "RX" #id "-CIF-Capture",	\
+			.channels_min = 1,			\
+			.channels_max = 8,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				SNDRV_PCM_FMTBIT_S16_LE |	\
+				SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.ops = &tegra210_mixer_in_dai_ops,		\
+	}
+
+#define OUT_DAI(id)						\
+	{							\
+		.name = "MIXER-TX-CIF" #id,			\
+		.playback = {					\
+			.stream_name = "TX" #id "-CIF-Playback",\
+			.channels_min = 1,			\
+			.channels_max = 8,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				SNDRV_PCM_FMTBIT_S16_LE |	\
+				SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.capture = {					\
+			.stream_name = "TX" #id "-CIF-Capture",	\
+			.channels_min = 1,			\
+			.channels_max = 8,			\
+			.rates = SNDRV_PCM_RATE_8000_192000,	\
+			.formats = SNDRV_PCM_FMTBIT_S8 |	\
+				SNDRV_PCM_FMTBIT_S16_LE |	\
+				SNDRV_PCM_FMTBIT_S32_LE,	\
+		},						\
+		.ops = &tegra210_mixer_out_dai_ops,		\
+	}
+
+static struct snd_soc_dai_driver tegra210_mixer_dais[] = {
+	/* Mixer Input */
+	IN_DAI(1),
+	IN_DAI(2),
+	IN_DAI(3),
+	IN_DAI(4),
+	IN_DAI(5),
+	IN_DAI(6),
+	IN_DAI(7),
+	IN_DAI(8),
+	IN_DAI(9),
+	IN_DAI(10),
+
+	/* Mixer Output */
+	OUT_DAI(1),
+	OUT_DAI(2),
+	OUT_DAI(3),
+	OUT_DAI(4),
+	OUT_DAI(5),
+};
+
+#define ADDER_CTRL_DECL(name, reg)			\
+	static const struct snd_kcontrol_new name[] = {	\
+		SOC_DAPM_SINGLE("RX1", reg, 0, 1, 0),	\
+		SOC_DAPM_SINGLE("RX2", reg, 1, 1, 0),	\
+		SOC_DAPM_SINGLE("RX3", reg, 2, 1, 0),	\
+		SOC_DAPM_SINGLE("RX4", reg, 3, 1, 0),	\
+		SOC_DAPM_SINGLE("RX5", reg, 4, 1, 0),	\
+		SOC_DAPM_SINGLE("RX6", reg, 5, 1, 0),	\
+		SOC_DAPM_SINGLE("RX7", reg, 6, 1, 0),	\
+		SOC_DAPM_SINGLE("RX8", reg, 7, 1, 0),	\
+		SOC_DAPM_SINGLE("RX9", reg, 8, 1, 0),	\
+		SOC_DAPM_SINGLE("RX10", reg, 9, 1, 0),	\
+	}
+
+ADDER_CTRL_DECL(adder1, TEGRA210_MIXER_TX1_ADDER_CONFIG);
+ADDER_CTRL_DECL(adder2, TEGRA210_MIXER_TX2_ADDER_CONFIG);
+ADDER_CTRL_DECL(adder3, TEGRA210_MIXER_TX3_ADDER_CONFIG);
+ADDER_CTRL_DECL(adder4, TEGRA210_MIXER_TX4_ADDER_CONFIG);
+ADDER_CTRL_DECL(adder5, TEGRA210_MIXER_TX5_ADDER_CONFIG);
+
+#define GAIN_CTRL(id)	\
+	SOC_SINGLE_EXT("RX" #id " Gain Volume",			\
+		       MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0,	\
+		       0x20000, 0, tegra210_mixer_get_gain,	\
+		       tegra210_mixer_put_gain),		\
+	SOC_SINGLE_EXT("RX" #id " Instant Gain Volume",		\
+		       MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0,	\
+		       0x20000, 0, tegra210_mixer_get_gain,	\
+		       tegra210_mixer_put_gain),
+
+/* Volume controls for all MIXER inputs */
+static const struct snd_kcontrol_new tegra210_mixer_gain_ctls[] = {
+	GAIN_CTRL(1)
+	GAIN_CTRL(2)
+	GAIN_CTRL(3)
+	GAIN_CTRL(4)
+	GAIN_CTRL(5)
+	GAIN_CTRL(6)
+	GAIN_CTRL(7)
+	GAIN_CTRL(8)
+	GAIN_CTRL(9)
+	GAIN_CTRL(10)
+};
+
+static const struct snd_soc_dapm_widget tegra210_mixer_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("RX4", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("RX5", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("RX6", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("RX7", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("RX8", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("RX9", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("RX10", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("TX1", NULL, 0, TEGRA210_MIXER_TX1_ENABLE, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("TX2", NULL, 0, TEGRA210_MIXER_TX2_ENABLE, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("TX3", NULL, 0, TEGRA210_MIXER_TX3_ENABLE, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("TX4", NULL, 0, TEGRA210_MIXER_TX4_ENABLE, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("TX5", NULL, 0, TEGRA210_MIXER_TX5_ENABLE, 0, 0),
+	SND_SOC_DAPM_MIXER("Adder1", SND_SOC_NOPM, 1, 0, adder1,
+			   ARRAY_SIZE(adder1)),
+	SND_SOC_DAPM_MIXER("Adder2", SND_SOC_NOPM, 1, 0, adder2,
+			   ARRAY_SIZE(adder2)),
+	SND_SOC_DAPM_MIXER("Adder3", SND_SOC_NOPM, 1, 0, adder3,
+			   ARRAY_SIZE(adder3)),
+	SND_SOC_DAPM_MIXER("Adder4", SND_SOC_NOPM, 1, 0, adder4,
+			   ARRAY_SIZE(adder4)),
+	SND_SOC_DAPM_MIXER("Adder5", SND_SOC_NOPM, 1, 0, adder5,
+			   ARRAY_SIZE(adder5)),
+};
+
+#define RX_ROUTES(id, sname)						   \
+	{ "RX" #id " XBAR-" sname,	NULL,	"RX" #id " XBAR-TX" },	   \
+	{ "RX" #id "-CIF-" sname,	NULL,	"RX" #id " XBAR-" sname }, \
+	{ "RX" #id,			NULL,	"RX" #id "-CIF-" sname }
+
+#define MIXER_RX_ROUTES(id)		\
+	RX_ROUTES(id, "Playback"),	\
+	RX_ROUTES(id, "Capture")
+
+#define ADDER_ROUTES(id, sname)						  \
+	{ "Adder" #id,			"RX1",	"RX1" },		  \
+	{ "Adder" #id,			"RX2",	"RX2" },		  \
+	{ "Adder" #id,			"RX3",	"RX3" },		  \
+	{ "Adder" #id,			"RX4",	"RX4" },		  \
+	{ "Adder" #id,			"RX5",	"RX5" },		  \
+	{ "Adder" #id,			"RX6",	"RX6" },		  \
+	{ "Adder" #id,			"RX7",	"RX7" },		  \
+	{ "Adder" #id,			"RX8",	"RX8" },		  \
+	{ "Adder" #id,			"RX9",	"RX9" },		  \
+	{ "Adder" #id,			"RX10",	"RX10" },		  \
+	{ "TX" #id,			NULL,	"Adder" #id },		  \
+	{ "TX" #id "-CIF-" sname,	NULL,	"TX" #id },		  \
+	{ "TX" #id " XBAR-" sname,	NULL,	"TX" #id "-CIF-" sname }, \
+	{ "TX" #id " XBAR-RX",		NULL,	"TX" #id " XBAR-" sname } \
+
+#define TX_ROUTES(id, sname)		\
+	ADDER_ROUTES(1, sname),		\
+	ADDER_ROUTES(2, sname),		\
+	ADDER_ROUTES(3, sname),		\
+	ADDER_ROUTES(4, sname),		\
+	ADDER_ROUTES(5, sname)
+
+#define MIXER_TX_ROUTES(id)		\
+	TX_ROUTES(id, "Playback"),	\
+	TX_ROUTES(id, "Capture")
+
+static const struct snd_soc_dapm_route tegra210_mixer_routes[] = {
+	/* Input */
+	MIXER_RX_ROUTES(1),
+	MIXER_RX_ROUTES(2),
+	MIXER_RX_ROUTES(3),
+	MIXER_RX_ROUTES(4),
+	MIXER_RX_ROUTES(5),
+	MIXER_RX_ROUTES(6),
+	MIXER_RX_ROUTES(7),
+	MIXER_RX_ROUTES(8),
+	MIXER_RX_ROUTES(9),
+	MIXER_RX_ROUTES(10),
+	/* Output */
+	MIXER_TX_ROUTES(1),
+	MIXER_TX_ROUTES(2),
+	MIXER_TX_ROUTES(3),
+	MIXER_TX_ROUTES(4),
+	MIXER_TX_ROUTES(5),
+};
+
+static const struct snd_soc_component_driver tegra210_mixer_cmpnt = {
+	.dapm_widgets		= tegra210_mixer_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(tegra210_mixer_widgets),
+	.dapm_routes		= tegra210_mixer_routes,
+	.num_dapm_routes	= ARRAY_SIZE(tegra210_mixer_routes),
+	.controls		= tegra210_mixer_gain_ctls,
+	.num_controls		= ARRAY_SIZE(tegra210_mixer_gain_ctls),
+};
+
+static bool tegra210_mixer_wr_reg(struct device *dev,
+				unsigned int reg)
+{
+	if (reg < TEGRA210_MIXER_RX_LIMIT)
+		reg = MIXER_REG_BASE(reg);
+	else if (reg < TEGRA210_MIXER_TX_LIMIT)
+		reg = MIXER_REG_BASE(reg) + TEGRA210_MIXER_TX1_ENABLE;
+
+	switch (reg) {
+	case TEGRA210_MIXER_RX1_SOFT_RESET:
+	case TEGRA210_MIXER_RX1_CIF_CTRL ... TEGRA210_MIXER_RX1_PEAK_CTRL:
+
+	case TEGRA210_MIXER_TX1_ENABLE:
+	case TEGRA210_MIXER_TX1_SOFT_RESET:
+	case TEGRA210_MIXER_TX1_INT_MASK ... TEGRA210_MIXER_TX1_ADDER_CONFIG:
+
+	case TEGRA210_MIXER_ENABLE ... TEGRA210_MIXER_CG:
+	case TEGRA210_MIXER_GAIN_CFG_RAM_CTRL ... TEGRA210_MIXER_CTRL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra210_mixer_rd_reg(struct device *dev,
+				unsigned int reg)
+{
+	if (reg < TEGRA210_MIXER_RX_LIMIT)
+		reg = MIXER_REG_BASE(reg);
+	else if (reg < TEGRA210_MIXER_TX_LIMIT)
+		reg = MIXER_REG_BASE(reg) + TEGRA210_MIXER_TX1_ENABLE;
+
+	switch (reg) {
+	case TEGRA210_MIXER_RX1_SOFT_RESET ... TEGRA210_MIXER_RX1_SAMPLE_COUNT:
+	case TEGRA210_MIXER_TX1_ENABLE ... TEGRA210_MIXER_TX1_ADDER_CONFIG:
+	case TEGRA210_MIXER_ENABLE ... TEGRA210_MIXER_CTRL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra210_mixer_volatile_reg(struct device *dev,
+				unsigned int reg)
+{
+	if (reg < TEGRA210_MIXER_RX_LIMIT)
+		reg = MIXER_REG_BASE(reg);
+	else if (reg < TEGRA210_MIXER_TX_LIMIT)
+		reg = MIXER_REG_BASE(reg) + TEGRA210_MIXER_TX1_ENABLE;
+
+	switch (reg) {
+	case TEGRA210_MIXER_RX1_SOFT_RESET:
+	case TEGRA210_MIXER_RX1_STATUS:
+
+	case TEGRA210_MIXER_TX1_SOFT_RESET:
+	case TEGRA210_MIXER_TX1_STATUS:
+	case TEGRA210_MIXER_TX1_INT_STATUS:
+	case TEGRA210_MIXER_TX1_INT_SET:
+
+	case TEGRA210_MIXER_SOFT_RESET:
+	case TEGRA210_MIXER_STATUS:
+	case TEGRA210_MIXER_INT_STATUS:
+	case TEGRA210_MIXER_GAIN_CFG_RAM_CTRL:
+	case TEGRA210_MIXER_GAIN_CFG_RAM_DATA:
+	case TEGRA210_MIXER_PEAKM_RAM_CTRL:
+	case TEGRA210_MIXER_PEAKM_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool tegra210_mixer_precious_reg(struct device *dev,
+				unsigned int reg)
+{
+	switch (reg) {
+	case TEGRA210_MIXER_GAIN_CFG_RAM_DATA:
+	case TEGRA210_MIXER_PEAKM_RAM_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config tegra210_mixer_regmap_config = {
+	.reg_bits		= 32,
+	.reg_stride		= 4,
+	.val_bits		= 32,
+	.max_register		= TEGRA210_MIXER_CTRL,
+	.writeable_reg		= tegra210_mixer_wr_reg,
+	.readable_reg		= tegra210_mixer_rd_reg,
+	.volatile_reg		= tegra210_mixer_volatile_reg,
+	.precious_reg		= tegra210_mixer_precious_reg,
+	.reg_defaults		= tegra210_mixer_reg_defaults,
+	.num_reg_defaults	= ARRAY_SIZE(tegra210_mixer_reg_defaults),
+	.cache_type		= REGCACHE_FLAT,
+};
+
+static const struct of_device_id tegra210_mixer_of_match[] = {
+	{ .compatible = "nvidia,tegra210-amixer" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tegra210_mixer_of_match);
+
+static int tegra210_mixer_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra210_mixer *mixer;
+	void __iomem *regs;
+	int err, i;
+
+	mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
+	if (!mixer)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, mixer);
+
+	/* Use default gain value for all MIXER inputs */
+	for (i = 0; i < TEGRA210_MIXER_RX_MAX; i++)
+		mixer->gain_value[i] = gain_params.gain_value;
+
+	regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	mixer->regmap = devm_regmap_init_mmio(dev, regs,
+					      &tegra210_mixer_regmap_config);
+	if (IS_ERR(mixer->regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(mixer->regmap);
+	}
+
+	regcache_cache_only(mixer->regmap, true);
+
+	err = devm_snd_soc_register_component(dev, &tegra210_mixer_cmpnt,
+					      tegra210_mixer_dais,
+					      ARRAY_SIZE(tegra210_mixer_dais));
+	if (err) {
+		dev_err(dev, "can't register MIXER component, err: %d\n", err);
+		return err;
+	}
+
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+
+static int tegra210_mixer_platform_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops tegra210_mixer_pm_ops = {
+	SET_RUNTIME_PM_OPS(tegra210_mixer_runtime_suspend,
+			   tegra210_mixer_runtime_resume, NULL)
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				     pm_runtime_force_resume)
+};
+
+static struct platform_driver tegra210_mixer_driver = {
+	.driver = {
+		.name = "tegra210_mixer",
+		.of_match_table = tegra210_mixer_of_match,
+		.pm = &tegra210_mixer_pm_ops,
+	},
+	.probe = tegra210_mixer_platform_probe,
+	.remove = tegra210_mixer_platform_remove,
+};
+module_platform_driver(tegra210_mixer_driver);
+
+MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>");
+MODULE_DESCRIPTION("Tegra210 MIXER ASoC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/tegra/tegra210_mixer.h b/sound/soc/tegra/tegra210_mixer.h
new file mode 100644
index 0000000..a330530
--- /dev/null
+++ b/sound/soc/tegra/tegra210_mixer.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * tegra210_mixer.h - Definitions for Tegra210 MIXER driver
+ *
+ * Copyright (c) 2021, NVIDIA CORPORATION.  All rights reserved.
+ *
+ */
+
+#ifndef __TEGRA210_MIXER_H__
+#define __TEGRA210_MIXER_H__
+
+/* XBAR_RX related MIXER offsets */
+#define TEGRA210_MIXER_RX1_SOFT_RESET	0x04
+#define TEGRA210_MIXER_RX1_STATUS	0x10
+#define TEGRA210_MIXER_RX1_CIF_CTRL	0x24
+#define TEGRA210_MIXER_RX1_CTRL		0x28
+#define TEGRA210_MIXER_RX1_PEAK_CTRL	0x2c
+#define TEGRA210_MIXER_RX1_SAMPLE_COUNT	0x30
+
+/* XBAR_TX related MIXER offsets */
+#define TEGRA210_MIXER_TX1_ENABLE	0x280
+#define TEGRA210_MIXER_TX1_SOFT_RESET	0x284
+#define TEGRA210_MIXER_TX1_STATUS	0x290
+#define TEGRA210_MIXER_TX1_INT_STATUS	0x294
+#define TEGRA210_MIXER_TX1_INT_MASK	0x298
+#define TEGRA210_MIXER_TX1_INT_SET	0x29c
+#define TEGRA210_MIXER_TX1_INT_CLEAR	0x2a0
+#define TEGRA210_MIXER_TX1_CIF_CTRL	0x2a4
+#define TEGRA210_MIXER_TX1_ADDER_CONFIG	0x2a8
+
+/* MIXER related offsets */
+#define TEGRA210_MIXER_ENABLE			0x400
+#define TEGRA210_MIXER_SOFT_RESET		0x404
+#define TEGRA210_MIXER_CG			0x408
+#define TEGRA210_MIXER_STATUS			0x410
+#define TEGRA210_MIXER_INT_STATUS		0x414
+#define TEGRA210_MIXER_GAIN_CFG_RAM_CTRL	0x42c
+#define TEGRA210_MIXER_GAIN_CFG_RAM_DATA	0x430
+#define TEGRA210_MIXER_PEAKM_RAM_CTRL		0x434
+#define TEGRA210_MIXER_PEAKM_RAM_DATA		0x438
+#define TEGRA210_MIXER_CTRL			0x43c
+
+#define TEGRA210_MIXER_TX2_ADDER_CONFIG	(TEGRA210_MIXER_TX1_ADDER_CONFIG + TEGRA210_MIXER_REG_STRIDE)
+#define TEGRA210_MIXER_TX3_ADDER_CONFIG	(TEGRA210_MIXER_TX2_ADDER_CONFIG + TEGRA210_MIXER_REG_STRIDE)
+#define TEGRA210_MIXER_TX4_ADDER_CONFIG	(TEGRA210_MIXER_TX3_ADDER_CONFIG + TEGRA210_MIXER_REG_STRIDE)
+#define TEGRA210_MIXER_TX5_ADDER_CONFIG	(TEGRA210_MIXER_TX4_ADDER_CONFIG + TEGRA210_MIXER_REG_STRIDE)
+
+#define TEGRA210_MIXER_TX2_ENABLE	(TEGRA210_MIXER_TX1_ENABLE + TEGRA210_MIXER_REG_STRIDE)
+#define TEGRA210_MIXER_TX3_ENABLE	(TEGRA210_MIXER_TX2_ENABLE + TEGRA210_MIXER_REG_STRIDE)
+#define TEGRA210_MIXER_TX4_ENABLE	(TEGRA210_MIXER_TX3_ENABLE + TEGRA210_MIXER_REG_STRIDE)
+#define TEGRA210_MIXER_TX5_ENABLE	(TEGRA210_MIXER_TX4_ENABLE + TEGRA210_MIXER_REG_STRIDE)
+
+/* Fields in TEGRA210_MIXER_ENABLE */
+#define TEGRA210_MIXER_ENABLE_SHIFT	0
+#define TEGRA210_MIXER_ENABLE_MASK	(1 << TEGRA210_MIXER_ENABLE_SHIFT)
+#define TEGRA210_MIXER_EN		(1 << TEGRA210_MIXER_ENABLE_SHIFT)
+
+/* Fields in TEGRA210_MIXER_GAIN_CFG_RAM_CTRL */
+#define TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_0		0x0
+#define TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_STRIDE		0x10
+
+#define TEGRA210_MIXER_GAIN_CFG_RAM_RW_SHIFT		14
+#define TEGRA210_MIXER_GAIN_CFG_RAM_RW_MASK		(1 << TEGRA210_MIXER_GAIN_CFG_RAM_RW_SHIFT)
+#define TEGRA210_MIXER_GAIN_CFG_RAM_RW_WRITE		(1 << TEGRA210_MIXER_GAIN_CFG_RAM_RW_SHIFT)
+
+#define TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_INIT_EN_SHIFT	13
+#define TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_INIT_EN_MASK	(1 << TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_INIT_EN_SHIFT)
+#define TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_INIT_EN	(1 << TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_INIT_EN_SHIFT)
+
+#define TEGRA210_MIXER_GAIN_CFG_RAM_SEQ_ACCESS_EN_SHIFT	12
+#define TEGRA210_MIXER_GAIN_CFG_RAM_SEQ_ACCESS_EN_MASK	(1 << TEGRA210_MIXER_GAIN_CFG_RAM_SEQ_ACCESS_EN_SHIFT)
+#define TEGRA210_MIXER_GAIN_CFG_RAM_SEQ_ACCESS_EN	(1 << TEGRA210_MIXER_GAIN_CFG_RAM_SEQ_ACCESS_EN_SHIFT)
+
+#define TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_SHIFT		0
+#define TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_MASK		(0x1ff << TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_SHIFT)
+
+#define TEGRA210_MIXER_REG_STRIDE	0x40
+#define TEGRA210_MIXER_RX_MAX		10
+#define TEGRA210_MIXER_RX_LIMIT		(TEGRA210_MIXER_RX_MAX * TEGRA210_MIXER_REG_STRIDE)
+#define TEGRA210_MIXER_TX_MAX		5
+#define TEGRA210_MIXER_TX_LIMIT		(TEGRA210_MIXER_RX_LIMIT + (TEGRA210_MIXER_TX_MAX * TEGRA210_MIXER_REG_STRIDE))
+
+#define REG_CFG_DONE_TRIGGER	0xf
+#define VAL_CFG_DONE_TRIGGER	0x1
+
+#define NUM_GAIN_POLY_COEFFS 9
+#define NUM_DURATION_PARMS 4
+
+struct tegra210_mixer_gain_params {
+	int poly_coeff[NUM_GAIN_POLY_COEFFS];
+	int gain_value;
+	int duration[NUM_DURATION_PARMS];
+};
+
+struct tegra210_mixer {
+	int gain_value[TEGRA210_MIXER_RX_MAX];
+	struct regmap *regmap;
+};
+
+#endif
-- 
2.7.4


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

* [PATCH 11/13] arm64: defconfig: Enable few Tegra210 based AHUB drivers
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (9 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 10/13] ASoC: tegra: Add Tegra210 based Mixer driver Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-08-27  9:33 ` [PATCH 12/13] arm64: tegra: Add few AHUB devices for Tegra210 and later Sameer Pujar
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

Enable configs for following modules:
 * SFC (Sampling Frequency Converter)
 * MVC (Master Volume Control)
 * AMX (Audio Multiplexer)
 * ADX (Audio Demultiplexer)
 * Mixer

These configs are used on Tegra186 and later SoCs as well.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 arch/arm64/configs/defconfig | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3bf6f8a..b936a23 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -773,6 +773,11 @@ CONFIG_SND_SOC_TEGRA210_DMIC=m
 CONFIG_SND_SOC_TEGRA210_I2S=m
 CONFIG_SND_SOC_TEGRA186_DSPK=m
 CONFIG_SND_SOC_TEGRA210_ADMAIF=m
+CONFIG_SND_SOC_TEGRA210_MVC=m
+CONFIG_SND_SOC_TEGRA210_SFC=m
+CONFIG_SND_SOC_TEGRA210_AMX=m
+CONFIG_SND_SOC_TEGRA210_ADX=m
+CONFIG_SND_SOC_TEGRA210_MIXER=m
 CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD=m
 CONFIG_SND_SOC_AK4613=m
 CONFIG_SND_SOC_ES7134=m
-- 
2.7.4


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

* [PATCH 12/13] arm64: tegra: Add few AHUB devices for Tegra210 and later
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (10 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 11/13] arm64: defconfig: Enable few Tegra210 based AHUB drivers Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-08-27  9:33 ` [PATCH 13/13] arm64: tegra: Extend APE audio support on Jetson platforms Sameer Pujar
  2021-09-08  4:56 ` [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

Add DT nodes for following AHUB devices:
 * SFC (Sampling Frequency Converter)
 * MVC (Master Volume Control)
 * AMX (Audio Multiplexer)
 * ADX (Audio Demultiplexer)
 * Mixer

Above devices are added for Tegra210, Tegra186 and Tegra194 generations
of Tegra SoC.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 120 +++++++++++++++++++++++++++++++
 arch/arm64/boot/dts/nvidia/tegra194.dtsi | 116 ++++++++++++++++++++++++++++++
 arch/arm64/boot/dts/nvidia/tegra210.dtsi |  77 ++++++++++++++++++++
 3 files changed, 313 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index e94f8ad..0d0ada5 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -354,6 +354,126 @@
 				sound-name-prefix = "DSPK2";
 				status = "disabled";
 			};
+
+			tegra_sfc1: sfc@2902000 {
+				compatible = "nvidia,tegra186-sfc",
+					     "nvidia,tegra210-sfc";
+				reg = <0x2902000 0x200>;
+				sound-name-prefix = "SFC1";
+				status = "disabled";
+			};
+
+			tegra_sfc2: sfc@2902200 {
+				compatible = "nvidia,tegra186-sfc",
+					     "nvidia,tegra210-sfc";
+				reg = <0x2902200 0x200>;
+				sound-name-prefix = "SFC2";
+				status = "disabled";
+			};
+
+			tegra_sfc3: sfc@2902400 {
+				compatible = "nvidia,tegra186-sfc",
+					     "nvidia,tegra210-sfc";
+				reg = <0x2902400 0x200>;
+				sound-name-prefix = "SFC3";
+				status = "disabled";
+			};
+
+			tegra_sfc4: sfc@2902600 {
+				compatible = "nvidia,tegra186-sfc",
+					     "nvidia,tegra210-sfc";
+				reg = <0x2902600 0x200>;
+				sound-name-prefix = "SFC4";
+				status = "disabled";
+			};
+
+			tegra_mvc1: mvc@290a000 {
+				compatible = "nvidia,tegra186-mvc",
+					     "nvidia,tegra210-mvc";
+				reg = <0x290a000 0x200>;
+				sound-name-prefix = "MVC1";
+				status = "disabled";
+			};
+
+			tegra_mvc2: mvc@290a200 {
+				compatible = "nvidia,tegra186-mvc",
+					     "nvidia,tegra210-mvc";
+				reg = <0x290a200 0x200>;
+				sound-name-prefix = "MVC2";
+				status = "disabled";
+			};
+
+			tegra_amx1: amx@2903000 {
+				compatible = "nvidia,tegra186-amx",
+					     "nvidia,tegra210-amx";
+				reg = <0x2903000 0x100>;
+				sound-name-prefix = "AMX1";
+				status = "disabled";
+			};
+
+			tegra_amx2: amx@2903100 {
+				compatible = "nvidia,tegra186-amx",
+					     "nvidia,tegra210-amx";
+				reg = <0x2903100 0x100>;
+				sound-name-prefix = "AMX2";
+				status = "disabled";
+			};
+
+			tegra_amx3: amx@2903200 {
+				compatible = "nvidia,tegra186-amx",
+					     "nvidia,tegra210-amx";
+				reg = <0x2903200 0x100>;
+				sound-name-prefix = "AMX3";
+				status = "disabled";
+			};
+
+			tegra_amx4: amx@2903300 {
+				compatible = "nvidia,tegra186-amx",
+					     "nvidia,tegra210-amx";
+				reg = <0x2903300 0x100>;
+				sound-name-prefix = "AMX4";
+				status = "disabled";
+			};
+
+			tegra_adx1: adx@2903800 {
+				compatible = "nvidia,tegra186-adx",
+					     "nvidia,tegra210-adx";
+				reg = <0x2903800 0x100>;
+				sound-name-prefix = "ADX1";
+				status = "disabled";
+			};
+
+			tegra_adx2: adx@2903900 {
+				compatible = "nvidia,tegra186-adx",
+					     "nvidia,tegra210-adx";
+				reg = <0x2903900 0x100>;
+				sound-name-prefix = "ADX2";
+				status = "disabled";
+			};
+
+			tegra_adx3: adx@2903a00 {
+				compatible = "nvidia,tegra186-adx",
+					     "nvidia,tegra210-adx";
+				reg = <0x2903a00 0x100>;
+				sound-name-prefix = "ADX3";
+				status = "disabled";
+			};
+
+			tegra_adx4: adx@2903b00 {
+				compatible = "nvidia,tegra186-adx",
+					     "nvidia,tegra210-adx";
+				reg = <0x2903b00 0x100>;
+				sound-name-prefix = "ADX4";
+				status = "disabled";
+			};
+
+			tegra_amixer: amixer@290bb00 {
+				compatible = "nvidia,tegra186-amixer",
+					     "nvidia,tegra210-amixer";
+				reg = <0x290bb00 0x800>;
+				sound-name-prefix = "MIXER";
+				status = "disabled";
+			};
 		};
 	};
 
diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
index c8250a3..6027d84 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
@@ -363,6 +363,122 @@
 					sound-name-prefix = "DSPK2";
 					status = "disabled";
 				};
+
+				tegra_sfc1: sfc@2902000 {
+					compatible = "nvidia,tegra194-sfc",
+						     "nvidia,tegra210-sfc";
+					reg = <0x2902000 0x200>;
+					sound-name-prefix = "SFC1";
+					status = "disabled";
+				};
+
+				tegra_sfc2: sfc@2902200 {
+					compatible = "nvidia,tegra194-sfc",
+						     "nvidia,tegra210-sfc";
+					reg = <0x2902200 0x200>;
+					sound-name-prefix = "SFC2";
+					status = "disabled";
+				};
+
+				tegra_sfc3: sfc@2902400 {
+					compatible = "nvidia,tegra194-sfc",
+						     "nvidia,tegra210-sfc";
+					reg = <0x2902400 0x200>;
+					sound-name-prefix = "SFC3";
+					status = "disabled";
+				};
+
+				tegra_sfc4: sfc@2902600 {
+					compatible = "nvidia,tegra194-sfc",
+						     "nvidia,tegra210-sfc";
+					reg = <0x2902600 0x200>;
+					sound-name-prefix = "SFC4";
+					status = "disabled";
+				};
+
+				tegra_mvc1: mvc@290a000 {
+					compatible = "nvidia,tegra194-mvc",
+						     "nvidia,tegra210-mvc";
+					reg = <0x290a000 0x200>;
+					sound-name-prefix = "MVC1";
+					status = "disabled";
+				};
+
+				tegra_mvc2: mvc@290a200 {
+					compatible = "nvidia,tegra194-mvc",
+						     "nvidia,tegra210-mvc";
+					reg = <0x290a200 0x200>;
+					sound-name-prefix = "MVC2";
+					status = "disabled";
+				};
+
+				tegra_amx1: amx@2903000 {
+					compatible = "nvidia,tegra194-amx";
+					reg = <0x2903000 0x100>;
+					sound-name-prefix = "AMX1";
+					status = "disabled";
+				};
+
+				tegra_amx2: amx@2903100 {
+					compatible = "nvidia,tegra194-amx";
+					reg = <0x2903100 0x100>;
+					sound-name-prefix = "AMX2";
+					status = "disabled";
+				};
+
+				tegra_amx3: amx@2903200 {
+					compatible = "nvidia,tegra194-amx";
+					reg = <0x2903200 0x100>;
+					sound-name-prefix = "AMX3";
+					status = "disabled";
+				};
+
+				tegra_amx4: amx@2903300 {
+					compatible = "nvidia,tegra194-amx";
+					reg = <0x2903300 0x100>;
+					sound-name-prefix = "AMX4";
+					status = "disabled";
+				};
+
+				tegra_adx1: adx@2903800 {
+					compatible = "nvidia,tegra194-adx",
+						     "nvidia,tegra210-adx";
+					reg = <0x2903800 0x100>;
+					sound-name-prefix = "ADX1";
+					status = "disabled";
+				};
+
+				tegra_adx2: adx@2903900 {
+					compatible = "nvidia,tegra194-adx",
+						     "nvidia,tegra210-adx";
+					reg = <0x2903900 0x100>;
+					sound-name-prefix = "ADX2";
+					status = "disabled";
+				};
+
+				tegra_adx3: adx@2903a00 {
+					compatible = "nvidia,tegra194-adx",
+						     "nvidia,tegra210-adx";
+					reg = <0x2903a00 0x100>;
+					sound-name-prefix = "ADX3";
+					status = "disabled";
+				};
+
+				tegra_adx4: adx@2903b00 {
+					compatible = "nvidia,tegra194-adx",
+						     "nvidia,tegra210-adx";
+					reg = <0x2903b00 0x100>;
+					sound-name-prefix = "ADX4";
+					status = "disabled";
+				};
+
+				tegra_amixer: amixer@290bb00 {
+					compatible = "nvidia,tegra194-amixer",
+						     "nvidia,tegra210-amixer";
+					reg = <0x290bb00 0x800>;
+					sound-name-prefix = "MIXER";
+					status = "disabled";
+				};
 			};
 		};
 
diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 26b3f98a..b84c963 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1641,6 +1641,83 @@
 				status = "disabled";
 			};
 
+			tegra_sfc1: sfc@702d2000 {
+				compatible = "nvidia,tegra210-sfc";
+				reg = <0x702d2000 0x200>;
+				sound-name-prefix = "SFC1";
+				status = "disabled";
+			};
+
+			tegra_sfc2: sfc@702d2200 {
+				compatible = "nvidia,tegra210-sfc";
+				reg = <0x702d2200 0x200>;
+				sound-name-prefix = "SFC2";
+				status = "disabled";
+			};
+
+			tegra_sfc3: sfc@702d2400 {
+				compatible = "nvidia,tegra210-sfc";
+				reg = <0x702d2400 0x200>;
+				sound-name-prefix = "SFC3";
+				status = "disabled";
+			};
+
+			tegra_sfc4: sfc@702d2600 {
+				compatible = "nvidia,tegra210-sfc";
+				reg = <0x702d2600 0x200>;
+				sound-name-prefix = "SFC4";
+				status = "disabled";
+			};
+
+			tegra_mvc1: mvc@702da000 {
+				compatible = "nvidia,tegra210-mvc";
+				reg = <0x702da000 0x200>;
+				sound-name-prefix = "MVC1";
+				status = "disabled";
+			};
+
+			tegra_mvc2: mvc@702da200 {
+				compatible = "nvidia,tegra210-mvc";
+				reg = <0x702da200 0x200>;
+				sound-name-prefix = "MVC2";
+				status = "disabled";
+			};
+
+			tegra_amx1: amx@702d3000 {
+				compatible = "nvidia,tegra210-amx";
+				reg = <0x702d3000 0x100>;
+				sound-name-prefix = "AMX1";
+				status = "disabled";
+			};
+
+			tegra_amx2: amx@702d3100 {
+				compatible = "nvidia,tegra210-amx";
+				reg = <0x702d3100 0x100>;
+				sound-name-prefix = "AMX2";
+				status = "disabled";
+			};
+
+			tegra_adx1: adx@702d3800 {
+				compatible = "nvidia,tegra210-adx";
+				reg = <0x702d3800 0x100>;
+				sound-name-prefix = "ADX1";
+				status = "disabled";
+			};
+
+			tegra_adx2: adx@702d3900 {
+				compatible = "nvidia,tegra210-adx";
+				reg = <0x702d3900 0x100>;
+				sound-name-prefix = "ADX2";
+				status = "disabled";
+			};
+
+			tegra_amixer: amixer@702dbb00 {
+				compatible = "nvidia,tegra210-amixer";
+				reg = <0x702dbb00 0x800>;
+				sound-name-prefix = "MIXER";
+				status = "disabled";
+			};
+
 			ports {
 				#address-cells = <1>;
 				#size-cells = <0>;
-- 
2.7.4


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

* [PATCH 13/13] arm64: tegra: Extend APE audio support on Jetson platforms
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (11 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 12/13] arm64: tegra: Add few AHUB devices for Tegra210 and later Sameer Pujar
@ 2021-08-27  9:33 ` Sameer Pujar
  2021-09-08  4:56 ` [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-08-27  9:33 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel, Sameer Pujar

Extend APE audio support by adding more audio components such as SFC,
MVC, AMX, ADX and Mixer. These components can be plugged into an audio
path and required processing can be done. ASoC audio-graph based sound
driver is used to facilitate this and thus extend sound bindings as
well.

The components in the path may require different PCM parameters (such
as sample rate, channels or sample size). Depending on the pre-defined
audio paths, these can be statically configured with "convert-xxx" DT
properties in endpoint subnode. The support for the rate and channel
conversion is already available in generic audio-graph driver. Sample
size conversion support can be added based on the need in future.

The support is extended for following platforms:
 * Jertson TX1
 * Jetson Nano
 * Jetson TX2
 * Jetson AGX Xavier
 * Jetson Xavier NX

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts | 1554 ++++++++++++++++++--
 arch/arm64/boot/dts/nvidia/tegra194-p2972-0000.dts | 1493 +++++++++++++++++--
 .../arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi | 1520 +++++++++++++++++--
 arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts |  876 +++++++++++
 arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts |  876 +++++++++++
 5 files changed, 5900 insertions(+), 419 deletions(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
index 74c1a5d..52fa258 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
@@ -275,178 +275,1097 @@
 						remote-endpoint = <&dspk2_cif_ep>;
 					};
 				};
+
+				xbar_sfc1_in_port: port@20 {
+					reg = <0x20>;
+
+					xbar_sfc1_in_ep: endpoint {
+						remote-endpoint = <&sfc1_cif_in_ep>;
+					};
+				};
+
+				port@21 {
+					reg = <0x21>;
+
+					xbar_sfc1_out_ep: endpoint {
+						remote-endpoint = <&sfc1_cif_out_ep>;
+					};
+				};
+
+				xbar_sfc2_in_port: port@22 {
+					reg = <0x22>;
+
+					xbar_sfc2_in_ep: endpoint {
+						remote-endpoint = <&sfc2_cif_in_ep>;
+					};
+				};
+
+				port@23 {
+					reg = <0x23>;
+
+					xbar_sfc2_out_ep: endpoint {
+						remote-endpoint = <&sfc2_cif_out_ep>;
+					};
+				};
+
+				xbar_sfc3_in_port: port@24 {
+					reg = <0x24>;
+
+					xbar_sfc3_in_ep: endpoint {
+						remote-endpoint = <&sfc3_cif_in_ep>;
+					};
+				};
+
+				port@25 {
+					reg = <0x25>;
+
+					xbar_sfc3_out_ep: endpoint {
+						remote-endpoint = <&sfc3_cif_out_ep>;
+					};
+				};
+
+				xbar_sfc4_in_port: port@26 {
+					reg = <0x26>;
+
+					xbar_sfc4_in_ep: endpoint {
+						remote-endpoint = <&sfc4_cif_in_ep>;
+					};
+				};
+
+				port@27 {
+					reg = <0x27>;
+
+					xbar_sfc4_out_ep: endpoint {
+						remote-endpoint = <&sfc4_cif_out_ep>;
+					};
+				};
+
+				xbar_mvc1_in_port: port@28 {
+					reg = <0x28>;
+
+					xbar_mvc1_in_ep: endpoint {
+						remote-endpoint = <&mvc1_cif_in_ep>;
+					};
+				};
+
+				port@29 {
+					reg = <0x29>;
+
+					xbar_mvc1_out_ep: endpoint {
+						remote-endpoint = <&mvc1_cif_out_ep>;
+					};
+				};
+
+				xbar_mvc2_in_port: port@2a {
+					reg = <0x2a>;
+
+					xbar_mvc2_in_ep: endpoint {
+						remote-endpoint = <&mvc2_cif_in_ep>;
+					};
+				};
+
+				port@2b {
+					reg = <0x2b>;
+
+					xbar_mvc2_out_ep: endpoint {
+						remote-endpoint = <&mvc2_cif_out_ep>;
+					};
+				};
+
+				xbar_amx1_in1_port: port@2c {
+					reg = <0x2c>;
+
+					xbar_amx1_in1_ep: endpoint {
+						remote-endpoint = <&amx1_in1_ep>;
+					};
+				};
+
+				xbar_amx1_in2_port: port@2d {
+					reg = <0x2d>;
+
+					xbar_amx1_in2_ep: endpoint {
+						remote-endpoint = <&amx1_in2_ep>;
+					};
+				};
+
+				xbar_amx1_in3_port: port@2e {
+					reg = <0x2e>;
+
+					xbar_amx1_in3_ep: endpoint {
+						remote-endpoint = <&amx1_in3_ep>;
+					};
+				};
+
+				xbar_amx1_in4_port: port@2f {
+					reg = <0x2f>;
+
+					xbar_amx1_in4_ep: endpoint {
+						remote-endpoint = <&amx1_in4_ep>;
+					};
+				};
+
+				port@30 {
+					reg = <0x30>;
+
+					xbar_amx1_out_ep: endpoint {
+						remote-endpoint = <&amx1_out_ep>;
+					};
+				};
+
+				xbar_amx2_in1_port: port@31 {
+					reg = <0x31>;
+
+					xbar_amx2_in1_ep: endpoint {
+						remote-endpoint = <&amx2_in1_ep>;
+					};
+				};
+
+				xbar_amx2_in2_port: port@32 {
+					reg = <0x32>;
+
+					xbar_amx2_in2_ep: endpoint {
+						remote-endpoint = <&amx2_in2_ep>;
+					};
+				};
+
+				xbar_amx2_in3_port: port@33 {
+					reg = <0x33>;
+
+					xbar_amx2_in3_ep: endpoint {
+						remote-endpoint = <&amx2_in3_ep>;
+					};
+				};
+
+				xbar_amx2_in4_port: port@34 {
+					reg = <0x34>;
+
+					xbar_amx2_in4_ep: endpoint {
+						remote-endpoint = <&amx2_in4_ep>;
+					};
+				};
+
+				port@35 {
+					reg = <0x35>;
+
+					xbar_amx2_out_ep: endpoint {
+						remote-endpoint = <&amx2_out_ep>;
+					};
+				};
+
+				xbar_amx3_in1_port: port@36 {
+					reg = <0x36>;
+
+					xbar_amx3_in1_ep: endpoint {
+						remote-endpoint = <&amx3_in1_ep>;
+					};
+				};
+
+				xbar_amx3_in2_port: port@37 {
+					reg = <0x37>;
+
+					xbar_amx3_in2_ep: endpoint {
+						remote-endpoint = <&amx3_in2_ep>;
+					};
+				};
+
+				xbar_amx3_in3_port: port@38 {
+					reg = <0x38>;
+
+					xbar_amx3_in3_ep: endpoint {
+						remote-endpoint = <&amx3_in3_ep>;
+					};
+				};
+
+				xbar_amx3_in4_port: port@39 {
+					reg = <0x39>;
+
+					xbar_amx3_in4_ep: endpoint {
+						remote-endpoint = <&amx3_in4_ep>;
+					};
+				};
+
+				port@3a {
+					reg = <0x3a>;
+
+					xbar_amx3_out_ep: endpoint {
+						remote-endpoint = <&amx3_out_ep>;
+					};
+				};
+
+				xbar_amx4_in1_port: port@3b {
+					reg = <0x3b>;
+
+					xbar_amx4_in1_ep: endpoint {
+						remote-endpoint = <&amx4_in1_ep>;
+					};
+				};
+
+				xbar_amx4_in2_port: port@3c {
+					reg = <0x3c>;
+
+					xbar_amx4_in2_ep: endpoint {
+						remote-endpoint = <&amx4_in2_ep>;
+					};
+				};
+
+				xbar_amx4_in3_port: port@3d {
+					reg = <0x3d>;
+
+					xbar_amx4_in3_ep: endpoint {
+						remote-endpoint = <&amx4_in3_ep>;
+					};
+				};
+
+				xbar_amx4_in4_port: port@3e {
+					reg = <0x3e>;
+
+					xbar_amx4_in4_ep: endpoint {
+						remote-endpoint = <&amx4_in4_ep>;
+					};
+				};
+
+				port@3f {
+					reg = <0x3f>;
+
+					xbar_amx4_out_ep: endpoint {
+						remote-endpoint = <&amx4_out_ep>;
+					};
+				};
+
+				xbar_adx1_in_port: port@40 {
+					reg = <0x40>;
+
+					xbar_adx1_in_ep: endpoint {
+						remote-endpoint = <&adx1_in_ep>;
+					};
+				};
+
+				port@41 {
+					reg = <0x41>;
+
+					xbar_adx1_out1_ep: endpoint {
+						remote-endpoint = <&adx1_out1_ep>;
+					};
+				};
+
+				port@42 {
+					reg = <0x42>;
+
+					xbar_adx1_out2_ep: endpoint {
+						remote-endpoint = <&adx1_out2_ep>;
+					};
+				};
+
+				port@43 {
+					reg = <0x43>;
+
+					xbar_adx1_out3_ep: endpoint {
+						remote-endpoint = <&adx1_out3_ep>;
+					};
+				};
+
+				port@44 {
+					reg = <0x44>;
+
+					xbar_adx1_out4_ep: endpoint {
+						remote-endpoint = <&adx1_out4_ep>;
+					};
+				};
+
+				xbar_adx2_in_port: port@45 {
+					reg = <0x45>;
+
+					xbar_adx2_in_ep: endpoint {
+						remote-endpoint = <&adx2_in_ep>;
+					};
+				};
+
+				port@46 {
+					reg = <0x46>;
+
+					xbar_adx2_out1_ep: endpoint {
+						remote-endpoint = <&adx2_out1_ep>;
+					};
+				};
+
+				port@47 {
+					reg = <0x47>;
+
+					xbar_adx2_out2_ep: endpoint {
+						remote-endpoint = <&adx2_out2_ep>;
+					};
+				};
+
+				port@48 {
+					reg = <0x48>;
+
+					xbar_adx2_out3_ep: endpoint {
+						remote-endpoint = <&adx2_out3_ep>;
+					};
+				};
+
+				port@49 {
+					reg = <0x49>;
+
+					xbar_adx2_out4_ep: endpoint {
+						remote-endpoint = <&adx2_out4_ep>;
+					};
+				};
+
+				xbar_adx3_in_port: port@4a {
+					reg = <0x4a>;
+
+					xbar_adx3_in_ep: endpoint {
+						remote-endpoint = <&adx3_in_ep>;
+					};
+				};
+
+				port@4b {
+					reg = <0x4b>;
+
+					xbar_adx3_out1_ep: endpoint {
+						remote-endpoint = <&adx3_out1_ep>;
+					};
+				};
+
+				port@4c {
+					reg = <0x4c>;
+
+					xbar_adx3_out2_ep: endpoint {
+						remote-endpoint = <&adx3_out2_ep>;
+					};
+				};
+
+				port@4d {
+					reg = <0x4d>;
+
+					xbar_adx3_out3_ep: endpoint {
+						remote-endpoint = <&adx3_out3_ep>;
+					};
+				};
+
+				port@4e {
+					reg = <0x4e>;
+
+					xbar_adx3_out4_ep: endpoint {
+						remote-endpoint = <&adx3_out4_ep>;
+					};
+				};
+
+				xbar_adx4_in_port: port@4f {
+					reg = <0x4f>;
+
+					xbar_adx4_in_ep: endpoint {
+						remote-endpoint = <&adx4_in_ep>;
+					};
+				};
+
+				port@50 {
+					reg = <0x50>;
+
+					xbar_adx4_out1_ep: endpoint {
+						remote-endpoint = <&adx4_out1_ep>;
+					};
+				};
+
+				port@51 {
+					reg = <0x51>;
+
+					xbar_adx4_out2_ep: endpoint {
+						remote-endpoint = <&adx4_out2_ep>;
+					};
+				};
+
+				port@52 {
+					reg = <0x52>;
+
+					xbar_adx4_out3_ep: endpoint {
+						remote-endpoint = <&adx4_out3_ep>;
+					};
+				};
+
+				port@53 {
+					reg = <0x53>;
+
+					xbar_adx4_out4_ep: endpoint {
+						remote-endpoint = <&adx4_out4_ep>;
+					};
+				};
+
+				xbar_mixer_in1_port: port@54 {
+					reg = <0x54>;
+
+					xbar_mixer_in1_ep: endpoint {
+						remote-endpoint = <&mixer_in1_ep>;
+					};
+				};
+
+				xbar_mixer_in2_port: port@55 {
+					reg = <0x55>;
+
+					xbar_mixer_in2_ep: endpoint {
+						remote-endpoint = <&mixer_in2_ep>;
+					};
+				};
+
+				xbar_mixer_in3_port: port@56 {
+					reg = <0x56>;
+
+					xbar_mixer_in3_ep: endpoint {
+						remote-endpoint = <&mixer_in3_ep>;
+					};
+				};
+
+				xbar_mixer_in4_port: port@57 {
+					reg = <0x57>;
+
+					xbar_mixer_in4_ep: endpoint {
+						remote-endpoint = <&mixer_in4_ep>;
+					};
+				};
+
+				xbar_mixer_in5_port: port@58 {
+					reg = <0x58>;
+
+					xbar_mixer_in5_ep: endpoint {
+						remote-endpoint = <&mixer_in5_ep>;
+					};
+				};
+
+				xbar_mixer_in6_port: port@59 {
+					reg = <0x59>;
+
+					xbar_mixer_in6_ep: endpoint {
+						remote-endpoint = <&mixer_in6_ep>;
+					};
+				};
+
+				xbar_mixer_in7_port: port@5a {
+					reg = <0x5a>;
+
+					xbar_mixer_in7_ep: endpoint {
+						remote-endpoint = <&mixer_in7_ep>;
+					};
+				};
+
+				xbar_mixer_in8_port: port@5b {
+					reg = <0x5b>;
+
+					xbar_mixer_in8_ep: endpoint {
+						remote-endpoint = <&mixer_in8_ep>;
+					};
+				};
+
+				xbar_mixer_in9_port: port@5c {
+					reg = <0x5c>;
+
+					xbar_mixer_in9_ep: endpoint {
+						remote-endpoint = <&mixer_in9_ep>;
+					};
+				};
+
+				xbar_mixer_in10_port: port@5d {
+					reg = <0x5d>;
+
+					xbar_mixer_in10_ep: endpoint {
+						remote-endpoint = <&mixer_in10_ep>;
+					};
+				};
+
+				port@5e {
+					reg = <0x5e>;
+
+					xbar_mixer_out1_ep: endpoint {
+						remote-endpoint = <&mixer_out1_ep>;
+					};
+				};
+
+				port@5f {
+					reg = <0x5f>;
+
+					xbar_mixer_out2_ep: endpoint {
+						remote-endpoint = <&mixer_out2_ep>;
+					};
+				};
+
+				port@60 {
+					reg = <0x60>;
+
+					xbar_mixer_out3_ep: endpoint {
+						remote-endpoint = <&mixer_out3_ep>;
+					};
+				};
+
+				port@61 {
+					reg = <0x61>;
+
+					xbar_mixer_out4_ep: endpoint {
+						remote-endpoint = <&mixer_out4_ep>;
+					};
+				};
+
+				port@62 {
+					reg = <0x62>;
+
+					xbar_mixer_out5_ep: endpoint {
+						remote-endpoint = <&mixer_out5_ep>;
+					};
+				};
+			};
+
+			admaif@290f000 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					admaif0_port: port@0 {
+						reg = <0x0>;
+
+						admaif0_ep: endpoint {
+							remote-endpoint = <&xbar_admaif0_ep>;
+						};
+					};
+
+					admaif1_port: port@1 {
+						reg = <0x1>;
+
+						admaif1_ep: endpoint {
+							remote-endpoint = <&xbar_admaif1_ep>;
+						};
+					};
+
+					admaif2_port: port@2 {
+						reg = <0x2>;
+
+						admaif2_ep: endpoint {
+							remote-endpoint = <&xbar_admaif2_ep>;
+						};
+					};
+
+					admaif3_port: port@3 {
+						reg = <0x3>;
+
+						admaif3_ep: endpoint {
+							remote-endpoint = <&xbar_admaif3_ep>;
+						};
+					};
+
+					admaif4_port: port@4 {
+						reg = <0x4>;
+
+						admaif4_ep: endpoint {
+							remote-endpoint = <&xbar_admaif4_ep>;
+						};
+					};
+
+					admaif5_port: port@5 {
+						reg = <0x5>;
+
+						admaif5_ep: endpoint {
+							remote-endpoint = <&xbar_admaif5_ep>;
+						};
+					};
+
+					admaif6_port: port@6 {
+						reg = <0x6>;
+
+						admaif6_ep: endpoint {
+							remote-endpoint = <&xbar_admaif6_ep>;
+						};
+					};
+
+					admaif7_port: port@7 {
+						reg = <0x7>;
+
+						admaif7_ep: endpoint {
+							remote-endpoint = <&xbar_admaif7_ep>;
+						};
+					};
+
+					admaif8_port: port@8 {
+						reg = <0x8>;
+
+						admaif8_ep: endpoint {
+							remote-endpoint = <&xbar_admaif8_ep>;
+						};
+					};
+
+					admaif9_port: port@9 {
+						reg = <0x9>;
+
+						admaif9_ep: endpoint {
+							remote-endpoint = <&xbar_admaif9_ep>;
+						};
+					};
+
+					admaif10_port: port@a {
+						reg = <0xa>;
+
+						admaif10_ep: endpoint {
+							remote-endpoint = <&xbar_admaif10_ep>;
+						};
+					};
+
+					admaif11_port: port@b {
+						reg = <0xb>;
+
+						admaif11_ep: endpoint {
+							remote-endpoint = <&xbar_admaif11_ep>;
+						};
+					};
+
+					admaif12_port: port@c {
+						reg = <0xc>;
+
+						admaif12_ep: endpoint {
+							remote-endpoint = <&xbar_admaif12_ep>;
+						};
+					};
+
+					admaif13_port: port@d {
+						reg = <0xd>;
+
+						admaif13_ep: endpoint {
+							remote-endpoint = <&xbar_admaif13_ep>;
+						};
+					};
+
+					admaif14_port: port@e {
+						reg = <0xe>;
+
+						admaif14_ep: endpoint {
+							remote-endpoint = <&xbar_admaif14_ep>;
+						};
+					};
+
+					admaif15_port: port@f {
+						reg = <0xf>;
+
+						admaif15_ep: endpoint {
+							remote-endpoint = <&xbar_admaif15_ep>;
+						};
+					};
+
+					admaif16_port: port@10 {
+						reg = <0x10>;
+
+						admaif16_ep: endpoint {
+							remote-endpoint = <&xbar_admaif16_ep>;
+						};
+					};
+
+					admaif17_port: port@11 {
+						reg = <0x11>;
+
+						admaif17_ep: endpoint {
+							remote-endpoint = <&xbar_admaif17_ep>;
+						};
+					};
+
+					admaif18_port: port@12 {
+						reg = <0x12>;
+
+						admaif18_ep: endpoint {
+							remote-endpoint = <&xbar_admaif18_ep>;
+						};
+					};
+
+					admaif19_port: port@13 {
+						reg = <0x13>;
+
+						admaif19_ep: endpoint {
+							remote-endpoint = <&xbar_admaif19_ep>;
+						};
+					};
+				};
+			};
+
+			i2s@2901000 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						i2s1_cif_ep: endpoint {
+							remote-endpoint = <&xbar_i2s1_ep>;
+						};
+					};
+
+					i2s1_port: port@1 {
+						reg = <1>;
+
+						i2s1_dap_ep: endpoint {
+							dai-format = "i2s";
+							/* Placeholder for external Codec */
+						};
+					};
+				};
+			};
+
+			i2s@2901100 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						i2s2_cif_ep: endpoint {
+							remote-endpoint = <&xbar_i2s2_ep>;
+						};
+					};
+
+					i2s2_port: port@1 {
+						reg = <1>;
+
+						i2s2_dap_ep: endpoint {
+							dai-format = "i2s";
+							/* Placeholder for external Codec */
+						};
+					};
+				};
+			};
+
+			i2s@2901200 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						i2s3_cif_ep: endpoint {
+							remote-endpoint = <&xbar_i2s3_ep>;
+						};
+					};
+
+					i2s3_port: port@1 {
+						reg = <1>;
+
+						i2s3_dap_ep: endpoint {
+							dai-format = "i2s";
+							/* Placeholder for external Codec */
+						};
+					};
+				};
 			};
 
-			admaif@290f000 {
+			i2s@2901300 {
 				status = "okay";
 
 				ports {
 					#address-cells = <1>;
 					#size-cells = <0>;
 
-					admaif0_port: port@0 {
-						reg = <0x0>;
+					port@0 {
+						reg = <0>;
 
-						admaif0_ep: endpoint {
-							remote-endpoint = <&xbar_admaif0_ep>;
+						i2s4_cif_ep: endpoint {
+							remote-endpoint = <&xbar_i2s4_ep>;
 						};
 					};
 
-					admaif1_port: port@1 {
-						reg = <0x1>;
+					i2s4_port: port@1 {
+						reg = <1>;
 
-						admaif1_ep: endpoint {
-							remote-endpoint = <&xbar_admaif1_ep>;
+						i2s4_dap_ep: endpoint {
+							dai-format = "i2s";
+							/* Placeholder for external Codec */
 						};
 					};
+				};
+			};
 
-					admaif2_port: port@2 {
-						reg = <0x2>;
+			i2s@2901400 {
+				status = "okay";
 
-						admaif2_ep: endpoint {
-							remote-endpoint = <&xbar_admaif2_ep>;
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						i2s5_cif_ep: endpoint {
+							remote-endpoint = <&xbar_i2s5_ep>;
 						};
 					};
 
-					admaif3_port: port@3 {
-						reg = <0x3>;
+					i2s5_port: port@1 {
+						reg = <1>;
 
-						admaif3_ep: endpoint {
-							remote-endpoint = <&xbar_admaif3_ep>;
+						i2s5_dap_ep: endpoint {
+							dai-format = "i2s";
+							/* Placeholder for external Codec */
 						};
 					};
+				};
+			};
 
-					admaif4_port: port@4 {
-						reg = <0x4>;
+			i2s@2901500 {
+				status = "okay";
 
-						admaif4_ep: endpoint {
-							remote-endpoint = <&xbar_admaif4_ep>;
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						i2s6_cif_ep: endpoint {
+							remote-endpoint = <&xbar_i2s6_ep>;
 						};
 					};
 
-					admaif5_port: port@5 {
-						reg = <0x5>;
+					i2s6_port: port@1 {
+						reg = <1>;
 
-						admaif5_ep: endpoint {
-							remote-endpoint = <&xbar_admaif5_ep>;
+						i2s6_dap_ep: endpoint {
+							dai-format = "i2s";
+							/* Placeholder for external Codec */
 						};
 					};
+				};
+			};
 
-					admaif6_port: port@6 {
-						reg = <0x6>;
+			dmic@2904000 {
+				status = "okay";
 
-						admaif6_ep: endpoint {
-							remote-endpoint = <&xbar_admaif6_ep>;
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						dmic1_cif_ep: endpoint {
+							remote-endpoint = <&xbar_dmic1_ep>;
 						};
 					};
 
-					admaif7_port: port@7 {
-						reg = <0x7>;
+					dmic1_port: port@1 {
+						reg = <1>;
 
-						admaif7_ep: endpoint {
-							remote-endpoint = <&xbar_admaif7_ep>;
+						dmic1_dap_ep: endpoint {
+							/* Place holder for external Codec */
 						};
 					};
+				};
+			};
 
-					admaif8_port: port@8 {
-						reg = <0x8>;
+			dmic@2904100 {
+				status = "okay";
 
-						admaif8_ep: endpoint {
-							remote-endpoint = <&xbar_admaif8_ep>;
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						dmic2_cif_ep: endpoint {
+							remote-endpoint = <&xbar_dmic2_ep>;
 						};
 					};
 
-					admaif9_port: port@9 {
-						reg = <0x9>;
+					dmic2_port: port@1 {
+						reg = <1>;
 
-						admaif9_ep: endpoint {
-							remote-endpoint = <&xbar_admaif9_ep>;
+						dmic2_dap_ep: endpoint {
+							/* Place holder for external Codec */
 						};
 					};
+				};
+			};
 
-					admaif10_port: port@a {
-						reg = <0xa>;
+			dmic@2904200 {
+				status = "okay";
 
-						admaif10_ep: endpoint {
-							remote-endpoint = <&xbar_admaif10_ep>;
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						dmic3_cif_ep: endpoint {
+							remote-endpoint = <&xbar_dmic3_ep>;
 						};
 					};
 
-					admaif11_port: port@b {
-						reg = <0xb>;
+					dmic3_port: port@1 {
+						reg = <1>;
 
-						admaif11_ep: endpoint {
-							remote-endpoint = <&xbar_admaif11_ep>;
+						dmic3_dap_ep: endpoint {
+							/* Place holder for external Codec */
 						};
 					};
+				};
+			};
 
-					admaif12_port: port@c {
-						reg = <0xc>;
+			dspk@2905000 {
+				status = "okay";
 
-						admaif12_ep: endpoint {
-							remote-endpoint = <&xbar_admaif12_ep>;
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						dspk1_cif_ep: endpoint {
+							remote-endpoint = <&xbar_dspk1_ep>;
 						};
 					};
 
-					admaif13_port: port@d {
-						reg = <0xd>;
+					dspk1_port: port@1 {
+						reg = <1>;
 
-						admaif13_ep: endpoint {
-							remote-endpoint = <&xbar_admaif13_ep>;
+						dspk1_dap_ep: endpoint {
+							/* Place holder for external Codec */
 						};
 					};
+				};
+			};
 
-					admaif14_port: port@e {
-						reg = <0xe>;
+			dspk@2905100 {
+				status = "okay";
 
-						admaif14_ep: endpoint {
-							remote-endpoint = <&xbar_admaif14_ep>;
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						dspk2_cif_ep: endpoint {
+							remote-endpoint = <&xbar_dspk2_ep>;
 						};
 					};
 
-					admaif15_port: port@f {
-						reg = <0xf>;
+					dspk2_port: port@1 {
+						reg = <1>;
 
-						admaif15_ep: endpoint {
-							remote-endpoint = <&xbar_admaif15_ep>;
+						dspk2_dap_ep: endpoint {
+							/* Place holder for external Codec */
 						};
 					};
+				};
+			};
 
-					admaif16_port: port@10 {
-						reg = <0x10>;
+			sfc@2902000 {
+				status = "okay";
 
-						admaif16_ep: endpoint {
-							remote-endpoint = <&xbar_admaif16_ep>;
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc1_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc1_in_ep>;
+							convert-rate = <44100>;
 						};
 					};
 
-					admaif17_port: port@11 {
-						reg = <0x11>;
+					sfc1_out_port: port@1 {
+						reg = <1>;
 
-						admaif17_ep: endpoint {
-							remote-endpoint = <&xbar_admaif17_ep>;
+						sfc1_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc1_out_ep>;
+							convert-rate = <48000>;
+						};
+					};
+				};
+			};
+
+			sfc@2902200 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc2_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc2_in_ep>;
+						};
+					};
+
+					sfc2_out_port: port@1 {
+						reg = <1>;
+
+						sfc2_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc2_out_ep>;
+						};
+					};
+				};
+			};
+
+			sfc@2902400 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc3_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc3_in_ep>;
+						};
+					};
+
+					sfc3_out_port: port@1 {
+						reg = <1>;
+
+						sfc3_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc3_out_ep>;
 						};
 					};
+				};
+			};
 
-					admaif18_port: port@12 {
-						reg = <0x12>;
+			sfc@2902600 {
+				status = "okay";
 
-						admaif18_ep: endpoint {
-							remote-endpoint = <&xbar_admaif18_ep>;
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc4_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc4_in_ep>;
 						};
 					};
 
-					admaif19_port: port@13 {
-						reg = <0x13>;
+					sfc4_out_port: port@1 {
+						reg = <1>;
 
-						admaif19_ep: endpoint {
-							remote-endpoint = <&xbar_admaif19_ep>;
+						sfc4_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc4_out_ep>;
 						};
 					};
 				};
 			};
 
-			i2s@2901000 {
+			mvc@290a000 {
 				status = "okay";
 
 				ports {
@@ -456,23 +1375,22 @@
 					port@0 {
 						reg = <0>;
 
-						i2s1_cif_ep: endpoint {
-							remote-endpoint = <&xbar_i2s1_ep>;
+						mvc1_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_mvc1_in_ep>;
 						};
 					};
 
-					i2s1_port: port@1 {
+					mvc1_out_port: port@1 {
 						reg = <1>;
 
-						i2s1_dap_ep: endpoint {
-							dai-format = "i2s";
-							/* Placeholder for external Codec */
+						mvc1_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_mvc1_out_ep>;
 						};
 					};
 				};
 			};
 
-			i2s@2901100 {
+			mvc@290a200 {
 				status = "okay";
 
 				ports {
@@ -482,23 +1400,22 @@
 					port@0 {
 						reg = <0>;
 
-						i2s2_cif_ep: endpoint {
-							remote-endpoint = <&xbar_i2s2_ep>;
+						mvc2_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_mvc2_in_ep>;
 						};
 					};
 
-					i2s2_port: port@1 {
+					mvc2_out_port: port@1 {
 						reg = <1>;
 
-						i2s2_dap_ep: endpoint {
-							dai-format = "i2s";
-							/* Placeholder for external Codec */
+						mvc2_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_mvc2_out_ep>;
 						};
 					};
 				};
 			};
 
-			i2s@2901200 {
+			amx@2903000 {
 				status = "okay";
 
 				ports {
@@ -508,23 +1425,46 @@
 					port@0 {
 						reg = <0>;
 
-						i2s3_cif_ep: endpoint {
-							remote-endpoint = <&xbar_i2s3_ep>;
+						amx1_in1_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in1_ep>;
 						};
 					};
 
-					i2s3_port: port@1 {
+					port@1 {
 						reg = <1>;
 
-						i2s3_dap_ep: endpoint {
-							dai-format = "i2s";
-							/* Placeholder for external Codec */
+						amx1_in2_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in2_ep>;
+						};
+					};
+
+					port@2 {
+						reg = <2>;
+
+						amx1_in3_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in3_ep>;
+						};
+					};
+
+					port@3 {
+						reg = <3>;
+
+						amx1_in4_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in4_ep>;
+						};
+					};
+
+					amx1_out_port: port@4 {
+						reg = <4>;
+
+						amx1_out_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_out_ep>;
 						};
 					};
 				};
 			};
 
-			i2s@2901300 {
+			amx@2903100 {
 				status = "okay";
 
 				ports {
@@ -534,23 +1474,46 @@
 					port@0 {
 						reg = <0>;
 
-						i2s4_cif_ep: endpoint {
-							remote-endpoint = <&xbar_i2s4_ep>;
+						amx2_in1_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in1_ep>;
 						};
 					};
 
-					i2s4_port: port@1 {
+					port@1 {
 						reg = <1>;
 
-						i2s4_dap_ep: endpoint {
-							dai-format = "i2s";
-							/* Placeholder for external Codec */
+						amx2_in2_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in2_ep>;
+						};
+					};
+
+					amx2_in3_port: port@2 {
+						reg = <2>;
+
+						amx2_in3_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in3_ep>;
+						};
+					};
+
+					amx2_in4_port: port@3 {
+						reg = <3>;
+
+						amx2_in4_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in4_ep>;
+						};
+					};
+
+					amx2_out_port: port@4 {
+						reg = <4>;
+
+						amx2_out_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_out_ep>;
 						};
 					};
 				};
 			};
 
-			i2s@2901400 {
+			amx@2903200 {
 				status = "okay";
 
 				ports {
@@ -560,23 +1523,46 @@
 					port@0 {
 						reg = <0>;
 
-						i2s5_cif_ep: endpoint {
-							remote-endpoint = <&xbar_i2s5_ep>;
+						amx3_in1_ep: endpoint {
+							remote-endpoint = <&xbar_amx3_in1_ep>;
 						};
 					};
 
-					i2s5_port: port@1 {
+					port@1 {
 						reg = <1>;
 
-						i2s5_dap_ep: endpoint {
-							dai-format = "i2s";
-							/* Placeholder for external Codec */
+						amx3_in2_ep: endpoint {
+							remote-endpoint = <&xbar_amx3_in2_ep>;
+						};
+					};
+
+					port@2 {
+						reg = <2>;
+
+						amx3_in3_ep: endpoint {
+							remote-endpoint = <&xbar_amx3_in3_ep>;
+						};
+					};
+
+					port@3 {
+						reg = <3>;
+
+						amx3_in4_ep: endpoint {
+							remote-endpoint = <&xbar_amx3_in4_ep>;
+						};
+					};
+
+					amx3_out_port: port@4 {
+						reg = <4>;
+
+						amx3_out_ep: endpoint {
+							remote-endpoint = <&xbar_amx3_out_ep>;
 						};
 					};
 				};
 			};
 
-			i2s@2901500 {
+			amx@2903300 {
 				status = "okay";
 
 				ports {
@@ -586,23 +1572,46 @@
 					port@0 {
 						reg = <0>;
 
-						i2s6_cif_ep: endpoint {
-							remote-endpoint = <&xbar_i2s6_ep>;
+						amx4_in1_ep: endpoint {
+							remote-endpoint = <&xbar_amx4_in1_ep>;
 						};
 					};
 
-					i2s6_port: port@1 {
+					port@1 {
 						reg = <1>;
 
-						i2s6_dap_ep: endpoint {
-							dai-format = "i2s";
-							/* Placeholder for external Codec */
+						amx4_in2_ep: endpoint {
+							remote-endpoint = <&xbar_amx4_in2_ep>;
+						};
+					};
+
+					port@2 {
+						reg = <2>;
+
+						amx4_in3_ep: endpoint {
+							remote-endpoint = <&xbar_amx4_in3_ep>;
+						};
+					};
+
+					port@3 {
+						reg = <3>;
+
+						amx4_in4_ep: endpoint {
+							remote-endpoint = <&xbar_amx4_in4_ep>;
+						};
+					};
+
+					amx4_out_port: port@4 {
+						reg = <4>;
+
+						amx4_out_ep: endpoint {
+							remote-endpoint = <&xbar_amx4_out_ep>;
 						};
 					};
 				};
 			};
 
-			dmic@2904000 {
+			adx@2903800 {
 				status = "okay";
 
 				ports {
@@ -612,22 +1621,46 @@
 					port@0 {
 						reg = <0>;
 
-						dmic1_cif_ep: endpoint {
-							remote-endpoint = <&xbar_dmic1_ep>;
+						adx1_in_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_in_ep>;
 						};
 					};
 
-					dmic1_port: port@1 {
+					adx1_out1_port: port@1 {
 						reg = <1>;
 
-						dmic1_dap_ep: endpoint {
-							/* Place holder for external Codec */
+						adx1_out1_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out1_ep>;
+						};
+					};
+
+					adx1_out2_port: port@2 {
+						reg = <2>;
+
+						adx1_out2_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out2_ep>;
+						};
+					};
+
+					adx1_out3_port: port@3 {
+						reg = <3>;
+
+						adx1_out3_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out3_ep>;
+						};
+					};
+
+					adx1_out4_port: port@4 {
+						reg = <4>;
+
+						adx1_out4_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out4_ep>;
 						};
 					};
 				};
 			};
 
-			dmic@2904100 {
+			adx@2903900 {
 				status = "okay";
 
 				ports {
@@ -637,22 +1670,46 @@
 					port@0 {
 						reg = <0>;
 
-						dmic2_cif_ep: endpoint {
-							remote-endpoint = <&xbar_dmic2_ep>;
+						adx2_in_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_in_ep>;
 						};
 					};
 
-					dmic2_port: port@1 {
+					adx2_out1_port: port@1 {
 						reg = <1>;
 
-						dmic2_dap_ep: endpoint {
-							/* Place holder for external Codec */
+						adx2_out1_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out1_ep>;
+						};
+					};
+
+					adx2_out2_port: port@2 {
+						reg = <2>;
+
+						adx2_out2_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out2_ep>;
+						};
+					};
+
+					adx2_out3_port: port@3 {
+						reg = <3>;
+
+						adx2_out3_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out3_ep>;
+						};
+					};
+
+					adx2_out4_port: port@4 {
+						reg = <4>;
+
+						adx2_out4_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out4_ep>;
 						};
 					};
 				};
 			};
 
-			dmic@2904200 {
+			adx@2903a00 {
 				status = "okay";
 
 				ports {
@@ -662,22 +1719,46 @@
 					port@0 {
 						reg = <0>;
 
-						dmic3_cif_ep: endpoint {
-							remote-endpoint = <&xbar_dmic3_ep>;
+						adx3_in_ep: endpoint {
+							remote-endpoint = <&xbar_adx3_in_ep>;
 						};
 					};
 
-					dmic3_port: port@1 {
+					adx3_out1_port: port@1 {
 						reg = <1>;
 
-						dmic3_dap_ep: endpoint {
-							/* Place holder for external Codec */
+						adx3_out1_ep: endpoint {
+							remote-endpoint = <&xbar_adx3_out1_ep>;
+						};
+					};
+
+					adx3_out2_port: port@2 {
+						reg = <2>;
+
+						adx3_out2_ep: endpoint {
+							remote-endpoint = <&xbar_adx3_out2_ep>;
+						};
+					};
+
+					adx3_out3_port: port@3 {
+						reg = <3>;
+
+						adx3_out3_ep: endpoint {
+							remote-endpoint = <&xbar_adx3_out3_ep>;
+						};
+					};
+
+					adx3_out4_port: port@4 {
+						reg = <4>;
+
+						adx3_out4_ep: endpoint {
+							remote-endpoint = <&xbar_adx3_out4_ep>;
 						};
 					};
 				};
 			};
 
-			dspk@2905000 {
+			adx@2903b00 {
 				status = "okay";
 
 				ports {
@@ -687,22 +1768,46 @@
 					port@0 {
 						reg = <0>;
 
-						dspk1_cif_ep: endpoint {
-							remote-endpoint = <&xbar_dspk1_ep>;
+						adx4_in_ep: endpoint {
+							remote-endpoint = <&xbar_adx4_in_ep>;
 						};
 					};
 
-					dspk1_port: port@1 {
+					adx4_out1_port: port@1 {
 						reg = <1>;
 
-						dspk1_dap_ep: endpoint {
-							/* Place holder for external Codec */
+						adx4_out1_ep: endpoint {
+							remote-endpoint = <&xbar_adx4_out1_ep>;
+						};
+					};
+
+					adx4_out2_port: port@2 {
+						reg = <2>;
+
+						adx4_out2_ep: endpoint {
+							remote-endpoint = <&xbar_adx4_out2_ep>;
+						};
+					};
+
+					adx4_out3_port: port@3 {
+						reg = <3>;
+
+						adx4_out3_ep: endpoint {
+							remote-endpoint = <&xbar_adx4_out3_ep>;
+						};
+					};
+
+					adx4_out4_port: port@4 {
+						reg = <4>;
+
+						adx4_out4_ep: endpoint {
+							remote-endpoint = <&xbar_adx4_out4_ep>;
 						};
 					};
 				};
 			};
 
-			dspk@2905100 {
+			amixer@290bb00 {
 				status = "okay";
 
 				ports {
@@ -710,18 +1815,122 @@
 					#size-cells = <0>;
 
 					port@0 {
-						reg = <0>;
+						reg = <0x0>;
 
-						dspk2_cif_ep: endpoint {
-							remote-endpoint = <&xbar_dspk2_ep>;
+						mixer_in1_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in1_ep>;
 						};
 					};
 
-					dspk2_port: port@1 {
-						reg = <1>;
+					port@1 {
+						reg = <0x1>;
 
-						dspk2_dap_ep: endpoint {
-							/* Place holder for external Codec */
+						mixer_in2_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in2_ep>;
+						};
+					};
+
+					port@2 {
+						reg = <0x2>;
+
+						mixer_in3_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in3_ep>;
+						};
+					};
+
+					port@3 {
+						reg = <0x3>;
+
+						mixer_in4_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in4_ep>;
+						};
+					};
+
+					port@4 {
+						reg = <0x4>;
+
+						mixer_in5_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in5_ep>;
+						};
+					};
+
+					port@5 {
+						reg = <0x5>;
+
+						mixer_in6_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in6_ep>;
+						};
+					};
+
+					port@6 {
+						reg = <0x6>;
+
+						mixer_in7_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in7_ep>;
+						};
+					};
+
+					port@7 {
+						reg = <0x7>;
+
+						mixer_in8_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in8_ep>;
+						};
+					};
+
+					port@8 {
+						reg = <0x8>;
+
+						mixer_in9_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in9_ep>;
+						};
+					};
+
+					port@9 {
+						reg = <0x9>;
+
+						mixer_in10_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in10_ep>;
+						};
+					};
+
+					mixer_out1_port: port@a {
+						reg = <0xa>;
+
+						mixer_out1_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out1_ep>;
+						};
+					};
+
+					mixer_out2_port: port@b {
+						reg = <0xb>;
+
+						mixer_out2_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out2_ep>;
+						};
+					};
+
+					mixer_out3_port: port@c {
+						reg = <0xc>;
+
+						mixer_out3_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out3_ep>;
+						};
+					};
+
+					mixer_out4_port: port@d {
+						reg = <0xd>;
+
+						mixer_out4_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out4_ep>;
+						};
+					};
+
+					mixer_out5_port: port@e {
+						reg = <0xe>;
+
+						mixer_out5_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out5_ep>;
 						};
 					};
 				};
@@ -1104,6 +2313,41 @@
 		       <&xbar_i2s4_port>, <&xbar_i2s5_port>, <&xbar_i2s6_port>,
 		       <&xbar_dmic1_port>, <&xbar_dmic2_port>, <&xbar_dmic3_port>,
 		       <&xbar_dspk1_port>, <&xbar_dspk2_port>,
+		       <&xbar_sfc1_in_port>, <&xbar_sfc2_in_port>,
+		       <&xbar_sfc3_in_port>, <&xbar_sfc4_in_port>,
+		       <&xbar_mvc1_in_port>, <&xbar_mvc2_in_port>,
+		       <&xbar_amx1_in1_port>, <&xbar_amx1_in2_port>,
+		       <&xbar_amx1_in3_port>, <&xbar_amx1_in4_port>,
+		       <&xbar_amx2_in1_port>, <&xbar_amx2_in2_port>,
+		       <&xbar_amx2_in3_port>, <&xbar_amx2_in4_port>,
+		       <&xbar_amx3_in1_port>, <&xbar_amx3_in2_port>,
+		       <&xbar_amx3_in3_port>, <&xbar_amx3_in4_port>,
+		       <&xbar_amx4_in1_port>, <&xbar_amx4_in2_port>,
+		       <&xbar_amx4_in3_port>, <&xbar_amx4_in4_port>,
+		       <&xbar_adx1_in_port>, <&xbar_adx2_in_port>,
+		       <&xbar_adx3_in_port>, <&xbar_adx4_in_port>,
+		       <&xbar_mixer_in1_port>, <&xbar_mixer_in2_port>,
+		       <&xbar_mixer_in3_port>, <&xbar_mixer_in4_port>,
+		       <&xbar_mixer_in5_port>, <&xbar_mixer_in6_port>,
+		       <&xbar_mixer_in7_port>, <&xbar_mixer_in8_port>,
+		       <&xbar_mixer_in9_port>, <&xbar_mixer_in10_port>,
+		       /* HW accelerators */
+		       <&sfc1_out_port>, <&sfc2_out_port>,
+		       <&sfc3_out_port>, <&sfc4_out_port>,
+		       <&mvc1_out_port>, <&mvc2_out_port>,
+		       <&amx1_out_port>, <&amx2_out_port>,
+		       <&amx3_out_port>, <&amx4_out_port>,
+		       <&adx1_out1_port>, <&adx1_out2_port>,
+		       <&adx1_out3_port>, <&adx1_out4_port>,
+		       <&adx2_out1_port>, <&adx2_out2_port>,
+		       <&adx2_out3_port>, <&adx2_out4_port>,
+		       <&adx3_out1_port>, <&adx3_out2_port>,
+		       <&adx3_out3_port>, <&adx3_out4_port>,
+		       <&adx4_out1_port>, <&adx4_out2_port>,
+		       <&adx4_out3_port>, <&adx4_out4_port>,
+		       <&mixer_out1_port>, <&mixer_out2_port>,
+		       <&mixer_out3_port>, <&mixer_out4_port>,
+		       <&mixer_out5_port>,
 		       /* I/O */
 		       <&i2s1_port>, <&i2s2_port>, <&i2s3_port>, <&i2s4_port>,
 		       <&i2s5_port>, <&i2s6_port>, <&dmic1_port>, <&dmic2_port>,
diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p2972-0000.dts b/arch/arm64/boot/dts/nvidia/tegra194-p2972-0000.dts
index 96bd01c..fab34d6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194-p2972-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra194-p2972-0000.dts
@@ -228,178 +228,1238 @@
 							remote-endpoint = <&dmic3_cif_ep>;
 						};
 					};
+
+					xbar_sfc1_in_port: port@20 {
+						reg = <0x20>;
+
+						xbar_sfc1_in_ep: endpoint {
+							remote-endpoint = <&sfc1_cif_in_ep>;
+						};
+					};
+
+					port@21 {
+						reg = <0x21>;
+
+						xbar_sfc1_out_ep: endpoint {
+							remote-endpoint = <&sfc1_cif_out_ep>;
+						};
+					};
+
+					xbar_sfc2_in_port: port@22 {
+						reg = <0x22>;
+
+						xbar_sfc2_in_ep: endpoint {
+							remote-endpoint = <&sfc2_cif_in_ep>;
+						};
+					};
+
+					port@23 {
+						reg = <0x23>;
+
+						xbar_sfc2_out_ep: endpoint {
+							remote-endpoint = <&sfc2_cif_out_ep>;
+						};
+					};
+
+					xbar_sfc3_in_port: port@24 {
+						reg = <0x24>;
+
+						xbar_sfc3_in_ep: endpoint {
+							remote-endpoint = <&sfc3_cif_in_ep>;
+						};
+					};
+
+					port@25 {
+						reg = <0x25>;
+
+						xbar_sfc3_out_ep: endpoint {
+							remote-endpoint = <&sfc3_cif_out_ep>;
+						};
+					};
+
+					xbar_sfc4_in_port: port@26 {
+						reg = <0x26>;
+
+						xbar_sfc4_in_ep: endpoint {
+							remote-endpoint = <&sfc4_cif_in_ep>;
+						};
+					};
+
+					port@27 {
+						reg = <0x27>;
+
+						xbar_sfc4_out_ep: endpoint {
+							remote-endpoint = <&sfc4_cif_out_ep>;
+						};
+					};
+
+					xbar_mvc1_in_port: port@28 {
+						reg = <0x28>;
+
+						xbar_mvc1_in_ep: endpoint {
+							remote-endpoint = <&mvc1_cif_in_ep>;
+						};
+					};
+
+					port@29 {
+						reg = <0x29>;
+
+						xbar_mvc1_out_ep: endpoint {
+							remote-endpoint = <&mvc1_cif_out_ep>;
+						};
+					};
+
+					xbar_mvc2_in_port: port@2a {
+						reg = <0x2a>;
+
+						xbar_mvc2_in_ep: endpoint {
+							remote-endpoint = <&mvc2_cif_in_ep>;
+						};
+					};
+
+					port@2b {
+						reg = <0x2b>;
+
+						xbar_mvc2_out_ep: endpoint {
+							remote-endpoint = <&mvc2_cif_out_ep>;
+						};
+					};
+
+					xbar_amx1_in1_port: port@2c {
+						reg = <0x2c>;
+
+						xbar_amx1_in1_ep: endpoint {
+							remote-endpoint = <&amx1_in1_ep>;
+						};
+					};
+
+					xbar_amx1_in2_port: port@2d {
+						reg = <0x2d>;
+
+						xbar_amx1_in2_ep: endpoint {
+							remote-endpoint = <&amx1_in2_ep>;
+						};
+					};
+
+					xbar_amx1_in3_port: port@2e {
+						reg = <0x2e>;
+
+						xbar_amx1_in3_ep: endpoint {
+							remote-endpoint = <&amx1_in3_ep>;
+						};
+					};
+
+					xbar_amx1_in4_port: port@2f {
+						reg = <0x2f>;
+
+						xbar_amx1_in4_ep: endpoint {
+							remote-endpoint = <&amx1_in4_ep>;
+						};
+					};
+
+					port@30 {
+						reg = <0x30>;
+
+						xbar_amx1_out_ep: endpoint {
+							remote-endpoint = <&amx1_out_ep>;
+						};
+					};
+
+					xbar_amx2_in1_port: port@31 {
+						reg = <0x31>;
+
+						xbar_amx2_in1_ep: endpoint {
+							remote-endpoint = <&amx2_in1_ep>;
+						};
+					};
+
+					xbar_amx2_in2_port: port@32 {
+						reg = <0x32>;
+
+						xbar_amx2_in2_ep: endpoint {
+							remote-endpoint = <&amx2_in2_ep>;
+						};
+					};
+
+					xbar_amx2_in3_port: port@33 {
+						reg = <0x33>;
+
+						xbar_amx2_in3_ep: endpoint {
+							remote-endpoint = <&amx2_in3_ep>;
+						};
+					};
+
+					xbar_amx2_in4_port: port@34 {
+						reg = <0x34>;
+
+						xbar_amx2_in4_ep: endpoint {
+							remote-endpoint = <&amx2_in4_ep>;
+						};
+					};
+
+					port@35 {
+						reg = <0x35>;
+
+						xbar_amx2_out_ep: endpoint {
+							remote-endpoint = <&amx2_out_ep>;
+						};
+					};
+
+					xbar_amx3_in1_port: port@36 {
+						reg = <0x36>;
+
+						xbar_amx3_in1_ep: endpoint {
+							remote-endpoint = <&amx3_in1_ep>;
+						};
+					};
+
+					xbar_amx3_in2_port: port@37 {
+						reg = <0x37>;
+
+						xbar_amx3_in2_ep: endpoint {
+							remote-endpoint = <&amx3_in2_ep>;
+						};
+					};
+
+					xbar_amx3_in3_port: port@38 {
+						reg = <0x38>;
+
+						xbar_amx3_in3_ep: endpoint {
+							remote-endpoint = <&amx3_in3_ep>;
+						};
+					};
+
+					xbar_amx3_in4_port: port@39 {
+						reg = <0x39>;
+
+						xbar_amx3_in4_ep: endpoint {
+							remote-endpoint = <&amx3_in4_ep>;
+						};
+					};
+
+					port@3a {
+						reg = <0x3a>;
+
+						xbar_amx3_out_ep: endpoint {
+							remote-endpoint = <&amx3_out_ep>;
+						};
+					};
+
+					xbar_amx4_in1_port: port@3b {
+						reg = <0x3b>;
+
+						xbar_amx4_in1_ep: endpoint {
+							remote-endpoint = <&amx4_in1_ep>;
+						};
+					};
+
+					xbar_amx4_in2_port: port@3c {
+						reg = <0x3c>;
+
+						xbar_amx4_in2_ep: endpoint {
+							remote-endpoint = <&amx4_in2_ep>;
+						};
+					};
+
+					xbar_amx4_in3_port: port@3d {
+						reg = <0x3d>;
+
+						xbar_amx4_in3_ep: endpoint {
+							remote-endpoint = <&amx4_in3_ep>;
+						};
+					};
+
+					xbar_amx4_in4_port: port@3e {
+						reg = <0x3e>;
+
+						xbar_amx4_in4_ep: endpoint {
+							remote-endpoint = <&amx4_in4_ep>;
+						};
+					};
+
+					port@3f {
+						reg = <0x3f>;
+
+						xbar_amx4_out_ep: endpoint {
+							remote-endpoint = <&amx4_out_ep>;
+						};
+					};
+
+					xbar_adx1_in_port: port@40 {
+						reg = <0x40>;
+
+						xbar_adx1_in_ep: endpoint {
+							remote-endpoint = <&adx1_in_ep>;
+						};
+					};
+
+					port@41 {
+						reg = <0x41>;
+
+						xbar_adx1_out1_ep: endpoint {
+							remote-endpoint = <&adx1_out1_ep>;
+						};
+					};
+
+					port@42 {
+						reg = <0x42>;
+
+						xbar_adx1_out2_ep: endpoint {
+							remote-endpoint = <&adx1_out2_ep>;
+						};
+					};
+
+					port@43 {
+						reg = <0x43>;
+
+						xbar_adx1_out3_ep: endpoint {
+							remote-endpoint = <&adx1_out3_ep>;
+						};
+					};
+
+					port@44 {
+						reg = <0x44>;
+
+						xbar_adx1_out4_ep: endpoint {
+							remote-endpoint = <&adx1_out4_ep>;
+						};
+					};
+
+					xbar_adx2_in_port: port@45 {
+						reg = <0x45>;
+
+						xbar_adx2_in_ep: endpoint {
+							remote-endpoint = <&adx2_in_ep>;
+						};
+					};
+
+					port@46 {
+						reg = <0x46>;
+
+						xbar_adx2_out1_ep: endpoint {
+							remote-endpoint = <&adx2_out1_ep>;
+						};
+					};
+
+					port@47 {
+						reg = <0x47>;
+
+						xbar_adx2_out2_ep: endpoint {
+							remote-endpoint = <&adx2_out2_ep>;
+						};
+					};
+
+					port@48 {
+						reg = <0x48>;
+
+						xbar_adx2_out3_ep: endpoint {
+							remote-endpoint = <&adx2_out3_ep>;
+						};
+					};
+
+					port@49 {
+						reg = <0x49>;
+
+						xbar_adx2_out4_ep: endpoint {
+							remote-endpoint = <&adx2_out4_ep>;
+						};
+					};
+
+					xbar_adx3_in_port: port@4a {
+						reg = <0x4a>;
+
+						xbar_adx3_in_ep: endpoint {
+							remote-endpoint = <&adx3_in_ep>;
+						};
+					};
+
+					port@4b {
+						reg = <0x4b>;
+
+						xbar_adx3_out1_ep: endpoint {
+							remote-endpoint = <&adx3_out1_ep>;
+						};
+					};
+
+					port@4c {
+						reg = <0x4c>;
+
+						xbar_adx3_out2_ep: endpoint {
+							remote-endpoint = <&adx3_out2_ep>;
+						};
+					};
+
+					port@4d {
+						reg = <0x4d>;
+
+						xbar_adx3_out3_ep: endpoint {
+							remote-endpoint = <&adx3_out3_ep>;
+						};
+					};
+
+					port@4e {
+						reg = <0x4e>;
+
+						xbar_adx3_out4_ep: endpoint {
+							remote-endpoint = <&adx3_out4_ep>;
+						};
+					};
+
+					xbar_adx4_in_port: port@4f {
+						reg = <0x4f>;
+
+						xbar_adx4_in_ep: endpoint {
+							remote-endpoint = <&adx4_in_ep>;
+						};
+					};
+
+					port@50 {
+						reg = <0x50>;
+
+						xbar_adx4_out1_ep: endpoint {
+							remote-endpoint = <&adx4_out1_ep>;
+						};
+					};
+
+					port@51 {
+						reg = <0x51>;
+
+						xbar_adx4_out2_ep: endpoint {
+							remote-endpoint = <&adx4_out2_ep>;
+						};
+					};
+
+					port@52 {
+						reg = <0x52>;
+
+						xbar_adx4_out3_ep: endpoint {
+							remote-endpoint = <&adx4_out3_ep>;
+						};
+					};
+
+					port@53 {
+						reg = <0x53>;
+
+						xbar_adx4_out4_ep: endpoint {
+							remote-endpoint = <&adx4_out4_ep>;
+						};
+					};
+
+					xbar_mixer_in1_port: port@54 {
+						reg = <0x54>;
+
+						xbar_mixer_in1_ep: endpoint {
+							remote-endpoint = <&mixer_in1_ep>;
+						};
+					};
+
+					xbar_mixer_in2_port: port@55 {
+						reg = <0x55>;
+
+						xbar_mixer_in2_ep: endpoint {
+							remote-endpoint = <&mixer_in2_ep>;
+						};
+					};
+
+					xbar_mixer_in3_port: port@56 {
+						reg = <0x56>;
+
+						xbar_mixer_in3_ep: endpoint {
+							remote-endpoint = <&mixer_in3_ep>;
+						};
+					};
+
+					xbar_mixer_in4_port: port@57 {
+						reg = <0x57>;
+
+						xbar_mixer_in4_ep: endpoint {
+							remote-endpoint = <&mixer_in4_ep>;
+						};
+					};
+
+					xbar_mixer_in5_port: port@58 {
+						reg = <0x58>;
+
+						xbar_mixer_in5_ep: endpoint {
+							remote-endpoint = <&mixer_in5_ep>;
+						};
+					};
+
+					xbar_mixer_in6_port: port@59 {
+						reg = <0x59>;
+
+						xbar_mixer_in6_ep: endpoint {
+							remote-endpoint = <&mixer_in6_ep>;
+						};
+					};
+
+					xbar_mixer_in7_port: port@5a {
+						reg = <0x5a>;
+
+						xbar_mixer_in7_ep: endpoint {
+							remote-endpoint = <&mixer_in7_ep>;
+						};
+					};
+
+					xbar_mixer_in8_port: port@5b {
+						reg = <0x5b>;
+
+						xbar_mixer_in8_ep: endpoint {
+							remote-endpoint = <&mixer_in8_ep>;
+						};
+					};
+
+					xbar_mixer_in9_port: port@5c {
+						reg = <0x5c>;
+
+						xbar_mixer_in9_ep: endpoint {
+							remote-endpoint = <&mixer_in9_ep>;
+						};
+					};
+
+					xbar_mixer_in10_port: port@5d {
+						reg = <0x5d>;
+
+						xbar_mixer_in10_ep: endpoint {
+							remote-endpoint = <&mixer_in10_ep>;
+						};
+					};
+
+					port@5e {
+						reg = <0x5e>;
+
+						xbar_mixer_out1_ep: endpoint {
+							remote-endpoint = <&mixer_out1_ep>;
+						};
+					};
+
+					port@5f {
+						reg = <0x5f>;
+
+						xbar_mixer_out2_ep: endpoint {
+							remote-endpoint = <&mixer_out2_ep>;
+						};
+					};
+
+					port@60 {
+						reg = <0x60>;
+
+						xbar_mixer_out3_ep: endpoint {
+							remote-endpoint = <&mixer_out3_ep>;
+						};
+					};
+
+					port@61 {
+						reg = <0x61>;
+
+						xbar_mixer_out4_ep: endpoint {
+							remote-endpoint = <&mixer_out4_ep>;
+						};
+					};
+
+					port@62 {
+						reg = <0x62>;
+
+						xbar_mixer_out5_ep: endpoint {
+							remote-endpoint = <&mixer_out5_ep>;
+						};
+					};
+				};
+
+				admaif@290f000 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						admaif0_port: port@0 {
+							reg = <0x0>;
+
+							admaif0_ep: endpoint {
+								remote-endpoint = <&xbar_admaif0_ep>;
+							};
+						};
+
+						admaif1_port: port@1 {
+							reg = <0x1>;
+
+							admaif1_ep: endpoint {
+								remote-endpoint = <&xbar_admaif1_ep>;
+							};
+						};
+
+						admaif2_port: port@2 {
+							reg = <0x2>;
+
+							admaif2_ep: endpoint {
+								remote-endpoint = <&xbar_admaif2_ep>;
+							};
+						};
+
+						admaif3_port: port@3 {
+							reg = <0x3>;
+
+							admaif3_ep: endpoint {
+								remote-endpoint = <&xbar_admaif3_ep>;
+							};
+						};
+
+						admaif4_port: port@4 {
+							reg = <0x4>;
+
+							admaif4_ep: endpoint {
+								remote-endpoint = <&xbar_admaif4_ep>;
+							};
+						};
+
+						admaif5_port: port@5 {
+							reg = <0x5>;
+
+							admaif5_ep: endpoint {
+								remote-endpoint = <&xbar_admaif5_ep>;
+							};
+						};
+
+						admaif6_port: port@6 {
+							reg = <0x6>;
+
+							admaif6_ep: endpoint {
+								remote-endpoint = <&xbar_admaif6_ep>;
+							};
+						};
+
+						admaif7_port: port@7 {
+							reg = <0x7>;
+
+							admaif7_ep: endpoint {
+								remote-endpoint = <&xbar_admaif7_ep>;
+							};
+						};
+
+						admaif8_port: port@8 {
+							reg = <0x8>;
+
+							admaif8_ep: endpoint {
+								remote-endpoint = <&xbar_admaif8_ep>;
+							};
+						};
+
+						admaif9_port: port@9 {
+							reg = <0x9>;
+
+							admaif9_ep: endpoint {
+								remote-endpoint = <&xbar_admaif9_ep>;
+							};
+						};
+
+						admaif10_port: port@a {
+							reg = <0xa>;
+
+							admaif10_ep: endpoint {
+								remote-endpoint = <&xbar_admaif10_ep>;
+							};
+						};
+
+						admaif11_port: port@b {
+							reg = <0xb>;
+
+							admaif11_ep: endpoint {
+								remote-endpoint = <&xbar_admaif11_ep>;
+							};
+						};
+
+						admaif12_port: port@c {
+							reg = <0xc>;
+
+							admaif12_ep: endpoint {
+								remote-endpoint = <&xbar_admaif12_ep>;
+							};
+						};
+
+						admaif13_port: port@d {
+							reg = <0xd>;
+
+							admaif13_ep: endpoint {
+								remote-endpoint = <&xbar_admaif13_ep>;
+							};
+						};
+
+						admaif14_port: port@e {
+							reg = <0xe>;
+
+							admaif14_ep: endpoint {
+								remote-endpoint = <&xbar_admaif14_ep>;
+							};
+						};
+
+						admaif15_port: port@f {
+							reg = <0xf>;
+
+							admaif15_ep: endpoint {
+								remote-endpoint = <&xbar_admaif15_ep>;
+							};
+						};
+
+						admaif16_port: port@10 {
+							reg = <0x10>;
+
+							admaif16_ep: endpoint {
+								remote-endpoint = <&xbar_admaif16_ep>;
+							};
+						};
+
+						admaif17_port: port@11 {
+							reg = <0x11>;
+
+							admaif17_ep: endpoint {
+								remote-endpoint = <&xbar_admaif17_ep>;
+							};
+						};
+
+						admaif18_port: port@12 {
+							reg = <0x12>;
+
+							admaif18_ep: endpoint {
+								remote-endpoint = <&xbar_admaif18_ep>;
+							};
+						};
+
+						admaif19_port: port@13 {
+							reg = <0x13>;
+
+							admaif19_ep: endpoint {
+								remote-endpoint = <&xbar_admaif19_ep>;
+							};
+						};
+					};
+				};
+
+				i2s@2901000 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							i2s1_cif_ep: endpoint {
+								remote-endpoint = <&xbar_i2s1_ep>;
+							};
+						};
+
+						i2s1_port: port@1 {
+							reg = <1>;
+
+							i2s1_dap_ep: endpoint {
+								dai-format = "i2s";
+								remote-endpoint = <&rt5658_ep>;
+							};
+						};
+					};
+				};
+
+				i2s@2901100 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							i2s2_cif_ep: endpoint {
+								remote-endpoint = <&xbar_i2s2_ep>;
+							};
+						};
+
+						i2s2_port: port@1 {
+							reg = <1>;
+
+							i2s2_dap_ep: endpoint {
+								dai-format = "i2s";
+								/* Place holder for external Codec */
+							};
+						};
+					};
+				};
+
+				i2s@2901300 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							i2s4_cif_ep: endpoint {
+								remote-endpoint = <&xbar_i2s4_ep>;
+							};
+						};
+
+						i2s4_port: port@1 {
+							reg = <1>;
+
+							i2s4_dap_ep: endpoint {
+								dai-format = "i2s";
+								/* Place holder for external Codec */
+							};
+						};
+					};
+				};
+
+				i2s@2901500 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							i2s6_cif_ep: endpoint {
+								remote-endpoint = <&xbar_i2s6_ep>;
+							};
+						};
+
+						i2s6_port: port@1 {
+							reg = <1>;
+
+							i2s6_dap_ep: endpoint@0 {
+								dai-format = "i2s";
+								/* Place holder for external Codec */
+							};
+						};
+					};
+				};
+
+				dmic@2904200 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							dmic3_cif_ep: endpoint {
+								remote-endpoint = <&xbar_dmic3_ep>;
+							};
+						};
+
+						dmic3_port: port@1 {
+							reg = <1>;
+
+							dmic3_dap_ep: endpoint {
+								/* Place holder for external Codec */
+							};
+						};
+					};
+				};
+
+				sfc@2902000 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							sfc1_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_sfc1_in_ep>;
+							};
+						};
+
+						sfc1_out_port: port@1 {
+							reg = <1>;
+
+							sfc1_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_sfc1_out_ep>;
+							};
+						};
+					};
+				};
+
+				sfc@2902200 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							sfc2_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_sfc2_in_ep>;
+							};
+						};
+
+						sfc2_out_port: port@1 {
+							reg = <1>;
+
+							sfc2_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_sfc2_out_ep>;
+							};
+						};
+					};
+				};
+
+				sfc@2902400 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							sfc3_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_sfc3_in_ep>;
+							};
+						};
+
+						sfc3_out_port: port@1 {
+							reg = <1>;
+
+							sfc3_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_sfc3_out_ep>;
+							};
+						};
+					};
+				};
+
+				sfc@2902600 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							sfc4_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_sfc4_in_ep>;
+							};
+						};
+
+						sfc4_out_port: port@1 {
+							reg = <1>;
+
+							sfc4_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_sfc4_out_ep>;
+							};
+						};
+					};
+				};
+
+				mvc@290a000 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							mvc1_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_mvc1_in_ep>;
+							};
+						};
+
+						mvc1_out_port: port@1 {
+							reg = <1>;
+
+							mvc1_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_mvc1_out_ep>;
+							};
+						};
+					};
+				};
+
+				mvc@290a200 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							mvc2_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_mvc2_in_ep>;
+							};
+						};
+
+						mvc2_out_port: port@1 {
+							reg = <1>;
+
+							mvc2_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_mvc2_out_ep>;
+							};
+						};
+					};
+				};
+
+				amx@2903000 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							amx1_in1_ep: endpoint {
+								remote-endpoint = <&xbar_amx1_in1_ep>;
+							};
+						};
+
+						port@1 {
+							reg = <1>;
+
+							amx1_in2_ep: endpoint {
+								remote-endpoint = <&xbar_amx1_in2_ep>;
+							};
+						};
+
+						port@2 {
+							reg = <2>;
+
+							amx1_in3_ep: endpoint {
+								remote-endpoint = <&xbar_amx1_in3_ep>;
+							};
+						};
+
+						port@3 {
+							reg = <3>;
+
+							amx1_in4_ep: endpoint {
+								remote-endpoint = <&xbar_amx1_in4_ep>;
+							};
+						};
+
+						amx1_out_port: port@4 {
+							reg = <4>;
+
+							amx1_out_ep: endpoint {
+								remote-endpoint = <&xbar_amx1_out_ep>;
+							};
+						};
+					};
 				};
 
-				admaif@290f000 {
+				amx@2903100 {
 					status = "okay";
 
 					ports {
 						#address-cells = <1>;
 						#size-cells = <0>;
 
-						admaif0_port: port@0 {
-							reg = <0x0>;
+						port@0 {
+							reg = <0>;
 
-							admaif0_ep: endpoint {
-								remote-endpoint = <&xbar_admaif0_ep>;
+							amx2_in1_ep: endpoint {
+								remote-endpoint = <&xbar_amx2_in1_ep>;
 							};
 						};
 
-						admaif1_port: port@1 {
-							reg = <0x1>;
+						port@1 {
+							reg = <1>;
 
-							admaif1_ep: endpoint {
-								remote-endpoint = <&xbar_admaif1_ep>;
+							amx2_in2_ep: endpoint {
+								remote-endpoint = <&xbar_amx2_in2_ep>;
 							};
 						};
 
-						admaif2_port: port@2 {
-							reg = <0x2>;
+						amx2_in3_port: port@2 {
+							reg = <2>;
 
-							admaif2_ep: endpoint {
-								remote-endpoint = <&xbar_admaif2_ep>;
+							amx2_in3_ep: endpoint {
+								remote-endpoint = <&xbar_amx2_in3_ep>;
 							};
 						};
 
-						admaif3_port: port@3 {
-							reg = <0x3>;
+						amx2_in4_port: port@3 {
+							reg = <3>;
 
-							admaif3_ep: endpoint {
-								remote-endpoint = <&xbar_admaif3_ep>;
+							amx2_in4_ep: endpoint {
+								remote-endpoint = <&xbar_amx2_in4_ep>;
 							};
 						};
 
-						admaif4_port: port@4 {
-							reg = <0x4>;
+						amx2_out_port: port@4 {
+							reg = <4>;
 
-							admaif4_ep: endpoint {
-								remote-endpoint = <&xbar_admaif4_ep>;
+							amx2_out_ep: endpoint {
+								remote-endpoint = <&xbar_amx2_out_ep>;
 							};
 						};
+					};
+				};
 
-						admaif5_port: port@5 {
-							reg = <0x5>;
+				amx@2903200 {
+					status = "okay";
 
-							admaif5_ep: endpoint {
-								remote-endpoint = <&xbar_admaif5_ep>;
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							amx3_in1_ep: endpoint {
+								remote-endpoint = <&xbar_amx3_in1_ep>;
 							};
 						};
 
-						admaif6_port: port@6 {
-							reg = <0x6>;
+						port@1 {
+							reg = <1>;
 
-							admaif6_ep: endpoint {
-								remote-endpoint = <&xbar_admaif6_ep>;
+							amx3_in2_ep: endpoint {
+								remote-endpoint = <&xbar_amx3_in2_ep>;
 							};
 						};
 
-						admaif7_port: port@7 {
-							reg = <0x7>;
+						port@2 {
+							reg = <2>;
 
-							admaif7_ep: endpoint {
-								remote-endpoint = <&xbar_admaif7_ep>;
+							amx3_in3_ep: endpoint {
+								remote-endpoint = <&xbar_amx3_in3_ep>;
 							};
 						};
 
-						admaif8_port: port@8 {
-							reg = <0x8>;
+						port@3 {
+							reg = <3>;
 
-							admaif8_ep: endpoint {
-								remote-endpoint = <&xbar_admaif8_ep>;
+							amx3_in4_ep: endpoint {
+								remote-endpoint = <&xbar_amx3_in4_ep>;
 							};
 						};
 
-						admaif9_port: port@9 {
-							reg = <0x9>;
+						amx3_out_port: port@4 {
+							reg = <4>;
 
-							admaif9_ep: endpoint {
-								remote-endpoint = <&xbar_admaif9_ep>;
+							amx3_out_ep: endpoint {
+								remote-endpoint = <&xbar_amx3_out_ep>;
 							};
 						};
+					};
+				};
 
-						admaif10_port: port@a {
-							reg = <0xa>;
+				amx@2903300 {
+					status = "okay";
 
-							admaif10_ep: endpoint {
-								remote-endpoint = <&xbar_admaif10_ep>;
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							amx4_in1_ep: endpoint {
+								remote-endpoint = <&xbar_amx4_in1_ep>;
 							};
 						};
 
-						admaif11_port: port@b {
-							reg = <0xb>;
+						port@1 {
+							reg = <1>;
 
-							admaif11_ep: endpoint {
-								remote-endpoint = <&xbar_admaif11_ep>;
+							amx4_in2_ep: endpoint {
+								remote-endpoint = <&xbar_amx4_in2_ep>;
 							};
 						};
 
-						admaif12_port: port@c {
-							reg = <0xc>;
+						port@2 {
+							reg = <2>;
 
-							admaif12_ep: endpoint {
-								remote-endpoint = <&xbar_admaif12_ep>;
+							amx4_in3_ep: endpoint {
+								remote-endpoint = <&xbar_amx4_in3_ep>;
 							};
 						};
 
-						admaif13_port: port@d {
-							reg = <0xd>;
+						port@3 {
+							reg = <3>;
 
-							admaif13_ep: endpoint {
-								remote-endpoint = <&xbar_admaif13_ep>;
+							amx4_in4_ep: endpoint {
+								remote-endpoint = <&xbar_amx4_in4_ep>;
 							};
 						};
 
-						admaif14_port: port@e {
-							reg = <0xe>;
+						amx4_out_port: port@4 {
+							reg = <4>;
 
-							admaif14_ep: endpoint {
-								remote-endpoint = <&xbar_admaif14_ep>;
+							amx4_out_ep: endpoint {
+								remote-endpoint = <&xbar_amx4_out_ep>;
 							};
 						};
+					};
+				};
 
-						admaif15_port: port@f {
-							reg = <0xf>;
+				adx@2903800 {
+					status = "okay";
 
-							admaif15_ep: endpoint {
-								remote-endpoint = <&xbar_admaif15_ep>;
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							adx1_in_ep: endpoint {
+								remote-endpoint = <&xbar_adx1_in_ep>;
 							};
 						};
 
-						admaif16_port: port@10 {
-							reg = <0x10>;
+						adx1_out1_port: port@1 {
+							reg = <1>;
 
-							admaif16_ep: endpoint {
-								remote-endpoint = <&xbar_admaif16_ep>;
+							adx1_out1_ep: endpoint {
+								remote-endpoint = <&xbar_adx1_out1_ep>;
 							};
 						};
 
-						admaif17_port: port@11 {
-							reg = <0x11>;
+						adx1_out2_port: port@2 {
+							reg = <2>;
 
-							admaif17_ep: endpoint {
-								remote-endpoint = <&xbar_admaif17_ep>;
+							adx1_out2_ep: endpoint {
+								remote-endpoint = <&xbar_adx1_out2_ep>;
 							};
 						};
 
-						admaif18_port: port@12 {
-							reg = <0x12>;
+						adx1_out3_port: port@3 {
+							reg = <3>;
 
-							admaif18_ep: endpoint {
-								remote-endpoint = <&xbar_admaif18_ep>;
+							adx1_out3_ep: endpoint {
+								remote-endpoint = <&xbar_adx1_out3_ep>;
 							};
 						};
 
-						admaif19_port: port@13 {
-							reg = <0x13>;
+						adx1_out4_port: port@4 {
+							reg = <4>;
 
-							admaif19_ep: endpoint {
-								remote-endpoint = <&xbar_admaif19_ep>;
+							adx1_out4_ep: endpoint {
+								remote-endpoint = <&xbar_adx1_out4_ep>;
 							};
 						};
 					};
 				};
 
-				i2s@2901000 {
+				adx@2903900 {
 					status = "okay";
 
 					ports {
@@ -409,49 +1469,46 @@
 						port@0 {
 							reg = <0>;
 
-							i2s1_cif_ep: endpoint {
-								remote-endpoint = <&xbar_i2s1_ep>;
+							adx2_in_ep: endpoint {
+								remote-endpoint = <&xbar_adx2_in_ep>;
 							};
 						};
 
-						i2s1_port: port@1 {
+						adx2_out1_port: port@1 {
 							reg = <1>;
 
-							i2s1_dap_ep: endpoint {
-								dai-format = "i2s";
-								remote-endpoint = <&rt5658_ep>;
+							adx2_out1_ep: endpoint {
+								remote-endpoint = <&xbar_adx2_out1_ep>;
 							};
 						};
-					};
-				};
 
-				i2s@2901100 {
-					status = "okay";
+						adx2_out2_port: port@2 {
+							reg = <2>;
 
-					ports {
-						#address-cells = <1>;
-						#size-cells = <0>;
+							adx2_out2_ep: endpoint {
+								remote-endpoint = <&xbar_adx2_out2_ep>;
+							};
+						};
 
-						port@0 {
-							reg = <0>;
+						adx2_out3_port: port@3 {
+							reg = <3>;
 
-							i2s2_cif_ep: endpoint {
-								remote-endpoint = <&xbar_i2s2_ep>;
+							adx2_out3_ep: endpoint {
+								remote-endpoint = <&xbar_adx2_out3_ep>;
 							};
 						};
 
-						i2s2_port: port@1 {
-							reg = <1>;
+						adx2_out4_port: port@4 {
+							reg = <4>;
 
-							i2s2_dap_ep: endpoint {
-								dai-format = "i2s";
-								/* Place holder for external Codec */
+							adx2_out4_ep: endpoint {
+								remote-endpoint = <&xbar_adx2_out4_ep>;
 							};
 						};
 					};
 				};
 
-				i2s@2901300 {
+				adx@2903a00 {
 					status = "okay";
 
 					ports {
@@ -461,23 +1518,46 @@
 						port@0 {
 							reg = <0>;
 
-							i2s4_cif_ep: endpoint {
-								remote-endpoint = <&xbar_i2s4_ep>;
+							adx3_in_ep: endpoint {
+								remote-endpoint = <&xbar_adx3_in_ep>;
 							};
 						};
 
-						i2s4_port: port@1 {
+						adx3_out1_port: port@1 {
 							reg = <1>;
 
-							i2s4_dap_ep: endpoint {
-								dai-format = "i2s";
-								/* Place holder for external Codec */
+							adx3_out1_ep: endpoint {
+								remote-endpoint = <&xbar_adx3_out1_ep>;
+							};
+						};
+
+						adx3_out2_port: port@2 {
+							reg = <2>;
+
+							adx3_out2_ep: endpoint {
+								remote-endpoint = <&xbar_adx3_out2_ep>;
+							};
+						};
+
+						adx3_out3_port: port@3 {
+							reg = <3>;
+
+							adx3_out3_ep: endpoint {
+								remote-endpoint = <&xbar_adx3_out3_ep>;
+							};
+						};
+
+						adx3_out4_port: port@4 {
+							reg = <4>;
+
+							adx3_out4_ep: endpoint {
+								remote-endpoint = <&xbar_adx3_out4_ep>;
 							};
 						};
 					};
 				};
 
-				i2s@2901500 {
+				adx@2903b00 {
 					status = "okay";
 
 					ports {
@@ -487,23 +1567,46 @@
 						port@0 {
 							reg = <0>;
 
-							i2s6_cif_ep: endpoint {
-								remote-endpoint = <&xbar_i2s6_ep>;
+							adx4_in_ep: endpoint {
+								remote-endpoint = <&xbar_adx4_in_ep>;
 							};
 						};
 
-						i2s6_port: port@1 {
+						adx4_out1_port: port@1 {
 							reg = <1>;
 
-							i2s6_dap_ep: endpoint@0 {
-								dai-format = "i2s";
-								/* Place holder for external Codec */
+							adx4_out1_ep: endpoint {
+								remote-endpoint = <&xbar_adx4_out1_ep>;
+							};
+						};
+
+						adx4_out2_port: port@2 {
+							reg = <2>;
+
+							adx4_out2_ep: endpoint {
+								remote-endpoint = <&xbar_adx4_out2_ep>;
+							};
+						};
+
+						adx4_out3_port: port@3 {
+							reg = <3>;
+
+							adx4_out3_ep: endpoint {
+								remote-endpoint = <&xbar_adx4_out3_ep>;
+							};
+						};
+
+						adx4_out4_port: port@4 {
+							reg = <4>;
+
+							adx4_out4_ep: endpoint {
+								remote-endpoint = <&xbar_adx4_out4_ep>;
 							};
 						};
 					};
 				};
 
-				dmic@2904200 {
+				amixer@290bb00 {
 					status = "okay";
 
 					ports {
@@ -511,18 +1614,122 @@
 						#size-cells = <0>;
 
 						port@0 {
-							reg = <0>;
+							reg = <0x0>;
 
-							dmic3_cif_ep: endpoint {
-								remote-endpoint = <&xbar_dmic3_ep>;
+							mixer_in1_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in1_ep>;
 							};
 						};
 
-						dmic3_port: port@1 {
-							reg = <1>;
+						port@1 {
+							reg = <0x1>;
 
-							dmic3_dap_ep: endpoint {
-								/* Place holder for external Codec */
+							mixer_in2_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in2_ep>;
+							};
+						};
+
+						port@2 {
+							reg = <0x2>;
+
+							mixer_in3_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in3_ep>;
+							};
+						};
+
+						port@3 {
+							reg = <0x3>;
+
+							mixer_in4_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in4_ep>;
+							};
+						};
+
+						port@4 {
+							reg = <0x4>;
+
+							mixer_in5_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in5_ep>;
+							};
+						};
+
+						port@5 {
+							reg = <0x5>;
+
+							mixer_in6_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in6_ep>;
+							};
+						};
+
+						port@6 {
+							reg = <0x6>;
+
+							mixer_in7_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in7_ep>;
+							};
+						};
+
+						port@7 {
+							reg = <0x7>;
+
+							mixer_in8_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in8_ep>;
+							};
+						};
+
+						port@8 {
+							reg = <0x8>;
+
+							mixer_in9_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in9_ep>;
+							};
+						};
+
+						port@9 {
+							reg = <0x9>;
+
+							mixer_in10_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in10_ep>;
+							};
+						};
+
+						mixer_out1_port: port@a {
+							reg = <0xa>;
+
+							mixer_out1_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_out1_ep>;
+							};
+						};
+
+						mixer_out2_port: port@b {
+							reg = <0xb>;
+
+							mixer_out2_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_out2_ep>;
+							};
+						};
+
+						mixer_out3_port: port@c {
+							reg = <0xc>;
+
+							mixer_out3_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_out3_ep>;
+							};
+						};
+
+						mixer_out4_port: port@d {
+							reg = <0xd>;
+
+							mixer_out4_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_out4_ep>;
+							};
+						};
+
+						mixer_out5_port: port@e {
+							reg = <0xe>;
+
+							mixer_out5_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_out5_ep>;
 							};
 						};
 					};
@@ -827,6 +2034,40 @@
 		       /* XBAR Ports */
 		       <&xbar_i2s1_port>, <&xbar_i2s2_port>, <&xbar_i2s4_port>,
 		       <&xbar_i2s6_port>, <&xbar_dmic3_port>,
+		       <&xbar_sfc1_in_port>, <&xbar_sfc2_in_port>,
+		       <&xbar_sfc3_in_port>, <&xbar_sfc4_in_port>,
+		       <&xbar_mvc1_in_port>, <&xbar_mvc2_in_port>,
+		       <&xbar_amx1_in1_port>, <&xbar_amx1_in2_port>,
+		       <&xbar_amx1_in3_port>, <&xbar_amx1_in4_port>,
+		       <&xbar_amx2_in1_port>, <&xbar_amx2_in2_port>,
+		       <&xbar_amx2_in3_port>, <&xbar_amx2_in4_port>,
+		       <&xbar_amx3_in1_port>, <&xbar_amx3_in2_port>,
+		       <&xbar_amx3_in3_port>, <&xbar_amx3_in4_port>,
+		       <&xbar_amx4_in1_port>, <&xbar_amx4_in2_port>,
+		       <&xbar_amx4_in3_port>, <&xbar_amx4_in4_port>,
+		       <&xbar_adx1_in_port>, <&xbar_adx2_in_port>,
+		       <&xbar_adx3_in_port>, <&xbar_adx4_in_port>,
+		       <&xbar_mixer_in1_port>, <&xbar_mixer_in2_port>,
+		       <&xbar_mixer_in3_port>, <&xbar_mixer_in4_port>,
+		       <&xbar_mixer_in5_port>, <&xbar_mixer_in6_port>,
+		       <&xbar_mixer_in7_port>, <&xbar_mixer_in8_port>,
+		       <&xbar_mixer_in9_port>, <&xbar_mixer_in10_port>,
+		       /* HW accelerators */
+		       <&sfc1_out_port>, <&sfc2_out_port>,
+		       <&sfc3_out_port>, <&sfc4_out_port>,
+		       <&mvc1_out_port>, <&mvc2_out_port>,
+		       <&amx1_out_port>, <&amx2_out_port>,
+		       <&amx3_out_port>, <&amx4_out_port>,
+		       <&adx1_out1_port>, <&adx1_out2_port>,
+		       <&adx1_out3_port>, <&adx1_out4_port>,
+		       <&adx2_out1_port>, <&adx2_out2_port>,
+		       <&adx2_out3_port>, <&adx2_out4_port>,
+		       <&adx3_out1_port>, <&adx3_out2_port>,
+		       <&adx3_out3_port>, <&adx3_out4_port>,
+		       <&adx4_out1_port>, <&adx4_out2_port>,
+		       <&adx4_out3_port>, <&adx4_out4_port>,
+		       <&mixer_out1_port>, <&mixer_out2_port>, <&mixer_out3_port>,
+		       <&mixer_out4_port>, <&mixer_out5_port>,
 		       /* BE I/O Ports */
 		       <&i2s1_port>, <&i2s2_port>, <&i2s4_port>, <&i2s6_port>,
 		       <&dmic3_port>;
diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi
index 836a7e0..48fc9cf 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi
@@ -238,178 +238,1190 @@
 							remote-endpoint = <&dspk2_cif_ep>;
 						};
 					};
+
+					xbar_sfc1_in_port: port@20 {
+						reg = <0x20>;
+
+						xbar_sfc1_in_ep: endpoint {
+							remote-endpoint = <&sfc1_cif_in_ep>;
+						};
+					};
+
+					port@21 {
+						reg = <0x21>;
+
+						xbar_sfc1_out_ep: endpoint {
+							remote-endpoint = <&sfc1_cif_out_ep>;
+						};
+					};
+
+					xbar_sfc2_in_port: port@22 {
+						reg = <0x22>;
+
+						xbar_sfc2_in_ep: endpoint {
+							remote-endpoint = <&sfc2_cif_in_ep>;
+						};
+					};
+
+					port@23 {
+						reg = <0x23>;
+
+						xbar_sfc2_out_ep: endpoint {
+							remote-endpoint = <&sfc2_cif_out_ep>;
+						};
+					};
+
+					xbar_sfc3_in_port: port@24 {
+						reg = <0x24>;
+
+						xbar_sfc3_in_ep: endpoint {
+							remote-endpoint = <&sfc3_cif_in_ep>;
+						};
+					};
+
+					port@25 {
+						reg = <0x25>;
+
+						xbar_sfc3_out_ep: endpoint {
+							remote-endpoint = <&sfc3_cif_out_ep>;
+						};
+					};
+
+					xbar_sfc4_in_port: port@26 {
+						reg = <0x26>;
+
+						xbar_sfc4_in_ep: endpoint {
+							remote-endpoint = <&sfc4_cif_in_ep>;
+						};
+					};
+
+					port@27 {
+						reg = <0x27>;
+
+						xbar_sfc4_out_ep: endpoint {
+							remote-endpoint = <&sfc4_cif_out_ep>;
+						};
+					};
+
+					xbar_mvc1_in_port: port@28 {
+						reg = <0x28>;
+
+						xbar_mvc1_in_ep: endpoint {
+							remote-endpoint = <&mvc1_cif_in_ep>;
+						};
+					};
+
+					port@29 {
+						reg = <0x29>;
+
+						xbar_mvc1_out_ep: endpoint {
+							remote-endpoint = <&mvc1_cif_out_ep>;
+						};
+					};
+
+					xbar_mvc2_in_port: port@2a {
+						reg = <0x2a>;
+
+						xbar_mvc2_in_ep: endpoint {
+							remote-endpoint = <&mvc2_cif_in_ep>;
+						};
+					};
+
+					port@2b {
+						reg = <0x2b>;
+
+						xbar_mvc2_out_ep: endpoint {
+							remote-endpoint = <&mvc2_cif_out_ep>;
+						};
+					};
+
+					xbar_amx1_in1_port: port@2c {
+						reg = <0x2c>;
+
+						xbar_amx1_in1_ep: endpoint {
+							remote-endpoint = <&amx1_in1_ep>;
+						};
+					};
+
+					xbar_amx1_in2_port: port@2d {
+						reg = <0x2d>;
+
+						xbar_amx1_in2_ep: endpoint {
+							remote-endpoint = <&amx1_in2_ep>;
+						};
+					};
+
+					xbar_amx1_in3_port: port@2e {
+						reg = <0x2e>;
+
+						xbar_amx1_in3_ep: endpoint {
+							remote-endpoint = <&amx1_in3_ep>;
+						};
+					};
+
+					xbar_amx1_in4_port: port@2f {
+						reg = <0x2f>;
+
+						xbar_amx1_in4_ep: endpoint {
+							remote-endpoint = <&amx1_in4_ep>;
+						};
+					};
+
+					port@30 {
+						reg = <0x30>;
+
+						xbar_amx1_out_ep: endpoint {
+							remote-endpoint = <&amx1_out_ep>;
+						};
+					};
+
+					xbar_amx2_in1_port: port@31 {
+						reg = <0x31>;
+
+						xbar_amx2_in1_ep: endpoint {
+							remote-endpoint = <&amx2_in1_ep>;
+						};
+					};
+
+					xbar_amx2_in2_port: port@32 {
+						reg = <0x32>;
+
+						xbar_amx2_in2_ep: endpoint {
+							remote-endpoint = <&amx2_in2_ep>;
+						};
+					};
+
+					xbar_amx2_in3_port: port@33 {
+						reg = <0x33>;
+
+						xbar_amx2_in3_ep: endpoint {
+							remote-endpoint = <&amx2_in3_ep>;
+						};
+					};
+
+					xbar_amx2_in4_port: port@34 {
+						reg = <0x34>;
+
+						xbar_amx2_in4_ep: endpoint {
+							remote-endpoint = <&amx2_in4_ep>;
+						};
+					};
+
+					port@35 {
+						reg = <0x35>;
+
+						xbar_amx2_out_ep: endpoint {
+							remote-endpoint = <&amx2_out_ep>;
+						};
+					};
+
+					xbar_amx3_in1_port: port@36 {
+						reg = <0x36>;
+
+						xbar_amx3_in1_ep: endpoint {
+							remote-endpoint = <&amx3_in1_ep>;
+						};
+					};
+
+					xbar_amx3_in2_port: port@37 {
+						reg = <0x37>;
+
+						xbar_amx3_in2_ep: endpoint {
+							remote-endpoint = <&amx3_in2_ep>;
+						};
+					};
+
+					xbar_amx3_in3_port: port@38 {
+						reg = <0x38>;
+
+						xbar_amx3_in3_ep: endpoint {
+							remote-endpoint = <&amx3_in3_ep>;
+						};
+					};
+
+					xbar_amx3_in4_port: port@39 {
+						reg = <0x39>;
+
+						xbar_amx3_in4_ep: endpoint {
+							remote-endpoint = <&amx3_in4_ep>;
+						};
+					};
+
+					port@3a {
+						reg = <0x3a>;
+
+						xbar_amx3_out_ep: endpoint {
+							remote-endpoint = <&amx3_out_ep>;
+						};
+					};
+
+					xbar_amx4_in1_port: port@3b {
+						reg = <0x3b>;
+
+						xbar_amx4_in1_ep: endpoint {
+							remote-endpoint = <&amx4_in1_ep>;
+						};
+					};
+
+					xbar_amx4_in2_port: port@3c {
+						reg = <0x3c>;
+
+						xbar_amx4_in2_ep: endpoint {
+							remote-endpoint = <&amx4_in2_ep>;
+						};
+					};
+
+					xbar_amx4_in3_port: port@3d {
+						reg = <0x3d>;
+
+						xbar_amx4_in3_ep: endpoint {
+							remote-endpoint = <&amx4_in3_ep>;
+						};
+					};
+
+					xbar_amx4_in4_port: port@3e {
+						reg = <0x3e>;
+
+						xbar_amx4_in4_ep: endpoint {
+							remote-endpoint = <&amx4_in4_ep>;
+						};
+					};
+
+					port@3f {
+						reg = <0x3f>;
+
+						xbar_amx4_out_ep: endpoint {
+							remote-endpoint = <&amx4_out_ep>;
+						};
+					};
+
+					xbar_adx1_in_port: port@40 {
+						reg = <0x40>;
+
+						xbar_adx1_in_ep: endpoint {
+							remote-endpoint = <&adx1_in_ep>;
+						};
+					};
+
+					port@41 {
+						reg = <0x41>;
+
+						xbar_adx1_out1_ep: endpoint {
+							remote-endpoint = <&adx1_out1_ep>;
+						};
+					};
+
+					port@42 {
+						reg = <0x42>;
+
+						xbar_adx1_out2_ep: endpoint {
+							remote-endpoint = <&adx1_out2_ep>;
+						};
+					};
+
+					port@43 {
+						reg = <0x43>;
+
+						xbar_adx1_out3_ep: endpoint {
+							remote-endpoint = <&adx1_out3_ep>;
+						};
+					};
+
+					port@44 {
+						reg = <0x44>;
+
+						xbar_adx1_out4_ep: endpoint {
+							remote-endpoint = <&adx1_out4_ep>;
+						};
+					};
+
+					xbar_adx2_in_port: port@45 {
+						reg = <0x45>;
+
+						xbar_adx2_in_ep: endpoint {
+							remote-endpoint = <&adx2_in_ep>;
+						};
+					};
+
+					port@46 {
+						reg = <0x46>;
+
+						xbar_adx2_out1_ep: endpoint {
+							remote-endpoint = <&adx2_out1_ep>;
+						};
+					};
+
+					port@47 {
+						reg = <0x47>;
+
+						xbar_adx2_out2_ep: endpoint {
+							remote-endpoint = <&adx2_out2_ep>;
+						};
+					};
+
+					port@48 {
+						reg = <0x48>;
+
+						xbar_adx2_out3_ep: endpoint {
+							remote-endpoint = <&adx2_out3_ep>;
+						};
+					};
+
+					port@49 {
+						reg = <0x49>;
+
+						xbar_adx2_out4_ep: endpoint {
+							remote-endpoint = <&adx2_out4_ep>;
+						};
+					};
+
+					xbar_adx3_in_port: port@4a {
+						reg = <0x4a>;
+
+						xbar_adx3_in_ep: endpoint {
+							remote-endpoint = <&adx3_in_ep>;
+						};
+					};
+
+					port@4b {
+						reg = <0x4b>;
+
+						xbar_adx3_out1_ep: endpoint {
+							remote-endpoint = <&adx3_out1_ep>;
+						};
+					};
+
+					port@4c {
+						reg = <0x4c>;
+
+						xbar_adx3_out2_ep: endpoint {
+							remote-endpoint = <&adx3_out2_ep>;
+						};
+					};
+
+					port@4d {
+						reg = <0x4d>;
+
+						xbar_adx3_out3_ep: endpoint {
+							remote-endpoint = <&adx3_out3_ep>;
+						};
+					};
+
+					port@4e {
+						reg = <0x4e>;
+
+						xbar_adx3_out4_ep: endpoint {
+							remote-endpoint = <&adx3_out4_ep>;
+						};
+					};
+
+					xbar_adx4_in_port: port@4f {
+						reg = <0x4f>;
+
+						xbar_adx4_in_ep: endpoint {
+							remote-endpoint = <&adx4_in_ep>;
+						};
+					};
+
+					port@50 {
+						reg = <0x50>;
+
+						xbar_adx4_out1_ep: endpoint {
+							remote-endpoint = <&adx4_out1_ep>;
+						};
+					};
+
+					port@51 {
+						reg = <0x51>;
+
+						xbar_adx4_out2_ep: endpoint {
+							remote-endpoint = <&adx4_out2_ep>;
+						};
+					};
+
+					port@52 {
+						reg = <0x52>;
+
+						xbar_adx4_out3_ep: endpoint {
+							remote-endpoint = <&adx4_out3_ep>;
+						};
+					};
+
+					port@53 {
+						reg = <0x53>;
+
+						xbar_adx4_out4_ep: endpoint {
+							remote-endpoint = <&adx4_out4_ep>;
+						};
+					};
+
+					xbar_mixer_in1_port: port@54 {
+						reg = <0x54>;
+
+						xbar_mixer_in1_ep: endpoint {
+							remote-endpoint = <&mixer_in1_ep>;
+						};
+					};
+
+					xbar_mixer_in2_port: port@55 {
+						reg = <0x55>;
+
+						xbar_mixer_in2_ep: endpoint {
+							remote-endpoint = <&mixer_in2_ep>;
+						};
+					};
+
+					xbar_mixer_in3_port: port@56 {
+						reg = <0x56>;
+
+						xbar_mixer_in3_ep: endpoint {
+							remote-endpoint = <&mixer_in3_ep>;
+						};
+					};
+
+					xbar_mixer_in4_port: port@57 {
+						reg = <0x57>;
+
+						xbar_mixer_in4_ep: endpoint {
+							remote-endpoint = <&mixer_in4_ep>;
+						};
+					};
+
+					xbar_mixer_in5_port: port@58 {
+						reg = <0x58>;
+
+						xbar_mixer_in5_ep: endpoint {
+							remote-endpoint = <&mixer_in5_ep>;
+						};
+					};
+
+					xbar_mixer_in6_port: port@59 {
+						reg = <0x59>;
+
+						xbar_mixer_in6_ep: endpoint {
+							remote-endpoint = <&mixer_in6_ep>;
+						};
+					};
+
+					xbar_mixer_in7_port: port@5a {
+						reg = <0x5a>;
+
+						xbar_mixer_in7_ep: endpoint {
+							remote-endpoint = <&mixer_in7_ep>;
+						};
+					};
+
+					xbar_mixer_in8_port: port@5b {
+						reg = <0x5b>;
+
+						xbar_mixer_in8_ep: endpoint {
+							remote-endpoint = <&mixer_in8_ep>;
+						};
+					};
+
+					xbar_mixer_in9_port: port@5c {
+						reg = <0x5c>;
+
+						xbar_mixer_in9_ep: endpoint {
+							remote-endpoint = <&mixer_in9_ep>;
+						};
+					};
+
+					xbar_mixer_in10_port: port@5d {
+						reg = <0x5d>;
+
+						xbar_mixer_in10_ep: endpoint {
+							remote-endpoint = <&mixer_in10_ep>;
+						};
+					};
+
+					port@5e {
+						reg = <0x5e>;
+
+						xbar_mixer_out1_ep: endpoint {
+							remote-endpoint = <&mixer_out1_ep>;
+						};
+					};
+
+					port@5f {
+						reg = <0x5f>;
+
+						xbar_mixer_out2_ep: endpoint {
+							remote-endpoint = <&mixer_out2_ep>;
+						};
+					};
+
+					port@60 {
+						reg = <0x60>;
+
+						xbar_mixer_out3_ep: endpoint {
+							remote-endpoint = <&mixer_out3_ep>;
+						};
+					};
+
+					port@61 {
+						reg = <0x61>;
+
+						xbar_mixer_out4_ep: endpoint {
+							remote-endpoint = <&mixer_out4_ep>;
+						};
+					};
+
+					port@62 {
+						reg = <0x62>;
+
+						xbar_mixer_out5_ep: endpoint {
+							remote-endpoint = <&mixer_out5_ep>;
+						};
+					};
+				};
+
+				admaif@290f000 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						admaif0_port: port@0 {
+							reg = <0x0>;
+
+							admaif0_ep: endpoint {
+								remote-endpoint = <&xbar_admaif0_ep>;
+							};
+						};
+
+						admaif1_port: port@1 {
+							reg = <0x1>;
+
+							admaif1_ep: endpoint {
+								remote-endpoint = <&xbar_admaif1_ep>;
+							};
+						};
+
+						admaif2_port: port@2 {
+							reg = <0x2>;
+
+							admaif2_ep: endpoint {
+								remote-endpoint = <&xbar_admaif2_ep>;
+							};
+						};
+
+						admaif3_port: port@3 {
+							reg = <0x3>;
+
+							admaif3_ep: endpoint {
+								remote-endpoint = <&xbar_admaif3_ep>;
+							};
+						};
+
+						admaif4_port: port@4 {
+							reg = <0x4>;
+
+							admaif4_ep: endpoint {
+								remote-endpoint = <&xbar_admaif4_ep>;
+							};
+						};
+
+						admaif5_port: port@5 {
+							reg = <0x5>;
+
+							admaif5_ep: endpoint {
+								remote-endpoint = <&xbar_admaif5_ep>;
+							};
+						};
+
+						admaif6_port: port@6 {
+							reg = <0x6>;
+
+							admaif6_ep: endpoint {
+								remote-endpoint = <&xbar_admaif6_ep>;
+							};
+						};
+
+						admaif7_port: port@7 {
+							reg = <0x7>;
+
+							admaif7_ep: endpoint {
+								remote-endpoint = <&xbar_admaif7_ep>;
+							};
+						};
+
+						admaif8_port: port@8 {
+							reg = <0x8>;
+
+							admaif8_ep: endpoint {
+								remote-endpoint = <&xbar_admaif8_ep>;
+							};
+						};
+
+						admaif9_port: port@9 {
+							reg = <0x9>;
+
+							admaif9_ep: endpoint {
+								remote-endpoint = <&xbar_admaif9_ep>;
+							};
+						};
+
+						admaif10_port: port@a {
+							reg = <0xa>;
+
+							admaif10_ep: endpoint {
+								remote-endpoint = <&xbar_admaif10_ep>;
+							};
+						};
+
+						admaif11_port: port@b {
+							reg = <0xb>;
+
+							admaif11_ep: endpoint {
+								remote-endpoint = <&xbar_admaif11_ep>;
+							};
+						};
+
+						admaif12_port: port@c {
+							reg = <0xc>;
+
+							admaif12_ep: endpoint {
+								remote-endpoint = <&xbar_admaif12_ep>;
+							};
+						};
+
+						admaif13_port: port@d {
+							reg = <0xd>;
+
+							admaif13_ep: endpoint {
+								remote-endpoint = <&xbar_admaif13_ep>;
+							};
+						};
+
+						admaif14_port: port@e {
+							reg = <0xe>;
+
+							admaif14_ep: endpoint {
+								remote-endpoint = <&xbar_admaif14_ep>;
+							};
+						};
+
+						admaif15_port: port@f {
+							reg = <0xf>;
+
+							admaif15_ep: endpoint {
+								remote-endpoint = <&xbar_admaif15_ep>;
+							};
+						};
+
+						admaif16_port: port@10 {
+							reg = <0x10>;
+
+							admaif16_ep: endpoint {
+								remote-endpoint = <&xbar_admaif16_ep>;
+							};
+						};
+
+						admaif17_port: port@11 {
+							reg = <0x11>;
+
+							admaif17_ep: endpoint {
+								remote-endpoint = <&xbar_admaif17_ep>;
+							};
+						};
+
+						admaif18_port: port@12 {
+							reg = <0x12>;
+
+							admaif18_ep: endpoint {
+								remote-endpoint = <&xbar_admaif18_ep>;
+							};
+						};
+
+						admaif19_port: port@13 {
+							reg = <0x13>;
+
+							admaif19_ep: endpoint {
+								remote-endpoint = <&xbar_admaif19_ep>;
+							};
+						};
+					};
+				};
+
+				i2s@2901200 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							i2s3_cif_ep: endpoint {
+								remote-endpoint = <&xbar_i2s3_ep>;
+							};
+						};
+
+						i2s3_port: port@1 {
+							reg = <1>;
+
+							i2s3_dap_ep: endpoint {
+								dai-format = "i2s";
+								/* Place holder for external Codec */
+							};
+						};
+					};
+				};
+
+				i2s@2901400 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							i2s5_cif_ep: endpoint {
+								remote-endpoint = <&xbar_i2s5_ep>;
+							};
+						};
+
+						i2s5_port: port@1 {
+							reg = <1>;
+
+							i2s5_dap_ep: endpoint@0 {
+								dai-format = "i2s";
+								/* Place holder for external Codec */
+							};
+						};
+					};
 				};
 
-				admaif@290f000 {
+				dmic@2904000 {
 					status = "okay";
 
 					ports {
 						#address-cells = <1>;
 						#size-cells = <0>;
 
-						admaif0_port: port@0 {
-							reg = <0x0>;
+						port@0 {
+							reg = <0>;
 
-							admaif0_ep: endpoint {
-								remote-endpoint = <&xbar_admaif0_ep>;
+							dmic1_cif_ep: endpoint {
+								remote-endpoint = <&xbar_dmic1_ep>;
 							};
 						};
 
-						admaif1_port: port@1 {
-							reg = <0x1>;
+						dmic1_port: port@1 {
+							reg = <1>;
 
-							admaif1_ep: endpoint {
-								remote-endpoint = <&xbar_admaif1_ep>;
+							dmic1_dap_ep: endpoint {
+								/* Place holder for external Codec */
 							};
 						};
+					};
+				};
 
-						admaif2_port: port@2 {
-							reg = <0x2>;
+				dmic@2904100 {
+					status = "okay";
 
-							admaif2_ep: endpoint {
-								remote-endpoint = <&xbar_admaif2_ep>;
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							dmic2_cif_ep: endpoint {
+								remote-endpoint = <&xbar_dmic2_ep>;
 							};
 						};
 
-						admaif3_port: port@3 {
-							reg = <0x3>;
+						dmic2_port: port@1 {
+							reg = <1>;
 
-							admaif3_ep: endpoint {
-								remote-endpoint = <&xbar_admaif3_ep>;
+							dmic2_dap_ep: endpoint {
+								/* Place holder for external Codec */
 							};
 						};
+					};
+				};
 
-						admaif4_port: port@4 {
-							reg = <0x4>;
+				dmic@2904300 {
+					status = "okay";
 
-							admaif4_ep: endpoint {
-								remote-endpoint = <&xbar_admaif4_ep>;
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							dmic4_cif_ep: endpoint {
+								remote-endpoint = <&xbar_dmic4_ep>;
+							};
+						};
+
+						dmic4_port: port@1 {
+							reg = <1>;
+
+							dmic4_dap_ep: endpoint {
+								/* Place holder for external Codec */
+							};
+						};
+					};
+				};
+
+				dspk@2905000 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							dspk1_cif_ep: endpoint {
+								remote-endpoint = <&xbar_dspk1_ep>;
+							};
+						};
+
+						dspk1_port: port@1 {
+							reg = <1>;
+
+							dspk1_dap_ep: endpoint {
+								/* Place holder for external Codec */
+							};
+						};
+					};
+				};
+
+				dspk@2905100 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							dspk2_cif_ep: endpoint {
+								remote-endpoint = <&xbar_dspk2_ep>;
+							};
+						};
+
+						dspk2_port: port@1 {
+							reg = <1>;
+
+							dspk2_dap_ep: endpoint {
+								/* Place holder for external Codec */
+							};
+						};
+					};
+				};
+
+				sfc@2902000 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							sfc1_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_sfc1_in_ep>;
+								convert-rate = <44100>;
+							};
+						};
+
+						sfc1_out_port: port@1 {
+							reg = <1>;
+
+							sfc1_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_sfc1_out_ep>;
+								convert-rate = <48000>;
+							};
+						};
+					};
+				};
+
+				sfc@2902200 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							sfc2_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_sfc2_in_ep>;
+							};
+						};
+
+						sfc2_out_port: port@1 {
+							reg = <1>;
+
+							sfc2_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_sfc2_out_ep>;
+							};
+						};
+					};
+				};
+
+				sfc@2902400 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							sfc3_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_sfc3_in_ep>;
+							};
+						};
+
+						sfc3_out_port: port@1 {
+							reg = <1>;
+
+							sfc3_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_sfc3_out_ep>;
+							};
+						};
+					};
+				};
+
+				sfc@2902600 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							sfc4_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_sfc4_in_ep>;
+							};
+						};
+
+						sfc4_out_port: port@1 {
+							reg = <1>;
+
+							sfc4_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_sfc4_out_ep>;
+							};
+						};
+					};
+				};
+
+				mvc@290a000 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							mvc1_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_mvc1_in_ep>;
+							};
+						};
+
+						mvc1_out_port: port@1 {
+							reg = <1>;
+
+							mvc1_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_mvc1_out_ep>;
+							};
+						};
+					};
+				};
+
+				mvc@290a200 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							mvc2_cif_in_ep: endpoint {
+								remote-endpoint = <&xbar_mvc2_in_ep>;
+							};
+						};
+
+						mvc2_out_port: port@1 {
+							reg = <1>;
+
+							mvc2_cif_out_ep: endpoint {
+								remote-endpoint = <&xbar_mvc2_out_ep>;
+							};
+						};
+					};
+				};
+
+				amx@2903000 {
+					status = "okay";
+
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							amx1_in1_ep: endpoint {
+								remote-endpoint = <&xbar_amx1_in1_ep>;
 							};
 						};
 
-						admaif5_port: port@5 {
-							reg = <0x5>;
+						port@1 {
+							reg = <1>;
 
-							admaif5_ep: endpoint {
-								remote-endpoint = <&xbar_admaif5_ep>;
+							amx1_in2_ep: endpoint {
+								remote-endpoint = <&xbar_amx1_in2_ep>;
 							};
 						};
 
-						admaif6_port: port@6 {
-							reg = <0x6>;
+						port@2 {
+							reg = <2>;
 
-							admaif6_ep: endpoint {
-								remote-endpoint = <&xbar_admaif6_ep>;
+							amx1_in3_ep: endpoint {
+								remote-endpoint = <&xbar_amx1_in3_ep>;
 							};
 						};
 
-						admaif7_port: port@7 {
-							reg = <0x7>;
+						port@3 {
+							reg = <3>;
 
-							admaif7_ep: endpoint {
-								remote-endpoint = <&xbar_admaif7_ep>;
+							amx1_in4_ep: endpoint {
+								remote-endpoint = <&xbar_amx1_in4_ep>;
 							};
 						};
 
-						admaif8_port: port@8 {
-							reg = <0x8>;
+						amx1_out_port: port@4 {
+							reg = <4>;
 
-							admaif8_ep: endpoint {
-								remote-endpoint = <&xbar_admaif8_ep>;
+							amx1_out_ep: endpoint {
+								remote-endpoint = <&xbar_amx1_out_ep>;
 							};
 						};
+					};
+				};
 
-						admaif9_port: port@9 {
-							reg = <0x9>;
+				amx@2903100 {
+					status = "okay";
 
-							admaif9_ep: endpoint {
-								remote-endpoint = <&xbar_admaif9_ep>;
-							};
-						};
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
 
-						admaif10_port: port@a {
-							reg = <0xa>;
+						port@0 {
+							reg = <0>;
 
-							admaif10_ep: endpoint {
-								remote-endpoint = <&xbar_admaif10_ep>;
+							amx2_in1_ep: endpoint {
+								remote-endpoint = <&xbar_amx2_in1_ep>;
 							};
 						};
 
-						admaif11_port: port@b {
-							reg = <0xb>;
+						port@1 {
+							reg = <1>;
 
-							admaif11_ep: endpoint {
-								remote-endpoint = <&xbar_admaif11_ep>;
+							amx2_in2_ep: endpoint {
+								remote-endpoint = <&xbar_amx2_in2_ep>;
 							};
 						};
 
-						admaif12_port: port@c {
-							reg = <0xc>;
+						amx2_in3_port: port@2 {
+							reg = <2>;
 
-							admaif12_ep: endpoint {
-								remote-endpoint = <&xbar_admaif12_ep>;
+							amx2_in3_ep: endpoint {
+								remote-endpoint = <&xbar_amx2_in3_ep>;
 							};
 						};
 
-						admaif13_port: port@d {
-							reg = <0xd>;
+						amx2_in4_port: port@3 {
+							reg = <3>;
 
-							admaif13_ep: endpoint {
-								remote-endpoint = <&xbar_admaif13_ep>;
+							amx2_in4_ep: endpoint {
+								remote-endpoint = <&xbar_amx2_in4_ep>;
 							};
 						};
 
-						admaif14_port: port@e {
-							reg = <0xe>;
+						amx2_out_port: port@4 {
+							reg = <4>;
 
-							admaif14_ep: endpoint {
-								remote-endpoint = <&xbar_admaif14_ep>;
+							amx2_out_ep: endpoint {
+								remote-endpoint = <&xbar_amx2_out_ep>;
 							};
 						};
+					};
+				};
 
-						admaif15_port: port@f {
-							reg = <0xf>;
+				amx@2903200 {
+					status = "okay";
 
-							admaif15_ep: endpoint {
-								remote-endpoint = <&xbar_admaif15_ep>;
+					ports {
+						#address-cells = <1>;
+						#size-cells = <0>;
+
+						port@0 {
+							reg = <0>;
+
+							amx3_in1_ep: endpoint {
+								remote-endpoint = <&xbar_amx3_in1_ep>;
 							};
 						};
 
-						admaif16_port: port@10 {
-							reg = <0x10>;
+						port@1 {
+							reg = <1>;
 
-							admaif16_ep: endpoint {
-								remote-endpoint = <&xbar_admaif16_ep>;
+							amx3_in2_ep: endpoint {
+								remote-endpoint = <&xbar_amx3_in2_ep>;
 							};
 						};
 
-						admaif17_port: port@11 {
-							reg = <0x11>;
+						port@2 {
+							reg = <2>;
 
-							admaif17_ep: endpoint {
-								remote-endpoint = <&xbar_admaif17_ep>;
+							amx3_in3_ep: endpoint {
+								remote-endpoint = <&xbar_amx3_in3_ep>;
 							};
 						};
 
-						admaif18_port: port@12 {
-							reg = <0x12>;
+						port@3 {
+							reg = <3>;
 
-							admaif18_ep: endpoint {
-								remote-endpoint = <&xbar_admaif18_ep>;
+							amx3_in4_ep: endpoint {
+								remote-endpoint = <&xbar_amx3_in4_ep>;
 							};
 						};
 
-						admaif19_port: port@13 {
-							reg = <0x13>;
+						amx3_out_port: port@4 {
+							reg = <4>;
 
-							admaif19_ep: endpoint {
-								remote-endpoint = <&xbar_admaif19_ep>;
+							amx3_out_ep: endpoint {
+								remote-endpoint = <&xbar_amx3_out_ep>;
 							};
 						};
 					};
 				};
 
-				i2s@2901200 {
+				amx@2903300 {
 					status = "okay";
 
 					ports {
@@ -419,49 +1431,46 @@
 						port@0 {
 							reg = <0>;
 
-							i2s3_cif_ep: endpoint {
-								remote-endpoint = <&xbar_i2s3_ep>;
+							amx4_in1_ep: endpoint {
+								remote-endpoint = <&xbar_amx4_in1_ep>;
 							};
 						};
 
-						i2s3_port: port@1 {
+						port@1 {
 							reg = <1>;
 
-							i2s3_dap_ep: endpoint {
-								dai-format = "i2s";
-								/* Place holder for external Codec */
+							amx4_in2_ep: endpoint {
+								remote-endpoint = <&xbar_amx4_in2_ep>;
 							};
 						};
-					};
-				};
 
-				i2s@2901400 {
-					status = "okay";
+						port@2 {
+							reg = <2>;
 
-					ports {
-						#address-cells = <1>;
-						#size-cells = <0>;
+							amx4_in3_ep: endpoint {
+								remote-endpoint = <&xbar_amx4_in3_ep>;
+							};
+						};
 
-						port@0 {
-							reg = <0>;
+						port@3 {
+							reg = <3>;
 
-							i2s5_cif_ep: endpoint {
-								remote-endpoint = <&xbar_i2s5_ep>;
+							amx4_in4_ep: endpoint {
+								remote-endpoint = <&xbar_amx4_in4_ep>;
 							};
 						};
 
-						i2s5_port: port@1 {
-							reg = <1>;
+						amx4_out_port: port@4 {
+							reg = <4>;
 
-							i2s5_dap_ep: endpoint@0 {
-								dai-format = "i2s";
-								/* Place holder for external Codec */
+							amx4_out_ep: endpoint {
+								remote-endpoint = <&xbar_amx4_out_ep>;
 							};
 						};
 					};
 				};
 
-				dmic@2904000 {
+				adx@2903800 {
 					status = "okay";
 
 					ports {
@@ -471,22 +1480,46 @@
 						port@0 {
 							reg = <0>;
 
-							dmic1_cif_ep: endpoint {
-								remote-endpoint = <&xbar_dmic1_ep>;
+							adx1_in_ep: endpoint {
+								remote-endpoint = <&xbar_adx1_in_ep>;
 							};
 						};
 
-						dmic1_port: port@1 {
+						adx1_out1_port: port@1 {
 							reg = <1>;
 
-							dmic1_dap_ep: endpoint {
-								/* Place holder for external Codec */
+							adx1_out1_ep: endpoint {
+								remote-endpoint = <&xbar_adx1_out1_ep>;
+							};
+						};
+
+						adx1_out2_port: port@2 {
+							reg = <2>;
+
+							adx1_out2_ep: endpoint {
+								remote-endpoint = <&xbar_adx1_out2_ep>;
+							};
+						};
+
+						adx1_out3_port: port@3 {
+							reg = <3>;
+
+							adx1_out3_ep: endpoint {
+								remote-endpoint = <&xbar_adx1_out3_ep>;
+							};
+						};
+
+						adx1_out4_port: port@4 {
+							reg = <4>;
+
+							adx1_out4_ep: endpoint {
+								remote-endpoint = <&xbar_adx1_out4_ep>;
 							};
 						};
 					};
 				};
 
-				dmic@2904100 {
+				adx@2903900 {
 					status = "okay";
 
 					ports {
@@ -496,22 +1529,46 @@
 						port@0 {
 							reg = <0>;
 
-							dmic2_cif_ep: endpoint {
-								remote-endpoint = <&xbar_dmic2_ep>;
+							adx2_in_ep: endpoint {
+								remote-endpoint = <&xbar_adx2_in_ep>;
 							};
 						};
 
-						dmic2_port: port@1 {
+						adx2_out1_port: port@1 {
 							reg = <1>;
 
-							dmic2_dap_ep: endpoint {
-								/* Place holder for external Codec */
+							adx2_out1_ep: endpoint {
+								remote-endpoint = <&xbar_adx2_out1_ep>;
+							};
+						};
+
+						adx2_out2_port: port@2 {
+							reg = <2>;
+
+							adx2_out2_ep: endpoint {
+								remote-endpoint = <&xbar_adx2_out2_ep>;
+							};
+						};
+
+						adx2_out3_port: port@3 {
+							reg = <3>;
+
+							adx2_out3_ep: endpoint {
+								remote-endpoint = <&xbar_adx2_out3_ep>;
+							};
+						};
+
+						adx2_out4_port: port@4 {
+							reg = <4>;
+
+							adx2_out4_ep: endpoint {
+								remote-endpoint = <&xbar_adx2_out4_ep>;
 							};
 						};
 					};
 				};
 
-				dmic@2904300 {
+				adx@2903a00 {
 					status = "okay";
 
 					ports {
@@ -521,22 +1578,46 @@
 						port@0 {
 							reg = <0>;
 
-							dmic4_cif_ep: endpoint {
-								remote-endpoint = <&xbar_dmic4_ep>;
+							adx3_in_ep: endpoint {
+								remote-endpoint = <&xbar_adx3_in_ep>;
 							};
 						};
 
-						dmic4_port: port@1 {
+						adx3_out1_port: port@1 {
 							reg = <1>;
 
-							dmic4_dap_ep: endpoint {
-								/* Place holder for external Codec */
+							adx3_out1_ep: endpoint {
+								remote-endpoint = <&xbar_adx3_out1_ep>;
+							};
+						};
+
+						adx3_out2_port: port@2 {
+							reg = <2>;
+
+							adx3_out2_ep: endpoint {
+								remote-endpoint = <&xbar_adx3_out2_ep>;
+							};
+						};
+
+						adx3_out3_port: port@3 {
+							reg = <3>;
+
+							adx3_out3_ep: endpoint {
+								remote-endpoint = <&xbar_adx3_out3_ep>;
+							};
+						};
+
+						adx3_out4_port: port@4 {
+							reg = <4>;
+
+							adx3_out4_ep: endpoint {
+								remote-endpoint = <&xbar_adx3_out4_ep>;
 							};
 						};
 					};
 				};
 
-				dspk@2905000 {
+				adx@2903b00 {
 					status = "okay";
 
 					ports {
@@ -546,22 +1627,46 @@
 						port@0 {
 							reg = <0>;
 
-							dspk1_cif_ep: endpoint {
-								remote-endpoint = <&xbar_dspk1_ep>;
+							adx4_in_ep: endpoint {
+								remote-endpoint = <&xbar_adx4_in_ep>;
 							};
 						};
 
-						dspk1_port: port@1 {
+						adx4_out1_port: port@1 {
 							reg = <1>;
 
-							dspk1_dap_ep: endpoint {
-								/* Place holder for external Codec */
+							adx4_out1_ep: endpoint {
+								remote-endpoint = <&xbar_adx4_out1_ep>;
+							};
+						};
+
+						adx4_out2_port: port@2 {
+							reg = <2>;
+
+							adx4_out2_ep: endpoint {
+								remote-endpoint = <&xbar_adx4_out2_ep>;
+							};
+						};
+
+						adx4_out3_port: port@3 {
+							reg = <3>;
+
+							adx4_out3_ep: endpoint {
+								remote-endpoint = <&xbar_adx4_out3_ep>;
+							};
+						};
+
+						adx4_out4_port: port@4 {
+							reg = <4>;
+
+							adx4_out4_ep: endpoint {
+								remote-endpoint = <&xbar_adx4_out4_ep>;
 							};
 						};
 					};
 				};
 
-				dspk@2905100 {
+				amixer@290bb00 {
 					status = "okay";
 
 					ports {
@@ -569,18 +1674,122 @@
 						#size-cells = <0>;
 
 						port@0 {
-							reg = <0>;
+							reg = <0x0>;
 
-							dspk2_cif_ep: endpoint {
-								remote-endpoint = <&xbar_dspk2_ep>;
+							mixer_in1_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in1_ep>;
 							};
 						};
 
-						dspk2_port: port@1 {
-							reg = <1>;
+						port@1 {
+							reg = <0x1>;
 
-							dspk2_dap_ep: endpoint {
-								/* Place holder for external Codec */
+							mixer_in2_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in2_ep>;
+							};
+						};
+
+						port@2 {
+							reg = <0x2>;
+
+							mixer_in3_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in3_ep>;
+							};
+						};
+
+						port@3 {
+							reg = <0x3>;
+
+							mixer_in4_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in4_ep>;
+							};
+						};
+
+						port@4 {
+							reg = <0x4>;
+
+							mixer_in5_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in5_ep>;
+							};
+						};
+
+						port@5 {
+							reg = <0x5>;
+
+							mixer_in6_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in6_ep>;
+							};
+						};
+
+						port@6 {
+							reg = <0x6>;
+
+							mixer_in7_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in7_ep>;
+							};
+						};
+
+						port@7 {
+							reg = <0x7>;
+
+							mixer_in8_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in8_ep>;
+							};
+						};
+
+						port@8 {
+							reg = <0x8>;
+
+							mixer_in9_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in9_ep>;
+							};
+						};
+
+						port@9 {
+							reg = <0x9>;
+
+							mixer_in10_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_in10_ep>;
+							};
+						};
+
+						mixer_out1_port: port@a {
+							reg = <0xa>;
+
+							mixer_out1_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_out1_ep>;
+							};
+						};
+
+						mixer_out2_port: port@b {
+							reg = <0xb>;
+
+							mixer_out2_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_out2_ep>;
+							};
+						};
+
+						mixer_out3_port: port@c {
+							reg = <0xc>;
+
+							mixer_out3_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_out3_ep>;
+							};
+						};
+
+						mixer_out4_port: port@d {
+							reg = <0xd>;
+
+							mixer_out4_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_out4_ep>;
+							};
+						};
+
+						mixer_out5_port: port@e {
+							reg = <0xe>;
+
+							mixer_out5_ep: endpoint {
+								remote-endpoint = <&xbar_mixer_out5_ep>;
 							};
 						};
 					};
@@ -850,6 +2059,41 @@
 		       <&xbar_i2s3_port>, <&xbar_i2s5_port>,
 		       <&xbar_dmic1_port>, <&xbar_dmic2_port>, <&xbar_dmic4_port>,
 		       <&xbar_dspk1_port>, <&xbar_dspk2_port>,
+		       <&xbar_sfc1_in_port>, <&xbar_sfc2_in_port>,
+		       <&xbar_sfc3_in_port>, <&xbar_sfc4_in_port>,
+		       <&xbar_mvc1_in_port>, <&xbar_mvc2_in_port>,
+		       <&xbar_amx1_in1_port>, <&xbar_amx1_in2_port>,
+		       <&xbar_amx1_in3_port>, <&xbar_amx1_in4_port>,
+		       <&xbar_amx2_in1_port>, <&xbar_amx2_in2_port>,
+		       <&xbar_amx2_in3_port>, <&xbar_amx2_in4_port>,
+		       <&xbar_amx3_in1_port>, <&xbar_amx3_in2_port>,
+		       <&xbar_amx3_in3_port>, <&xbar_amx3_in4_port>,
+		       <&xbar_amx4_in1_port>, <&xbar_amx4_in2_port>,
+		       <&xbar_amx4_in3_port>, <&xbar_amx4_in4_port>,
+		       <&xbar_adx1_in_port>, <&xbar_adx2_in_port>,
+		       <&xbar_adx3_in_port>, <&xbar_adx4_in_port>,
+		       <&xbar_mixer_in1_port>, <&xbar_mixer_in2_port>,
+		       <&xbar_mixer_in3_port>, <&xbar_mixer_in4_port>,
+		       <&xbar_mixer_in5_port>, <&xbar_mixer_in6_port>,
+		       <&xbar_mixer_in7_port>, <&xbar_mixer_in8_port>,
+		       <&xbar_mixer_in9_port>, <&xbar_mixer_in10_port>,
+		       /* HW accelerators */
+		       <&sfc1_out_port>, <&sfc2_out_port>,
+		       <&sfc3_out_port>, <&sfc4_out_port>,
+		       <&mvc1_out_port>, <&mvc2_out_port>,
+		       <&amx1_out_port>, <&amx2_out_port>,
+		       <&amx3_out_port>, <&amx4_out_port>,
+		       <&adx1_out1_port>, <&adx1_out2_port>,
+		       <&adx1_out3_port>, <&adx1_out4_port>,
+		       <&adx2_out1_port>, <&adx2_out2_port>,
+		       <&adx2_out3_port>, <&adx2_out4_port>,
+		       <&adx3_out1_port>, <&adx3_out2_port>,
+		       <&adx3_out3_port>, <&adx3_out4_port>,
+		       <&adx4_out1_port>, <&adx4_out2_port>,
+		       <&adx4_out3_port>, <&adx4_out4_port>,
+		       <&mixer_out1_port>, <&mixer_out2_port>,
+		       <&mixer_out3_port>, <&mixer_out4_port>,
+		       <&mixer_out5_port>,
 		       /* BE I/O Ports */
 		       <&i2s3_port>, <&i2s5_port>,
 		       <&dmic1_port>, <&dmic2_port>, <&dmic4_port>,
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts b/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts
index 7d3e363..2e17df6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts
@@ -339,6 +339,481 @@
 				};
 			};
 
+			sfc@702d2000 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc1_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc1_in_ep>;
+						};
+					};
+
+					sfc1_out_port: port@1 {
+						reg = <1>;
+
+						sfc1_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc1_out_ep>;
+						};
+					};
+				};
+			};
+
+			sfc@702d2200 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc2_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc2_in_ep>;
+						};
+					};
+
+					sfc2_out_port: port@1 {
+						reg = <1>;
+
+						sfc2_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc2_out_ep>;
+						};
+					};
+				};
+			};
+
+			sfc@702d2400 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc3_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc3_in_ep>;
+						};
+					};
+
+					sfc3_out_port: port@1 {
+						reg = <1>;
+
+						sfc3_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc3_out_ep>;
+						};
+					};
+				};
+			};
+
+			sfc@702d2600 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc4_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc4_in_ep>;
+						};
+					};
+
+					sfc4_out_port: port@1 {
+						reg = <1>;
+
+						sfc4_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc4_out_ep>;
+						};
+					};
+				};
+			};
+
+			mvc@702da000 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						mvc1_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_mvc1_in_ep>;
+						};
+					};
+
+					mvc1_out_port: port@1 {
+						reg = <1>;
+
+						mvc1_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_mvc1_out_ep>;
+						};
+					};
+				};
+			};
+
+			mvc@702da200 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						mvc2_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_mvc2_in_ep>;
+						};
+					};
+
+					mvc2_out_port: port@1 {
+						reg = <1>;
+
+						mvc2_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_mvc2_out_ep>;
+						};
+					};
+				};
+			};
+
+			amx@702d3000 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						amx1_in1_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in1_ep>;
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+
+						amx1_in2_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in2_ep>;
+						};
+					};
+
+					port@2 {
+						reg = <2>;
+
+						amx1_in3_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in3_ep>;
+						};
+					};
+
+					port@3 {
+						reg = <3>;
+
+						amx1_in4_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in4_ep>;
+						};
+					};
+
+					amx1_out_port: port@4 {
+						reg = <4>;
+
+						amx1_out_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_out_ep>;
+						};
+					};
+				};
+			};
+
+			amx@702d3100 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						amx2_in1_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in1_ep>;
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+
+						amx2_in2_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in2_ep>;
+						};
+					};
+
+					amx2_in3_port: port@2 {
+						reg = <2>;
+
+						amx2_in3_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in3_ep>;
+						};
+					};
+
+					amx2_in4_port: port@3 {
+						reg = <3>;
+
+						amx2_in4_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in4_ep>;
+						};
+					};
+
+					amx2_out_port: port@4 {
+						reg = <4>;
+
+						amx2_out_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_out_ep>;
+						};
+					};
+				};
+			};
+
+			adx@702d3800 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						adx1_in_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_in_ep>;
+						};
+					};
+
+					adx1_out1_port: port@1 {
+						reg = <1>;
+
+						adx1_out1_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out1_ep>;
+						};
+					};
+
+					adx1_out2_port: port@2 {
+						reg = <2>;
+
+						adx1_out2_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out2_ep>;
+						};
+					};
+
+					adx1_out3_port: port@3 {
+						reg = <3>;
+
+						adx1_out3_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out3_ep>;
+						};
+					};
+
+					adx1_out4_port: port@4 {
+						reg = <4>;
+
+						adx1_out4_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out4_ep>;
+						};
+					};
+				};
+			};
+
+			adx@702d3900 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						adx2_in_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_in_ep>;
+						};
+					};
+
+					adx2_out1_port: port@1 {
+						reg = <1>;
+
+						adx2_out1_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out1_ep>;
+						};
+					};
+
+					adx2_out2_port: port@2 {
+						reg = <2>;
+
+						adx2_out2_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out2_ep>;
+						};
+					};
+
+					adx2_out3_port: port@3 {
+						reg = <3>;
+
+						adx2_out3_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out3_ep>;
+						};
+					};
+
+					adx2_out4_port: port@4 {
+						reg = <4>;
+
+						adx2_out4_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out4_ep>;
+						};
+					};
+				};
+			};
+
+			amixer@702dbb00 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0x0>;
+
+						mixer_in1_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in1_ep>;
+						};
+					};
+
+					port@1 {
+						reg = <0x1>;
+
+						mixer_in2_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in2_ep>;
+						};
+					};
+
+					port@2 {
+						reg = <0x2>;
+
+						mixer_in3_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in3_ep>;
+						};
+					};
+
+					port@3 {
+						reg = <0x3>;
+
+						mixer_in4_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in4_ep>;
+						};
+					};
+
+					port@4 {
+						reg = <0x4>;
+
+						mixer_in5_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in5_ep>;
+						};
+					};
+
+					port@5 {
+						reg = <0x5>;
+
+						mixer_in6_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in6_ep>;
+						};
+					};
+
+					port@6 {
+						reg = <0x6>;
+
+						mixer_in7_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in7_ep>;
+						};
+					};
+
+					port@7 {
+						reg = <0x7>;
+
+						mixer_in8_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in8_ep>;
+						};
+					};
+
+					port@8 {
+						reg = <0x8>;
+
+						mixer_in9_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in9_ep>;
+						};
+					};
+
+					port@9 {
+						reg = <0x9>;
+
+						mixer_in10_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in10_ep>;
+						};
+					};
+
+					mixer_out1_port: port@a {
+						reg = <0xa>;
+
+						mixer_out1_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out1_ep>;
+						};
+					};
+
+					mixer_out2_port: port@b {
+						reg = <0xb>;
+
+						mixer_out2_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out2_ep>;
+						};
+					};
+
+					mixer_out3_port: port@c {
+						reg = <0xc>;
+
+						mixer_out3_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out3_ep>;
+						};
+					};
+
+					mixer_out4_port: port@d {
+						reg = <0xd>;
+
+						mixer_out4_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out4_ep>;
+						};
+					};
+
+					mixer_out5_port: port@e {
+						reg = <0xe>;
+
+						mixer_out5_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out5_ep>;
+						};
+					};
+				};
+			};
+
 			ports {
 				xbar_i2s1_port: port@a {
 					reg = <0xa>;
@@ -403,6 +878,382 @@
 						remote-endpoint = <&dmic3_cif_ep>;
 					};
 				};
+
+				xbar_sfc1_in_port: port@12 {
+					reg = <0x12>;
+
+					xbar_sfc1_in_ep: endpoint {
+						remote-endpoint = <&sfc1_cif_in_ep>;
+					};
+				};
+
+				port@13 {
+					reg = <0x13>;
+
+					xbar_sfc1_out_ep: endpoint {
+						remote-endpoint = <&sfc1_cif_out_ep>;
+					};
+				};
+
+				xbar_sfc2_in_port: port@14 {
+					reg = <0x14>;
+
+					xbar_sfc2_in_ep: endpoint {
+						remote-endpoint = <&sfc2_cif_in_ep>;
+					};
+				};
+
+				port@15 {
+					reg = <0x15>;
+
+					xbar_sfc2_out_ep: endpoint {
+						remote-endpoint = <&sfc2_cif_out_ep>;
+					};
+				};
+
+				xbar_sfc3_in_port: port@16 {
+					reg = <0x16>;
+
+					xbar_sfc3_in_ep: endpoint {
+						remote-endpoint = <&sfc3_cif_in_ep>;
+					};
+				};
+
+				port@17 {
+					reg = <0x17>;
+
+					xbar_sfc3_out_ep: endpoint {
+						remote-endpoint = <&sfc3_cif_out_ep>;
+					};
+				};
+
+				xbar_sfc4_in_port: port@18 {
+					reg = <0x18>;
+
+					xbar_sfc4_in_ep: endpoint {
+						remote-endpoint = <&sfc4_cif_in_ep>;
+					};
+				};
+
+				port@19 {
+					reg = <0x19>;
+
+					xbar_sfc4_out_ep: endpoint {
+						remote-endpoint = <&sfc4_cif_out_ep>;
+					};
+				};
+
+				xbar_mvc1_in_port: port@1a {
+					reg = <0x1a>;
+
+					xbar_mvc1_in_ep: endpoint {
+						remote-endpoint = <&mvc1_cif_in_ep>;
+					};
+				};
+
+				port@1b {
+					reg = <0x1b>;
+
+					xbar_mvc1_out_ep: endpoint {
+						remote-endpoint = <&mvc1_cif_out_ep>;
+					};
+				};
+
+				xbar_mvc2_in_port: port@1c {
+					reg = <0x1c>;
+
+					xbar_mvc2_in_ep: endpoint {
+						remote-endpoint = <&mvc2_cif_in_ep>;
+					};
+				};
+
+				port@1d {
+					reg = <0x1d>;
+
+					xbar_mvc2_out_ep: endpoint {
+						remote-endpoint = <&mvc2_cif_out_ep>;
+					};
+				};
+
+				xbar_amx1_in1_port: port@1e {
+					reg = <0x1e>;
+
+					xbar_amx1_in1_ep: endpoint {
+						remote-endpoint = <&amx1_in1_ep>;
+					};
+				};
+
+				xbar_amx1_in2_port: port@1f {
+					reg = <0x1f>;
+
+					xbar_amx1_in2_ep: endpoint {
+						remote-endpoint = <&amx1_in2_ep>;
+					};
+				};
+
+				xbar_amx1_in3_port: port@20 {
+					reg = <0x20>;
+
+					xbar_amx1_in3_ep: endpoint {
+						remote-endpoint = <&amx1_in3_ep>;
+					};
+				};
+
+				xbar_amx1_in4_port: port@21 {
+					reg = <0x21>;
+
+					xbar_amx1_in4_ep: endpoint {
+						remote-endpoint = <&amx1_in4_ep>;
+					};
+				};
+
+				port@22 {
+					reg = <0x22>;
+
+					xbar_amx1_out_ep: endpoint {
+						remote-endpoint = <&amx1_out_ep>;
+					};
+				};
+
+				xbar_amx2_in1_port: port@23 {
+					reg = <0x23>;
+
+					xbar_amx2_in1_ep: endpoint {
+						remote-endpoint = <&amx2_in1_ep>;
+					};
+				};
+
+				xbar_amx2_in2_port: port@24 {
+					reg = <0x24>;
+
+					xbar_amx2_in2_ep: endpoint {
+						remote-endpoint = <&amx2_in2_ep>;
+					};
+				};
+
+				xbar_amx2_in3_port: port@25 {
+					reg = <0x25>;
+
+					xbar_amx2_in3_ep: endpoint {
+						remote-endpoint = <&amx2_in3_ep>;
+					};
+				};
+
+				xbar_amx2_in4_port: port@26 {
+					reg = <0x26>;
+
+					xbar_amx2_in4_ep: endpoint {
+						remote-endpoint = <&amx2_in4_ep>;
+					};
+				};
+
+				port@27 {
+					reg = <0x27>;
+
+					xbar_amx2_out_ep: endpoint {
+						remote-endpoint = <&amx2_out_ep>;
+					};
+				};
+
+				xbar_adx1_in_port: port@28 {
+					reg = <0x28>;
+
+					xbar_adx1_in_ep: endpoint {
+						remote-endpoint = <&adx1_in_ep>;
+					};
+				};
+
+				port@29 {
+					reg = <0x29>;
+
+					xbar_adx1_out1_ep: endpoint {
+						remote-endpoint = <&adx1_out1_ep>;
+					};
+				};
+
+				port@2a {
+					reg = <0x2a>;
+
+					xbar_adx1_out2_ep: endpoint {
+						remote-endpoint = <&adx1_out2_ep>;
+					};
+				};
+
+				port@2b {
+					reg = <0x2b>;
+
+					xbar_adx1_out3_ep: endpoint {
+						remote-endpoint = <&adx1_out3_ep>;
+					};
+				};
+
+				port@2c {
+					reg = <0x2c>;
+
+					xbar_adx1_out4_ep: endpoint {
+						remote-endpoint = <&adx1_out4_ep>;
+					};
+				};
+
+				xbar_adx2_in_port: port@2d {
+					reg = <0x2d>;
+
+					xbar_adx2_in_ep: endpoint {
+						remote-endpoint = <&adx2_in_ep>;
+					};
+				};
+
+				port@2e {
+					reg = <0x2e>;
+
+					xbar_adx2_out1_ep: endpoint {
+						remote-endpoint = <&adx2_out1_ep>;
+					};
+				};
+
+				port@2f {
+					reg = <0x2f>;
+
+					xbar_adx2_out2_ep: endpoint {
+						remote-endpoint = <&adx2_out2_ep>;
+					};
+				};
+
+				port@30 {
+					reg = <0x30>;
+
+					xbar_adx2_out3_ep: endpoint {
+						remote-endpoint = <&adx2_out3_ep>;
+					};
+				};
+
+				port@31 {
+					reg = <0x31>;
+
+					xbar_adx2_out4_ep: endpoint {
+						remote-endpoint = <&adx2_out4_ep>;
+					};
+				};
+
+				xbar_mixer_in1_port: port@32 {
+					reg = <0x32>;
+
+					xbar_mixer_in1_ep: endpoint {
+						remote-endpoint = <&mixer_in1_ep>;
+					};
+				};
+
+				xbar_mixer_in2_port: port@33 {
+					reg = <0x33>;
+
+					xbar_mixer_in2_ep: endpoint {
+						remote-endpoint = <&mixer_in2_ep>;
+					};
+				};
+
+				xbar_mixer_in3_port: port@34 {
+					reg = <0x34>;
+
+					xbar_mixer_in3_ep: endpoint {
+						remote-endpoint = <&mixer_in3_ep>;
+					};
+				};
+
+				xbar_mixer_in4_port: port@35 {
+					reg = <0x35>;
+
+					xbar_mixer_in4_ep: endpoint {
+						remote-endpoint = <&mixer_in4_ep>;
+					};
+				};
+
+				xbar_mixer_in5_port: port@36 {
+					reg = <0x36>;
+
+					xbar_mixer_in5_ep: endpoint {
+						remote-endpoint = <&mixer_in5_ep>;
+					};
+				};
+
+				xbar_mixer_in6_port: port@37 {
+					reg = <0x37>;
+
+					xbar_mixer_in6_ep: endpoint {
+						remote-endpoint = <&mixer_in6_ep>;
+					};
+				};
+
+				xbar_mixer_in7_port: port@38 {
+					reg = <0x38>;
+
+					xbar_mixer_in7_ep: endpoint {
+						remote-endpoint = <&mixer_in7_ep>;
+					};
+				};
+
+				xbar_mixer_in8_port: port@39 {
+					reg = <0x39>;
+
+					xbar_mixer_in8_ep: endpoint {
+						remote-endpoint = <&mixer_in8_ep>;
+					};
+				};
+
+				xbar_mixer_in9_port: port@3a {
+					reg = <0x3a>;
+
+					xbar_mixer_in9_ep: endpoint {
+						remote-endpoint = <&mixer_in9_ep>;
+					};
+				};
+
+				xbar_mixer_in10_port: port@3b {
+					reg = <0x3b>;
+
+					xbar_mixer_in10_ep: endpoint {
+						remote-endpoint = <&mixer_in10_ep>;
+					};
+				};
+
+				port@3c {
+					reg = <0x3c>;
+
+					xbar_mixer_out1_ep: endpoint {
+						remote-endpoint = <&mixer_out1_ep>;
+					};
+				};
+
+				port@3d {
+					reg = <0x3d>;
+
+					xbar_mixer_out2_ep: endpoint {
+						remote-endpoint = <&mixer_out2_ep>;
+					};
+				};
+
+				port@3e {
+					reg = <0x3e>;
+
+					xbar_mixer_out3_ep: endpoint {
+						remote-endpoint = <&mixer_out3_ep>;
+					};
+				};
+
+				port@3f {
+					reg = <0x3f>;
+
+					xbar_mixer_out4_ep: endpoint {
+						remote-endpoint = <&mixer_out4_ep>;
+					};
+				};
+
+				port@40 {
+					reg = <0x40>;
+
+					xbar_mixer_out5_ep: endpoint {
+						remote-endpoint = <&mixer_out5_ep>;
+					};
+				};
 			};
 		};
 	};
@@ -420,6 +1271,31 @@
 		       <&xbar_i2s1_port>, <&xbar_i2s2_port>, <&xbar_i2s3_port>,
 		       <&xbar_i2s4_port>, <&xbar_i2s5_port>, <&xbar_dmic1_port>,
 		       <&xbar_dmic2_port>, <&xbar_dmic3_port>,
+		       <&xbar_sfc1_in_port>, <&xbar_sfc2_in_port>,
+		       <&xbar_sfc3_in_port>, <&xbar_sfc4_in_port>,
+		       <&xbar_mvc1_in_port>, <&xbar_mvc2_in_port>,
+		       <&xbar_amx1_in1_port>, <&xbar_amx1_in2_port>,
+		       <&xbar_amx1_in3_port>, <&xbar_amx1_in4_port>,
+		       <&xbar_amx2_in1_port>, <&xbar_amx2_in2_port>,
+		       <&xbar_amx2_in3_port>, <&xbar_amx2_in4_port>,
+		       <&xbar_adx1_in_port>, <&xbar_adx2_in_port>,
+		       <&xbar_mixer_in1_port>, <&xbar_mixer_in2_port>,
+		       <&xbar_mixer_in3_port>, <&xbar_mixer_in4_port>,
+		       <&xbar_mixer_in5_port>, <&xbar_mixer_in6_port>,
+		       <&xbar_mixer_in7_port>, <&xbar_mixer_in8_port>,
+		       <&xbar_mixer_in9_port>, <&xbar_mixer_in10_port>,
+		       /* HW accelerators */
+		       <&sfc1_out_port>, <&sfc2_out_port>,
+		       <&sfc3_out_port>, <&sfc4_out_port>,
+		       <&mvc1_out_port>, <&mvc2_out_port>,
+		       <&amx1_out_port>, <&amx2_out_port>,
+		       <&adx1_out1_port>, <&adx1_out2_port>,
+		       <&adx1_out3_port>, <&adx1_out4_port>,
+		       <&adx2_out1_port>, <&adx2_out2_port>,
+		       <&adx2_out3_port>, <&adx2_out4_port>,
+		       <&mixer_out1_port>, <&mixer_out2_port>,
+		       <&mixer_out3_port>, <&mixer_out4_port>,
+		       <&mixer_out5_port>,
 		       /* I/O DAP Ports */
 		       <&i2s1_port>, <&i2s2_port>, <&i2s3_port>, <&i2s4_port>,
 		       <&i2s5_port>, <&dmic1_port>, <&dmic2_port>, <&dmic3_port>;
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
index 7dbb13f..030f264 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
@@ -746,6 +746,481 @@
 				};
 			};
 
+			sfc@702d2000 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc1_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc1_in_ep>;
+						};
+					};
+
+					sfc1_out_port: port@1 {
+						reg = <1>;
+
+						sfc1_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc1_out_ep>;
+						};
+					};
+				};
+			};
+
+			sfc@702d2200 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc2_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc2_in_ep>;
+						};
+					};
+
+					sfc2_out_port: port@1 {
+						reg = <1>;
+
+						sfc2_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc2_out_ep>;
+						};
+					};
+				};
+			};
+
+			sfc@702d2400 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc3_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc3_in_ep>;
+						};
+					};
+
+					sfc3_out_port: port@1 {
+						reg = <1>;
+
+						sfc3_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc3_out_ep>;
+						};
+					};
+				};
+			};
+
+			sfc@702d2600 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						sfc4_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_sfc4_in_ep>;
+						};
+					};
+
+					sfc4_out_port: port@1 {
+						reg = <1>;
+
+						sfc4_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_sfc4_out_ep>;
+						};
+					};
+				};
+			};
+
+			mvc@702da000 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						mvc1_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_mvc1_in_ep>;
+						};
+					};
+
+					mvc1_out_port: port@1 {
+						reg = <1>;
+
+						mvc1_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_mvc1_out_ep>;
+						};
+					};
+				};
+			};
+
+			mvc@702da200 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						mvc2_cif_in_ep: endpoint {
+							remote-endpoint = <&xbar_mvc2_in_ep>;
+						};
+					};
+
+					mvc2_out_port: port@1 {
+						reg = <1>;
+
+						mvc2_cif_out_ep: endpoint {
+							remote-endpoint = <&xbar_mvc2_out_ep>;
+						};
+					};
+				};
+			};
+
+			amx@702d3000 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						amx1_in1_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in1_ep>;
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+
+						amx1_in2_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in2_ep>;
+						};
+					};
+
+					port@2 {
+						reg = <2>;
+
+						amx1_in3_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in3_ep>;
+						};
+					};
+
+					port@3 {
+						reg = <3>;
+
+						amx1_in4_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_in4_ep>;
+						};
+					};
+
+					amx1_out_port: port@4 {
+						reg = <4>;
+
+						amx1_out_ep: endpoint {
+							remote-endpoint = <&xbar_amx1_out_ep>;
+						};
+					};
+				};
+			};
+
+			amx@702d3100 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						amx2_in1_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in1_ep>;
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+
+						amx2_in2_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in2_ep>;
+						};
+					};
+
+					amx2_in3_port: port@2 {
+						reg = <2>;
+
+						amx2_in3_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in3_ep>;
+						};
+					};
+
+					amx2_in4_port: port@3 {
+						reg = <3>;
+
+						amx2_in4_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_in4_ep>;
+						};
+					};
+
+					amx2_out_port: port@4 {
+						reg = <4>;
+
+						amx2_out_ep: endpoint {
+							remote-endpoint = <&xbar_amx2_out_ep>;
+						};
+					};
+				};
+			};
+
+			adx@702d3800 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						adx1_in_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_in_ep>;
+						};
+					};
+
+					adx1_out1_port: port@1 {
+						reg = <1>;
+
+						adx1_out1_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out1_ep>;
+						};
+					};
+
+					adx1_out2_port: port@2 {
+						reg = <2>;
+
+						adx1_out2_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out2_ep>;
+						};
+					};
+
+					adx1_out3_port: port@3 {
+						reg = <3>;
+
+						adx1_out3_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out3_ep>;
+						};
+					};
+
+					adx1_out4_port: port@4 {
+						reg = <4>;
+
+						adx1_out4_ep: endpoint {
+							remote-endpoint = <&xbar_adx1_out4_ep>;
+						};
+					};
+				};
+			};
+
+			adx@702d3900 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						adx2_in_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_in_ep>;
+						};
+					};
+
+					adx2_out1_port: port@1 {
+						reg = <1>;
+
+						adx2_out1_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out1_ep>;
+						};
+					};
+
+					adx2_out2_port: port@2 {
+						reg = <2>;
+
+						adx2_out2_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out2_ep>;
+						};
+					};
+
+					adx2_out3_port: port@3 {
+						reg = <3>;
+
+						adx2_out3_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out3_ep>;
+						};
+					};
+
+					adx2_out4_port: port@4 {
+						reg = <4>;
+
+						adx2_out4_ep: endpoint {
+							remote-endpoint = <&xbar_adx2_out4_ep>;
+						};
+					};
+				};
+			};
+
+			amixer@702dbb00 {
+				status = "okay";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0x0>;
+
+						mixer_in1_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in1_ep>;
+						};
+					};
+
+					port@1 {
+						reg = <0x1>;
+
+						mixer_in2_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in2_ep>;
+						};
+					};
+
+					port@2 {
+						reg = <0x2>;
+
+						mixer_in3_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in3_ep>;
+						};
+					};
+
+					port@3 {
+						reg = <0x3>;
+
+						mixer_in4_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in4_ep>;
+						};
+					};
+
+					port@4 {
+						reg = <0x4>;
+
+						mixer_in5_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in5_ep>;
+						};
+					};
+
+					port@5 {
+						reg = <0x5>;
+
+						mixer_in6_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in6_ep>;
+						};
+					};
+
+					port@6 {
+						reg = <0x6>;
+
+						mixer_in7_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in7_ep>;
+						};
+					};
+
+					port@7 {
+						reg = <0x7>;
+
+						mixer_in8_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in8_ep>;
+						};
+					};
+
+					port@8 {
+						reg = <0x8>;
+
+						mixer_in9_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in9_ep>;
+						};
+					};
+
+					port@9 {
+						reg = <0x9>;
+
+						mixer_in10_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_in10_ep>;
+						};
+					};
+
+					mixer_out1_port: port@a {
+						reg = <0xa>;
+
+						mixer_out1_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out1_ep>;
+						};
+					};
+
+					mixer_out2_port: port@b {
+						reg = <0xb>;
+
+						mixer_out2_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out2_ep>;
+						};
+					};
+
+					mixer_out3_port: port@c {
+						reg = <0xc>;
+
+						mixer_out3_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out3_ep>;
+						};
+					};
+
+					mixer_out4_port: port@d {
+						reg = <0xd>;
+
+						mixer_out4_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out4_ep>;
+						};
+					};
+
+					mixer_out5_port: port@e {
+						reg = <0xe>;
+
+						mixer_out5_ep: endpoint {
+							remote-endpoint = <&xbar_mixer_out5_ep>;
+						};
+					};
+				};
+			};
+
 			ports {
 				xbar_i2s3_port: port@c {
 					reg = <0xc>;
@@ -778,6 +1253,382 @@
 						remote-endpoint = <&dmic2_cif_ep>;
 					};
 				};
+
+				xbar_sfc1_in_port: port@12 {
+					reg = <0x12>;
+
+					xbar_sfc1_in_ep: endpoint {
+						remote-endpoint = <&sfc1_cif_in_ep>;
+					};
+				};
+
+				port@13 {
+					reg = <0x13>;
+
+					xbar_sfc1_out_ep: endpoint {
+						remote-endpoint = <&sfc1_cif_out_ep>;
+					};
+				};
+
+				xbar_sfc2_in_port: port@14 {
+					reg = <0x14>;
+
+					xbar_sfc2_in_ep: endpoint {
+						remote-endpoint = <&sfc2_cif_in_ep>;
+					};
+				};
+
+				port@15 {
+					reg = <0x15>;
+
+					xbar_sfc2_out_ep: endpoint {
+						remote-endpoint = <&sfc2_cif_out_ep>;
+					};
+				};
+
+				xbar_sfc3_in_port: port@16 {
+					reg = <0x16>;
+
+					xbar_sfc3_in_ep: endpoint {
+						remote-endpoint = <&sfc3_cif_in_ep>;
+					};
+				};
+
+				port@17 {
+					reg = <0x17>;
+
+					xbar_sfc3_out_ep: endpoint {
+						remote-endpoint = <&sfc3_cif_out_ep>;
+					};
+				};
+
+				xbar_sfc4_in_port: port@18 {
+					reg = <0x18>;
+
+					xbar_sfc4_in_ep: endpoint {
+						remote-endpoint = <&sfc4_cif_in_ep>;
+					};
+				};
+
+				port@19 {
+					reg = <0x19>;
+
+					xbar_sfc4_out_ep: endpoint {
+						remote-endpoint = <&sfc4_cif_out_ep>;
+					};
+				};
+
+				xbar_mvc1_in_port: port@1a {
+					reg = <0x1a>;
+
+					xbar_mvc1_in_ep: endpoint {
+						remote-endpoint = <&mvc1_cif_in_ep>;
+					};
+				};
+
+				port@1b {
+					reg = <0x1b>;
+
+					xbar_mvc1_out_ep: endpoint {
+						remote-endpoint = <&mvc1_cif_out_ep>;
+					};
+				};
+
+				xbar_mvc2_in_port: port@1c {
+					reg = <0x1c>;
+
+					xbar_mvc2_in_ep: endpoint {
+						remote-endpoint = <&mvc2_cif_in_ep>;
+					};
+				};
+
+				port@1d {
+					reg = <0x1d>;
+
+					xbar_mvc2_out_ep: endpoint {
+						remote-endpoint = <&mvc2_cif_out_ep>;
+					};
+				};
+
+				xbar_amx1_in1_port: port@1e {
+					reg = <0x1e>;
+
+					xbar_amx1_in1_ep: endpoint {
+						remote-endpoint = <&amx1_in1_ep>;
+					};
+				};
+
+				xbar_amx1_in2_port: port@1f {
+					reg = <0x1f>;
+
+					xbar_amx1_in2_ep: endpoint {
+						remote-endpoint = <&amx1_in2_ep>;
+					};
+				};
+
+				xbar_amx1_in3_port: port@20 {
+					reg = <0x20>;
+
+					xbar_amx1_in3_ep: endpoint {
+						remote-endpoint = <&amx1_in3_ep>;
+					};
+				};
+
+				xbar_amx1_in4_port: port@21 {
+					reg = <0x21>;
+
+					xbar_amx1_in4_ep: endpoint {
+						remote-endpoint = <&amx1_in4_ep>;
+					};
+				};
+
+				port@22 {
+					reg = <0x22>;
+
+					xbar_amx1_out_ep: endpoint {
+						remote-endpoint = <&amx1_out_ep>;
+					};
+				};
+
+				xbar_amx2_in1_port: port@23 {
+					reg = <0x23>;
+
+					xbar_amx2_in1_ep: endpoint {
+						remote-endpoint = <&amx2_in1_ep>;
+					};
+				};
+
+				xbar_amx2_in2_port: port@24 {
+					reg = <0x24>;
+
+					xbar_amx2_in2_ep: endpoint {
+						remote-endpoint = <&amx2_in2_ep>;
+					};
+				};
+
+				xbar_amx2_in3_port: port@25 {
+					reg = <0x25>;
+
+					xbar_amx2_in3_ep: endpoint {
+						remote-endpoint = <&amx2_in3_ep>;
+					};
+				};
+
+				xbar_amx2_in4_port: port@26 {
+					reg = <0x26>;
+
+					xbar_amx2_in4_ep: endpoint {
+						remote-endpoint = <&amx2_in4_ep>;
+					};
+				};
+
+				port@27 {
+					reg = <0x27>;
+
+					xbar_amx2_out_ep: endpoint {
+						remote-endpoint = <&amx2_out_ep>;
+					};
+				};
+
+				xbar_adx1_in_port: port@28 {
+					reg = <0x28>;
+
+					xbar_adx1_in_ep: endpoint {
+						remote-endpoint = <&adx1_in_ep>;
+					};
+				};
+
+				port@29 {
+					reg = <0x29>;
+
+					xbar_adx1_out1_ep: endpoint {
+						remote-endpoint = <&adx1_out1_ep>;
+					};
+				};
+
+				port@2a {
+					reg = <0x2a>;
+
+					xbar_adx1_out2_ep: endpoint {
+						remote-endpoint = <&adx1_out2_ep>;
+					};
+				};
+
+				port@2b {
+					reg = <0x2b>;
+
+					xbar_adx1_out3_ep: endpoint {
+						remote-endpoint = <&adx1_out3_ep>;
+					};
+				};
+
+				port@2c {
+					reg = <0x2c>;
+
+					xbar_adx1_out4_ep: endpoint {
+						remote-endpoint = <&adx1_out4_ep>;
+					};
+				};
+
+				xbar_adx2_in_port: port@2d {
+					reg = <0x2d>;
+
+					xbar_adx2_in_ep: endpoint {
+						remote-endpoint = <&adx2_in_ep>;
+					};
+				};
+
+				port@2e {
+					reg = <0x2e>;
+
+					xbar_adx2_out1_ep: endpoint {
+						remote-endpoint = <&adx2_out1_ep>;
+					};
+				};
+
+				port@2f {
+					reg = <0x2f>;
+
+					xbar_adx2_out2_ep: endpoint {
+						remote-endpoint = <&adx2_out2_ep>;
+					};
+				};
+
+				port@30 {
+					reg = <0x30>;
+
+					xbar_adx2_out3_ep: endpoint {
+						remote-endpoint = <&adx2_out3_ep>;
+					};
+				};
+
+				port@31 {
+					reg = <0x31>;
+
+					xbar_adx2_out4_ep: endpoint {
+						remote-endpoint = <&adx2_out4_ep>;
+					};
+				};
+
+				xbar_mixer_in1_port: port@32 {
+					reg = <0x32>;
+
+					xbar_mixer_in1_ep: endpoint {
+						remote-endpoint = <&mixer_in1_ep>;
+					};
+				};
+
+				xbar_mixer_in2_port: port@33 {
+					reg = <0x33>;
+
+					xbar_mixer_in2_ep: endpoint {
+						remote-endpoint = <&mixer_in2_ep>;
+					};
+				};
+
+				xbar_mixer_in3_port: port@34 {
+					reg = <0x34>;
+
+					xbar_mixer_in3_ep: endpoint {
+						remote-endpoint = <&mixer_in3_ep>;
+					};
+				};
+
+				xbar_mixer_in4_port: port@35 {
+					reg = <0x35>;
+
+					xbar_mixer_in4_ep: endpoint {
+						remote-endpoint = <&mixer_in4_ep>;
+					};
+				};
+
+				xbar_mixer_in5_port: port@36 {
+					reg = <0x36>;
+
+					xbar_mixer_in5_ep: endpoint {
+						remote-endpoint = <&mixer_in5_ep>;
+					};
+				};
+
+				xbar_mixer_in6_port: port@37 {
+					reg = <0x37>;
+
+					xbar_mixer_in6_ep: endpoint {
+						remote-endpoint = <&mixer_in6_ep>;
+					};
+				};
+
+				xbar_mixer_in7_port: port@38 {
+					reg = <0x38>;
+
+					xbar_mixer_in7_ep: endpoint {
+						remote-endpoint = <&mixer_in7_ep>;
+					};
+				};
+
+				xbar_mixer_in8_port: port@39 {
+					reg = <0x39>;
+
+					xbar_mixer_in8_ep: endpoint {
+						remote-endpoint = <&mixer_in8_ep>;
+					};
+				};
+
+				xbar_mixer_in9_port: port@3a {
+					reg = <0x3a>;
+
+					xbar_mixer_in9_ep: endpoint {
+						remote-endpoint = <&mixer_in9_ep>;
+					};
+				};
+
+				xbar_mixer_in10_port: port@3b {
+					reg = <0x3b>;
+
+					xbar_mixer_in10_ep: endpoint {
+						remote-endpoint = <&mixer_in10_ep>;
+					};
+				};
+
+				port@3c {
+					reg = <0x3c>;
+
+					xbar_mixer_out1_ep: endpoint {
+						remote-endpoint = <&mixer_out1_ep>;
+					};
+				};
+
+				port@3d {
+					reg = <0x3d>;
+
+					xbar_mixer_out2_ep: endpoint {
+						remote-endpoint = <&mixer_out2_ep>;
+					};
+				};
+
+				port@3e {
+					reg = <0x3e>;
+
+					xbar_mixer_out3_ep: endpoint {
+						remote-endpoint = <&mixer_out3_ep>;
+					};
+				};
+
+				port@3f {
+					reg = <0x3f>;
+
+					xbar_mixer_out4_ep: endpoint {
+						remote-endpoint = <&mixer_out4_ep>;
+					};
+				};
+
+				port@40 {
+					reg = <0x40>;
+
+					xbar_mixer_out5_ep: endpoint {
+						remote-endpoint = <&mixer_out5_ep>;
+					};
+				};
 			};
 		};
 	};
@@ -1039,6 +1890,31 @@
 		       /* Router */
 		       <&xbar_i2s3_port>, <&xbar_i2s4_port>,
 		       <&xbar_dmic1_port>, <&xbar_dmic2_port>,
+		       <&xbar_sfc1_in_port>, <&xbar_sfc2_in_port>,
+		       <&xbar_sfc3_in_port>, <&xbar_sfc4_in_port>,
+		       <&xbar_mvc1_in_port>, <&xbar_mvc2_in_port>,
+		       <&xbar_amx1_in1_port>, <&xbar_amx1_in2_port>,
+		       <&xbar_amx1_in3_port>, <&xbar_amx1_in4_port>,
+		       <&xbar_amx2_in1_port>, <&xbar_amx2_in2_port>,
+		       <&xbar_amx2_in3_port>, <&xbar_amx2_in4_port>,
+		       <&xbar_adx1_in_port>, <&xbar_adx2_in_port>,
+		       <&xbar_mixer_in1_port>, <&xbar_mixer_in2_port>,
+		       <&xbar_mixer_in3_port>, <&xbar_mixer_in4_port>,
+		       <&xbar_mixer_in5_port>, <&xbar_mixer_in6_port>,
+		       <&xbar_mixer_in7_port>, <&xbar_mixer_in8_port>,
+		       <&xbar_mixer_in9_port>, <&xbar_mixer_in10_port>,
+		       /* HW accelerators */
+		       <&sfc1_out_port>, <&sfc2_out_port>,
+		       <&sfc3_out_port>, <&sfc4_out_port>,
+		       <&mvc1_out_port>, <&mvc2_out_port>,
+		       <&amx1_out_port>, <&amx2_out_port>,
+		       <&adx1_out1_port>, <&adx1_out2_port>,
+		       <&adx1_out3_port>, <&adx1_out4_port>,
+		       <&adx2_out1_port>, <&adx2_out2_port>,
+		       <&adx2_out3_port>, <&adx2_out4_port>,
+		       <&mixer_out1_port>, <&mixer_out2_port>,
+		       <&mixer_out3_port>, <&mixer_out4_port>,
+		       <&mixer_out5_port>,
 		       /* I/O DAP Ports */
 		       <&i2s3_port>, <&i2s4_port>,
 		       <&dmic1_port>, <&dmic2_port>;
-- 
2.7.4


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

* Re: [PATCH 04/13] ASoC: dt-bindings: tegra: Few more Tegra210 AHUB modules
  2021-08-27  9:33 ` [PATCH 04/13] ASoC: dt-bindings: tegra: Few more Tegra210 AHUB modules Sameer Pujar
@ 2021-08-31 20:21   ` Rob Herring
  2021-09-01  7:09     ` Sameer Pujar
  0 siblings, 1 reply; 29+ messages in thread
From: Rob Herring @ 2021-08-31 20:21 UTC (permalink / raw)
  To: Sameer Pujar
  Cc: broonie, lgirdwood, thierry.reding, jonathanh, catalin.marinas,
	will, perex, tiwai, kuninori.morimoto.gx, sharadg, alsa-devel,
	devicetree, linux-tegra, linux-kernel, linux-arm-kernel

On Fri, Aug 27, 2021 at 03:03:50PM +0530, Sameer Pujar wrote:
> This patch adds YAML schema for DT bindings of few AHUB modules.
> These devices will be registered as ASoC components and bindings
> will be used on Tegra210 and later chips. The bindings for below
> mentioned modules are added:
> 
>  * SFC (Sampling Frequency Converter)
>  * MVC (Master Volume Control)
>  * AMX (Audio Multiplexer)
>  * ADX (Audio Demultiplexer)
>  * Mixer
> 
> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> Cc: Rob Herring <robh+dt@kernel.org> 
> ---
>  .../bindings/sound/nvidia,tegra210-adx.yaml        | 74 ++++++++++++++++++++
>  .../bindings/sound/nvidia,tegra210-ahub.yaml       | 20 ++++++
>  .../bindings/sound/nvidia,tegra210-amx.yaml        | 72 ++++++++++++++++++++
>  .../bindings/sound/nvidia,tegra210-mixer.yaml      | 67 ++++++++++++++++++
>  .../bindings/sound/nvidia,tegra210-mvc.yaml        | 79 ++++++++++++++++++++++
>  .../bindings/sound/nvidia,tegra210-sfc.yaml        | 76 +++++++++++++++++++++
>  6 files changed, 388 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
>  create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
>  create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
>  create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
>  create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml
> 
> diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
> new file mode 100644
> index 0000000..9950585
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
> @@ -0,0 +1,74 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-adx.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Tegra210 ADX Device Tree Bindings
> +
> +description: |
> +  The Audio Demultiplexer (ADX) block takes an input stream with   up to

extra spaces.

> +  16 channels and demultiplexes it into four output streams of up to 16
> +  channels each. A byte RAM helps to form output frames by any combination
> +  of bytes from the input frame. Its design is identical to that of byte
> +  RAM in the AMX except that the data flow direction is reversed.
> +
> +maintainers:
> +  - Jon Hunter <jonathanh@nvidia.com>
> +  - Mohan Kumar <mkumard@nvidia.com>
> +  - Sameer Pujar <spujar@nvidia.com>
> +
> +properties:
> +  $nodename:
> +    pattern: "^adx@[0-9a-f]*$"
> +
> +  compatible:
> +    oneOf:
> +      - const: nvidia,tegra210-adx
> +      - items:
> +          - enum:
> +              - nvidia,tegra194-adx
> +              - nvidia,tegra186-adx
> +          - const: nvidia,tegra210-adx
> +
> +  reg:
> +    maxItems: 1
> +
> +  sound-name-prefix:

nvidia,sound-name-prefix

> +    pattern: "^ADX[1-9]$"
> +    $ref: /schemas/types.yaml#/definitions/string
> +    description:
> +      used as prefix for sink/source names of the component. Must be a
> +      unique string among multiple instances of the same component.
> +      The name can be "ADX1" or "ADX2" ... "ADXx", where x depends on
> +      the maximum available instances on a Tegra SoC.
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +    description: |
> +      ADX has one input and four output. Accordingly ACIF (Audio Client

You need to define the port numbers for the input and each output.

> +      Interface) RX and TX port nodes are defined to represent ADX inputs
> +      and output respectively. These are connected to corresponding ports
> +      on AHUB.
> +
> +    patternProperties:
> +      '^port@[0-9]':

Per above, this will need to be split at least into input and output 
ports.

Same issues in the other schemas.

> +        $ref: audio-graph-port.yaml#
> +        unevaluatedProperties: false
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +
> +    adx@702d3800 {
> +        compatible = "nvidia,tegra210-adx";
> +        reg = <0x702d3800 0x100>;
> +        sound-name-prefix = "ADX1";
> +    };
> +
> +...
> diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml
> index 1118a94..4087eeb 100644
> --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml
> +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml
> @@ -85,6 +85,26 @@ patternProperties:
>      type: object
>      $ref: nvidia,tegra186-dspk.yaml#
>  
> +  '^mvc@[0-9a-f]+$':
> +    type: object
> +    $ref: nvidia,tegra210-mvc.yaml#
> +
> +  '^sfc@[0-9a-f]+$':
> +    type: object
> +    $ref: nvidia,tegra210-sfc.yaml#
> +
> +  '^amx@[0-9a-f]+$':
> +    type: object
> +    $ref: nvidia,tegra210-amx.yaml#
> +
> +  '^adx@[0-9a-f]+$':
> +    type: object
> +    $ref: nvidia,tegra210-adx.yaml#
> +
> +  '^mixer@[0-9a-f]+$':
> +    type: object
> +    $ref: nvidia,tegra210-mixer.yaml#
> +
>  required:
>    - compatible
>    - reg
> diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
> new file mode 100644
> index 0000000..e6b365b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
> @@ -0,0 +1,72 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-amx.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Tegra210 AMX Device Tree Bindings
> +
> +description: |
> +  The Audio Multiplexer (AMX) block can multiplex up to four input streams
> +  each of which can have maximum 16 channels and generate an output stream
> +  with maximum 16 channels. A byte RAM helps to form an output frame by
> +  any combination of bytes from the input frames.
> +
> +maintainers:
> +  - Jon Hunter <jonathanh@nvidia.com>
> +  - Mohan Kumar <mkumard@nvidia.com>
> +  - Sameer Pujar <spujar@nvidia.com>
> +
> +properties:
> +  $nodename:
> +    pattern: "^amx@[0-9a-f]*$"
> +
> +  compatible:
> +    oneOf:
> +      - const: nvidia,tegra210-amx
> +      - items:
> +          - const: nvidia,tegra186-amx
> +          - const: nvidia,tegra210-amx
> +      - const: nvidia,tegra194-amx
> +
> +  reg:
> +    maxItems: 1
> +
> +  sound-name-prefix:
> +    pattern: "^AMX[1-9]$"
> +    $ref: /schemas/types.yaml#/definitions/string
> +    description:
> +      used as prefix for sink/source names of the component. Must be a
> +      unique string among multiple instances of the same component.
> +      The name can be "AMX1" or "AMX2" ... "AMXx", where x depends on
> +      the maximum available instances on a Tegra SoC.
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +    description: |
> +      AMX has four inputs and one output. Accordingly ACIF (Audio Client
> +      Interfaces) RX and TX port nodes are defined to represent AMX inputs
> +      and output respectively. These are connected to corresponding ports
> +      on AHUB.
> +
> +    patternProperties:
> +      '^port@[0-9]':
> +        $ref: audio-graph-port.yaml#
> +        unevaluatedProperties: false
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +
> +    amx@702d3000 {
> +        compatible = "nvidia,tegra210-amx";
> +        reg = <0x702d3000 0x100>;
> +        sound-name-prefix = "AMX1";
> +    };
> +
> +...
> diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
> new file mode 100644
> index 0000000..0808355
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
> @@ -0,0 +1,67 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-mixer.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Tegra210 Mixer Device Tree Bindings
> +
> +description: |
> +  The Mixer supports mixing of up to ten 7.1 audio input streams and
> +  generate five outputs (each of which can be any combination of the
> +  ten input streams).
> +
> +maintainers:
> +  - Jon Hunter <jonathanh@nvidia.com>
> +  - Mohan Kumar <mkumard@nvidia.com>
> +  - Sameer Pujar <spujar@nvidia.com>
> +
> +properties:
> +  $nodename:
> +    pattern: "^mixer@[0-9a-f]*$"
> +
> +  compatible:
> +    oneOf:
> +      - const: nvidia,tegra210-amixer
> +      - items:
> +          - enum:
> +              - nvidia,tegra194-amixer
> +              - nvidia,tegra186-amixer
> +          - const: nvidia,tegra210-amixer
> +
> +  reg:
> +    maxItems: 1
> +
> +  sound-name-prefix:
> +    const: "MIXER"

Don't need quotes. A fixed string seems a bit pointless to put into DT.

> +    $ref: /schemas/types.yaml#/definitions/string
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +    description: |
> +      Mixer has ten inputs and five outputs. Accordingly ACIF (Audio Client
> +      Interfaces) RX and TX port nodes are defined to represent MIXER inputs
> +      and outputs respectively. These are connected to corresponding ports
> +      on AHUB.
> +
> +    patternProperties:
> +      '^port@[0-9]':
> +        $ref: audio-graph-port.yaml#
> +        unevaluatedProperties: false
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +
> +    mixer@702dbb00 {
> +        compatible = "nvidia,tegra210-amixer";
> +        reg = <0x702dbb00 0x800>;
> +        sound-name-prefix = "MIXER";
> +    };
> +
> +...
> diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
> new file mode 100644
> index 0000000..7d81b11
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
> @@ -0,0 +1,79 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-mvc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Tegra210 MVC Device Tree Bindings
> +
> +description: |
> +  The Master Volume Control (MVC) provides gain or attenuation to a digital
> +  signal path. It can be used in input or output signal path for per-stream
> +  volume control or it can be used as master volume control. The MVC block
> +  has one input and one output. The input digital stream can be mono or
> +  multi-channel (up to 7.1 channels) stream. An independent mute control is
> +  also included in the MVC block.
> +
> +maintainers:
> +  - Jon Hunter <jonathanh@nvidia.com>
> +  - Mohan Kumar <mkumard@nvidia.com>
> +  - Sameer Pujar <spujar@nvidia.com>
> +
> +properties:
> +  $nodename:
> +    pattern: "^mvc@[0-9a-f]*$"
> +
> +  compatible:
> +    oneOf:
> +      - const: nvidia,tegra210-mvc
> +      - items:
> +          - enum:
> +              - nvidia,tegra194-mvc
> +              - nvidia,tegra186-mvc
> +          - const: nvidia,tegra210-mvc
> +
> +  reg:
> +    maxItems: 1
> +
> +  sound-name-prefix:
> +    pattern: "^MVC[1-9]$"
> +    $ref: /schemas/types.yaml#/definitions/string
> +    description:
> +      used as prefix for sink/source names of the component. Must be a
> +      unique string among multiple instances of the same component.
> +      The name can be "MVC1" or "MVC2" ... "MVCx", where x depends on
> +      the maximum available instances on a Tegra SoC.
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +    properties:
> +      port@0:
> +        $ref: audio-graph-port.yaml#
> +        unevaluatedProperties: false
> +        description: |
> +          ACIF (Audio Client Interface) acting as MVC input (RX) port.
> +          This is connected to corresponding ACIF port on AHUB.
> +
> +      port@1:
> +        $ref: audio-graph-port.yaml#
> +        unevaluatedProperties: false
> +        description: |
> +          ACIF (Audio Client Interface) acting as MVC output (TX) port.
> +          This is connected to corresponding ACIF port on AHUB.
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +
> +    mvc@702da000 {
> +        compatible = "nvidia,tegra210-mvc";
> +        reg = <0x702da000 0x200>;
> +        sound-name-prefix = "MVC1";
> +    };
> +
> +...
> diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml
> new file mode 100644
> index 0000000..5f05e2a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml
> @@ -0,0 +1,76 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-sfc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Tegra210 SFC Device Tree Bindings
> +
> +description: |
> +  The Sampling Frequency Converter (SFC) converts the sampling frequency
> +  of the input signal from one frequency to another. It supports sampling
> +  frequency conversions of streams of up to two channels (stereo).
> +
> +maintainers:
> +  - Jon Hunter <jonathanh@nvidia.com>
> +  - Mohan Kumar <mkumard@nvidia.com>
> +  - Sameer Pujar <spujar@nvidia.com>
> +
> +properties:
> +  $nodename:
> +    pattern: "^sfc@[0-9a-f]*$"
> +
> +  compatible:
> +    oneOf:
> +      - const: nvidia,tegra210-sfc
> +      - items:
> +          - enum:
> +              - nvidia,tegra194-sfc
> +              - nvidia,tegra186-sfc
> +          - const: nvidia,tegra210-sfc
> +
> +  reg:
> +    maxItems: 1
> +
> +  sound-name-prefix:
> +    pattern: "^SFC[1-9]$"
> +    $ref: /schemas/types.yaml#/definitions/string
> +    description:
> +      used as prefix for sink/source names of the component. Must be a
> +      unique string among multiple instances of the same component.
> +      The name can be "SFC1" or "SFC2" ... "SFCx", where x depends on
> +      the maximum available instances on a Tegra SoC.
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +    properties:
> +      port@0:
> +        $ref: audio-graph-port.yaml#
> +        unevaluatedProperties: false
> +        description: |
> +          ACIF (Audio Client Interface) acting as SFC input (RX) port.
> +          This is connected to corresponding ACIF port on AHUB.
> +
> +      port@1:
> +        $ref: audio-graph-port.yaml#
> +        unevaluatedProperties: false
> +        description: |
> +          ACIF (Audio Client Interface) acting as SFC output (TX) port.
> +          This is connected to corresponding ACIF port on AHUB.
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +
> +    sfc@702d2000 {
> +        compatible = "nvidia,tegra210-sfc";
> +        reg = <0x702d2000 0x200>;
> +        sound-name-prefix = "SFC1";
> +    };
> +
> +...
> -- 
> 2.7.4
> 
> 

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

* Re: [PATCH 04/13] ASoC: dt-bindings: tegra: Few more Tegra210 AHUB modules
  2021-08-31 20:21   ` Rob Herring
@ 2021-09-01  7:09     ` Sameer Pujar
  0 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-09-01  7:09 UTC (permalink / raw)
  To: Rob Herring
  Cc: broonie, lgirdwood, thierry.reding, jonathanh, catalin.marinas,
	will, perex, tiwai, kuninori.morimoto.gx, sharadg, alsa-devel,
	devicetree, linux-tegra, linux-kernel, linux-arm-kernel

Hi Rob,

Thanks for feedback.


On 9/1/2021 1:51 AM, Rob Herring wrote:
> On Fri, Aug 27, 2021 at 03:03:50PM +0530, Sameer Pujar wrote:
>> This patch adds YAML schema for DT bindings of few AHUB modules.
>> These devices will be registered as ASoC components and bindings
>> will be used on Tegra210 and later chips. The bindings for below
>> mentioned modules are added:
>>
>>   * SFC (Sampling Frequency Converter)
>>   * MVC (Master Volume Control)
>>   * AMX (Audio Multiplexer)
>>   * ADX (Audio Demultiplexer)
>>   * Mixer
>>
>> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> ---
>>   .../bindings/sound/nvidia,tegra210-adx.yaml        | 74 ++++++++++++++++++++
>>   .../bindings/sound/nvidia,tegra210-ahub.yaml       | 20 ++++++
>>   .../bindings/sound/nvidia,tegra210-amx.yaml        | 72 ++++++++++++++++++++
>>   .../bindings/sound/nvidia,tegra210-mixer.yaml      | 67 ++++++++++++++++++
>>   .../bindings/sound/nvidia,tegra210-mvc.yaml        | 79 ++++++++++++++++++++++
>>   .../bindings/sound/nvidia,tegra210-sfc.yaml        | 76 +++++++++++++++++++++
>>   6 files changed, 388 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
>>   create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
>>   create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
>>   create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
>>   create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml

[...]

>> +  16 channels and demultiplexes it into four output streams of up to 16
>> +  channels each. A byte RAM helps to form output frames by any combination
>> +  of bytes from the input frame. Its design is identical to that of byte
>> +  RAM in the AMX except that the data flow direction is reversed.
>> +
>> +maintainers:
>> +  - Jon Hunter <jonathanh@nvidia.com>
>> +  - Mohan Kumar <mkumard@nvidia.com>
>> +  - Sameer Pujar <spujar@nvidia.com>
>> +
>> +properties:
>> +  $nodename:
>> +    pattern: "^adx@[0-9a-f]*$"
>> +
>> +  compatible:
>> +    oneOf:
>> +      - const: nvidia,tegra210-adx
>> +      - items:
>> +          - enum:
>> +              - nvidia,tegra194-adx
>> +              - nvidia,tegra186-adx
>> +          - const: nvidia,tegra210-adx
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +  sound-name-prefix:
> nvidia,sound-name-prefix

It is supposed to be 'sound-name-prefix' for core to parse and apply 
prefix. May be this needs to be directly referenced from 
'Documentation/devicetree/bindings/sound/name-prefix.txt' after 
converting to YAML, which can be a separate commit?


Remaining comments will be taken care in next revision.

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

* Re: [PATCH 06/13] ASoC: tegra: Add Tegra210 based MVC driver
  2021-08-27  9:33 ` [PATCH 06/13] ASoC: tegra: Add Tegra210 based MVC driver Sameer Pujar
@ 2021-09-03 18:13   ` Mark Brown
       [not found]     ` <7b248062-9a62-524c-4c96-295685e211b1@nvidia.com>
       [not found]     ` <29c785d0-cc70-7cce-c205-77059c11e0e1@nvidia.com>
  0 siblings, 2 replies; 29+ messages in thread
From: Mark Brown @ 2021-09-03 18:13 UTC (permalink / raw)
  To: Sameer Pujar
  Cc: lgirdwood, robh+dt, thierry.reding, jonathanh, catalin.marinas,
	will, perex, tiwai, kuninori.morimoto.gx, sharadg, alsa-devel,
	devicetree, linux-tegra, linux-kernel, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 1487 bytes --]

On Fri, Aug 27, 2021 at 03:03:52PM +0530, Sameer Pujar wrote:
> The Master Volume Control (MVC) provides gain or attenuation to a digital
> signal path. It can be used in input or output signal path for per-stream
> volume control or it can be used as master volume control. The MVC block
> has one input and one output. The input digital stream can be mono or
> multi-channel (up to 7.1 channels) stream. An independent mute control is
> also included in the MVC block.

Looks like it's also got a little bit of other DSP in there (a simple
EQ?).  Not that it really matters.

> +	if (reg == TEGRA210_MVC_CTRL) {
> +		u32 val;
> +		u8 mute_mask;

> +	} else {
> +		u8 chan = (reg - TEGRA210_MVC_TARGET_VOL) / REG_SIZE;
> +		s32 val = mvc->volume[chan];

It's not clear to me why we're using the same callbacks for the volume
and mute settings - there's no shared code on the read path and only a
tiny bit on the write path.

> +	err |= regmap_update_bits(mvc->regmap, TEGRA210_MVC_SWITCH,
> +			TEGRA210_MVC_VOLUME_SWITCH_MASK,
> +			TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
> +
> +end:
> +	pm_runtime_put(cmpnt->dev);
> +	return err;
> +}

_put() should return 0 if there's no change or 1 for a change.

> +	/* SW reset */
> +	regmap_write(mvc->regmap, TEGRA210_MVC_SOFT_RESET, 1);

What about all the cached values in the regmap, won't they get out of
sync?  Especially things like volume and mute, it looks like the mute
just gets written directly to the regmap and not otherwise saved.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH 00/13] Extend AHUB audio support for Tegra210 and later
  2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
                   ` (12 preceding siblings ...)
  2021-08-27  9:33 ` [PATCH 13/13] arm64: tegra: Extend APE audio support on Jetson platforms Sameer Pujar
@ 2021-09-08  4:56 ` Sameer Pujar
  13 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-09-08  4:56 UTC (permalink / raw)
  To: broonie, lgirdwood, robh+dt, thierry.reding, jonathanh,
	catalin.marinas, will, perex, tiwai, kuninori.morimoto.gx
  Cc: sharadg, alsa-devel, devicetree, linux-tegra, linux-kernel,
	linux-arm-kernel

Hi All,

On 8/27/2021 3:03 PM, Sameer Pujar wrote:
> Earlier as part of series [0], support for ADMAIF and I/O modules (such
> as I2S, DMIC and DSPK) was added. This series aims at exposing some of
> the AHUB internal modules (listed below), which can be used for audio
> pre or post processing.
>
>    * SFC (Sampling Frequency Converter)
>    * MVC (Master Volume Control)
>    * AMX (Audio Multiplexer)
>    * ADX (Audio Demultiplexer)
>    * Mixer
>
> These modules can be plugged into audio paths and relevant processing
> can be done. The MUX routes are extended to allow add or remove above
> modules in the path via mixer controls. This is similar to how specific
> ADMAIF channels are connected to relevant I/O module instances at the
> moment.

> Some of these modules can alter PCM parameters. Consider example of
> resampler (44.1 -> 48 kHz) in the path.
>
>    aplay(44.1 kHz) -> ADMAIF -> SFC -> (48 kHz) I2S -> (48kHz) Codec
>
> The modules following SFC should be using converted sample rate and DAIs
> need to be configured accordingly. The audio-graph driver provides a
> mechanism to fixup the new parameters which can be specified in DT for a
> given DAI. Then core uses these new values via fixup callback and then
> pass it to respective DAIs hw_param() callback. The "convert-rate",
> described in [1], property can be used when there is rate conversion in
> the audio path. Similarly "convert-channels" can be used when there is
> channel conversion in the path. There is no "convert-xxx" property for
> sample size conversions. It can be added if necessary.

In above example, as we see the modules following SFC should be using 
converted PCM parameters (sample rate in above case). For this I am 
currently relying on DT properties ('convert-xxx') which is supported by 
audio-graph-card. This works fine for a static PCM configuration and may 
be fine to start with. But going ahead a more flexible configuration is 
preferred (without the need of a reboot). This came up during [0], but 
now with the introduction of processing modules in the path it becomes 
more important and would be nice to get this addressed.

Are there any mechanisms in place which can be leveraged to apply PCM 
configurations at runtime?
Or any directions/ideas we want to explore?
Any feedback or pointers will be of great help.


[0] https://lkml.org/lkml/2020/2/24/599


Thanks,
Sameer.

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

* Re: [PATCH 06/13] ASoC: tegra: Add Tegra210 based MVC driver
       [not found]       ` <86fc49a3-4cac-78c7-2c0c-eaee8e49d387@nvidia.com>
@ 2021-09-09 14:20         ` Mark Brown
  0 siblings, 0 replies; 29+ messages in thread
From: Mark Brown @ 2021-09-09 14:20 UTC (permalink / raw)
  To: Sameer Pujar
  Cc: lgirdwood, robh+dt, thierry.reding, jonathanh, catalin.marinas,
	will, perex, tiwai, kuninori.morimoto.gx, sharadg, alsa-devel,
	devicetree, linux-tegra, linux-kernel, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 1705 bytes --]

On Thu, Sep 09, 2021 at 06:33:33PM +0530, Sameer Pujar wrote:
> On 9/7/2021 1:35 PM, Sameer Pujar wrote:
> > On 9/3/2021 11:43 PM, Mark Brown wrote:
> > > On Fri, Aug 27, 2021 at 03:03:52PM +0530, Sameer Pujar wrote:

> > > > +	/* SW reset */
> > > > +	regmap_write(mvc->regmap, TEGRA210_MVC_SOFT_RESET, 1);
> > > What about all the cached values in the regmap, won't they get out of
> > > sync?  Especially things like volume and mute, it looks like the mute
> > > just gets written directly to the regmap and not otherwise saved.

> > 1. I think original idea was to disable MVC (forcefully) before new
> > configurations are applied and eventually it gets enabled via DAPM path.
> > DAPM path handles disable also, but sometimes MVC may get stuck in
> > enable state (due to a previous usage) when all the data in pipeline is
> > not processed. My understanding is that reset is restricted to this
> > alone. The volume/mute registers seem not to be affected by reset.
> > However I will confirm with HW about the reset behavior and affected
> > register map. Thanks for pointing this.

> I confirmed the behavior with HW folk here. The reset above clears all FSM,
> flushes flow control of FIFO and resets the state registers. It also brings
> module back to disabled state (without flushing the data in the pipe). There
> is no impact on the register cache, as state registers are anyway volatile
> and module disable is applicable only when it was hung in previous usage.
> Otherwise DAPM would disable the module during session close.

This needs to be *much* clearer in the code, it looks like a bug at the
minute.  It's very surprising that some of the registers wouldn't be
affected by a reset.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH 06/13] ASoC: tegra: Add Tegra210 based MVC driver
       [not found]     ` <29c785d0-cc70-7cce-c205-77059c11e0e1@nvidia.com>
@ 2021-09-13 14:23       ` Mark Brown
  0 siblings, 0 replies; 29+ messages in thread
From: Mark Brown @ 2021-09-13 14:23 UTC (permalink / raw)
  To: Sameer Pujar
  Cc: lgirdwood, robh+dt, thierry.reding, jonathanh, catalin.marinas,
	will, perex, tiwai, kuninori.morimoto.gx, sharadg, alsa-devel,
	devicetree, linux-tegra, linux-kernel, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 556 bytes --]

On Mon, Sep 13, 2021 at 10:32:32AM +0530, Sameer Pujar wrote:
> On 9/3/2021 11:43 PM, Mark Brown wrote:

> > > +	err |= regmap_update_bits(mvc->regmap, TEGRA210_MVC_SWITCH,
> > > +			TEGRA210_MVC_VOLUME_SWITCH_MASK,
> > > +			TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
> > > +
> > > +end:
> > > +	pm_runtime_put(cmpnt->dev);
> > > +	return err;
> > > +}

> > _put() should return 0 if there's no change or 1 for a change.

> So this means, no need to return any error value and just return 0 in such
> cases?

If there's an error you should return that instead.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE
  2021-08-27  9:33 ` [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE Sameer Pujar
@ 2021-09-28 21:25   ` Pierre-Louis Bossart
  2021-09-29  7:43     ` Sameer Pujar
  0 siblings, 1 reply; 29+ messages in thread
From: Pierre-Louis Bossart @ 2021-09-28 21:25 UTC (permalink / raw)
  To: Sameer Pujar, broonie, lgirdwood, robh+dt, thierry.reding,
	jonathanh, catalin.marinas, will, perex, tiwai,
	kuninori.morimoto.gx
  Cc: devicetree, alsa-devel, linux-kernel, linux-tegra, sharadg,
	linux-arm-kernel



On 8/27/21 4:33 AM, Sameer Pujar wrote:
> In some cases, multiple FE components have the same BE component in their
> respective DPCM paths. One such example would be a mixer component, which
> can receive two or more inputs and sends a mixed output. In such cases,
> to avoid reconfiguration of already active DAI (mixer output DAI in this
> case), check the BE stream state to filter out the redundancy.
> 
> In summary, allow connection of BE if the respective current stream state
> is either NEW or CLOSED.

This patch breaks our SOF CI tests, ironically in all cases where we
have a mixer with a 'Deep buffer' port! The tests with multiple streams
all fail with this error:

[  124.366400]  Port0 Deep Buffer: ASoC: no backend DAIs enabled for
Port0 Deep Buffer
[  124.366406]  Port0 Deep Buffer: ASoC: dpcm_fe_dai_prepare() failed (-22)

Reverting this patch restore the mixer functionality.

I see multiple problems with this patch:

At a high-level, there's at least a race condition where this BE state
is checked without any protection. That was already a problem that I
highlighted in a recent RFC and still working on, when we have multiple
FEs we can have START/STOP triggers happening concurrently and it's
necessary to serialize these triggers when checking the state, and this
patch increases the 'surface' for this race condition.

But in addition we'd need to agree on what an 'active BE' is. Why can't
we connect a second stream while the first one is already in HW_PARAMS
or PAUSED or STOP? It's perfectly legal in ALSA/ASoC to have multiple
HW_PARAMS calls, and when we reach STOP we have to do a prepare again.

And more fundamentally, the ability to add a second FE on a 'active' BE
in START state is a basic requirement for a mixer, e.g. to play a
notification on one FE while listening to music on another. What needs
to happen is only to make sure that the FE and BE are compatible in
terms of HW_PARAMS and not sending a second TRIGGER_STOP, only checking
the BE NEW or CLOSE state is way too restrictive.

I will agree this sort of mixer use cases is not well supported in
soc-pcm.c, but let's not make it worse than it was before this patch,
shall we?

I can send a revert with the explanations in the commit message if there
is a consensus that this patch needs to be revisited.

[1] https://github.com/thesofproject/linux/pull/3177
[2] https://sof-ci.01.org/linuxpr/PR3177/build6440/devicetest/

> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> ---
>  sound/soc/soc-pcm.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
> index 48f71bb..e30cb5a 100644
> --- a/sound/soc/soc-pcm.c
> +++ b/sound/soc/soc-pcm.c
> @@ -1395,6 +1395,10 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
>  		if (!fe->dpcm[stream].runtime && !fe->fe_compr)
>  			continue;
>  
> +		if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
> +		    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
> +			continue;
> +
>  		/* newly connected FE and BE */
>  		err = dpcm_be_connect(fe, be, stream);
>  		if (err < 0) {
> 

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

* Re: [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE
  2021-09-28 21:25   ` Pierre-Louis Bossart
@ 2021-09-29  7:43     ` Sameer Pujar
       [not found]       ` <2f96f1aa-74f2-8ea8-3f43-e4da97400fde@linux.intel.com>
  2021-09-30 19:00       ` Pierre-Louis Bossart
  0 siblings, 2 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-09-29  7:43 UTC (permalink / raw)
  To: Pierre-Louis Bossart, broonie, lgirdwood, robh+dt,
	thierry.reding, jonathanh, catalin.marinas, will, perex, tiwai,
	kuninori.morimoto.gx
  Cc: devicetree, alsa-devel, linux-kernel, linux-tegra, sharadg,
	linux-arm-kernel



On 9/29/2021 2:55 AM, Pierre-Louis Bossart wrote:
> On 8/27/21 4:33 AM, Sameer Pujar wrote:

[...]

> But in addition we'd need to agree on what an 'active BE' is. Why can't
> we connect a second stream while the first one is already in HW_PARAMS
> or PAUSED or STOP? It's perfectly legal in ALSA/ASoC to have multiple
> HW_PARAMS calls, and when we reach STOP we have to do a prepare again.
>
> And more fundamentally, the ability to add a second FE on a 'active' BE
> in START state is a basic requirement for a mixer, e.g. to play a
> notification on one FE while listening to music on another. What needs
> to happen is only to make sure that the FE and BE are compatible in
> terms of HW_PARAMS and not sending a second TRIGGER_STOP, only checking
> the BE NEW or CLOSE state is way too restrictive.

Sorry for the trouble to your system.

Idea was to avoid reconfiguration of the same BE DAI again, but not to 
stop the provision to add a subsequent FE. In fact I had tested mixing 
of streams coming from 10 different FEs.

In your case, because of this patch, looks like the subsequent FE is not 
finding a BE DAI since it is already active due to a prior FE. The 
reason it works at my end is because the mixer input and output DAIs are 
separated. Any new FE would just configure the mixer input DAI to which 
it is attached and skip already running/configured output DAI. I am just 
curious to know, if originally you were reconfiguring the BE DAI again 
with same parameters (for a second FE) or some additional configuration 
is done?


> I can send a revert with the explanations in the commit message if there
> is a consensus that this patch needs to be revisited.

May be this can be revisited since it appears to be a critical problem 
for your system. But I hope this discussion can be alive on following 
points for a better fix.

1. The original issue at my end was not just a configuration redundancy. 
I realize now that with more stream addition following error print is seen.
    "ASoC: too many users playback at open 4"

    This is because the max DPCM users is capped at 8. Increasing this 
may help (need to see what number is better), but does not address the 
redundancy problem.

2. If reconfiguration of the same BE is not necessary for a subsequent 
FE run, shouldn't we avoid the reconfig itself and somehow avoid FE failure?


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

* Re: [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE
       [not found]       ` <2f96f1aa-74f2-8ea8-3f43-e4da97400fde@linux.intel.com>
@ 2021-09-29 14:52         ` Pierre-Louis Bossart
  2021-09-30  7:57           ` Sameer Pujar
  0 siblings, 1 reply; 29+ messages in thread
From: Pierre-Louis Bossart @ 2021-09-29 14:52 UTC (permalink / raw)
  To: Péter Ujfalusi, Sameer Pujar, broonie, lgirdwood, robh+dt,
	thierry.reding, jonathanh, catalin.marinas, will, perex, tiwai,
	kuninori.morimoto.gx
  Cc: devicetree, alsa-devel, linux-kernel, linux-tegra, sharadg,
	linux-arm-kernel




>>> But in addition we'd need to agree on what an 'active BE' is. Why can't
>>> we connect a second stream while the first one is already in HW_PARAMS
>>> or PAUSED or STOP? It's perfectly legal in ALSA/ASoC to have multiple
>>> HW_PARAMS calls, and when we reach STOP we have to do a prepare again.
>>>
>>> And more fundamentally, the ability to add a second FE on a 'active' BE
>>> in START state is a basic requirement for a mixer, e.g. to play a
>>> notification on one FE while listening to music on another. What needs
>>> to happen is only to make sure that the FE and BE are compatible in
>>> terms of HW_PARAMS and not sending a second TRIGGER_STOP, only checking
>>> the BE NEW or CLOSE state is way too restrictive.
>>
>> Sorry for the trouble to your system.
>>
>> Idea was to avoid reconfiguration of the same BE DAI again, but not to
>> stop the provision to add a subsequent FE. In fact I had tested mixing
>> of streams coming from 10 different FEs.

Can you describe the sequence that you used to start them? That may be
useful to understand the criteria you used?

>> In your case, because of this patch, looks like the subsequent FE is not
>> finding a BE DAI since it is already active due to a prior FE. The
>> reason it works at my end is because the mixer input and output DAIs are
>> separated. Any new FE would just configure the mixer input DAI to which
>> it is attached and skip already running/configured output DAI. 

If you want to visualize the topology we're using in our 'nocodec'
tests, see

https://sof-ci.01.org/linuxpr/PR3177/build6440/devicetest/?model=ADLP_RVP_NOCODEC&testcase=verify-kernel-boot-log

and use the sof-adl-nocodec.

it's a bog-standard topology with processing entities connected by buffers.

I don't fully understand the notion of mixer input DAI, in our case we
have a bunch of PCM devices connected to a mixer. The mixer is not
directly connected to a DAI.

> The problem as I see is that with this patch one can not connect a new
> FE to a BE which is _not_ in NEW or CLOSE state.
> 
> The FE and BE needs to be connected to have DPCM working and this patch
> makes the code to skip the dpcm_be_connect().
> 
> Consider this simple setup:
> 
> FE1 -->|
>        | --> BE -->
> FE2- ->|
> 
> First we start FE1, dpcm_be_connect(FE1, BE, stream) is made.
> 
> Later FE2 is started but dpcm_be_connect(FE2, BE, stream) would be not
> made because BE is no longer in NEW/CLOSE state.

I share Peter's analysis, there cannot be any restrictions on
connections - at any time. A mixer input might become active and be
added to the mix. We might have a temporary lock to delay new
connections but cannot not reject them outright based on BE state.

>> I am just
>> curious to know, if originally you were reconfiguring the BE DAI again
>> with same parameters (for a second FE) or some additional configuration
>> is done?

That's a different question - and a good one.

In the case of a mixer, the propagation of hw_params is a broken
concept. It leads to the first FE configuring the BE to define its
preferred parameters, e.g. S16_LE format. If later on a second FE is
started which could play S24_LE, the mixer and BE are already configured
to a lower resolution. A mixer should really have its own parameters and
be the start of a new 'domain' - as Lars described it several years ago
at the audio miniconference.

For now, the only restriction that we could enforce is that the BE
cannot be reconfigured after the prepare step.

Note that our DAIs tolerate multiple calls to hw_params. If you have a
case where the hw_params allocates resources, maybe you should consider
moving that allocation to the prepare step, or free them if you detect a
reconfiguration. That would be something needed even outside of the DPCM
scope. Similarly you need to support the case where the DAI hw_free is
called without hw_params ever being called, it's a known sequence that
can happen if the FE hw-params fails.

>>> I can send a revert with the explanations in the commit message if there
>>> is a consensus that this patch needs to be revisited.
>>
>> May be this can be revisited since it appears to be a critical problem
>> for your system. But I hope this discussion can be alive on following
>> points for a better fix.
>>
>> 1. The original issue at my end was not just a configuration redundancy.
>> I realize now that with more stream addition following error print is seen.
>>    "ASoC: too many users playback at open 4"
>>
>>    This is because the max DPCM users is capped at 8. Increasing this
>> may help (need to see what number is better), but does not address the
>> redundancy problem.

we haven't used more than 2 users, but it's already broken at 2 with
race conditions left and right. I am really surprised you managed to
have more than 2 without hitting inconsistent states - our automated
play/stop/pause monkey tests reliably break DPCM in less than 20s.

>> 2. If reconfiguration of the same BE is not necessary for a subsequent
>> FE run, shouldn't we avoid the reconfig itself and somehow avoid FE
>> failure?
> 
> I'm not sure, but it might be possible to just skip the
> dpcm_set_be_update_state(be, stream, SND_SOC_DPCM_UPDATE_BE);
> call at the end of the loop, but the question is under which condition?
> Can a BE asked to be reconfigured when STOP/OPEN/HW_PARAMS?
> 
> Skipping the connect does not sound right for a new FE-BE connection.

The reconfiguration is one problem, but what also happens is that the BE
dailink will see multiple triggers. I've been playing with refcounts to
force consistency and make sure there is only one TRIGGER_START send to
the dailink, and conversely there are cases where the TRIGGER_STOP is
never sent...

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

* Re: [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE
  2021-09-29 14:52         ` Pierre-Louis Bossart
@ 2021-09-30  7:57           ` Sameer Pujar
  2021-09-30 14:34             ` Pierre-Louis Bossart
  0 siblings, 1 reply; 29+ messages in thread
From: Sameer Pujar @ 2021-09-30  7:57 UTC (permalink / raw)
  To: Pierre-Louis Bossart, Péter Ujfalusi, broonie, lgirdwood,
	robh+dt, thierry.reding, jonathanh, catalin.marinas, will, perex,
	tiwai, kuninori.morimoto.gx
  Cc: devicetree, alsa-devel, linux-kernel, linux-tegra, sharadg,
	linux-arm-kernel



On 9/29/2021 8:22 PM, Pierre-Louis Bossart wrote:
>>>> But in addition we'd need to agree on what an 'active BE' is. Why can't
>>>> we connect a second stream while the first one is already in HW_PARAMS
>>>> or PAUSED or STOP? It's perfectly legal in ALSA/ASoC to have multiple
>>>> HW_PARAMS calls, and when we reach STOP we have to do a prepare again.
>>>>
>>>> And more fundamentally, the ability to add a second FE on a 'active' BE
>>>> in START state is a basic requirement for a mixer, e.g. to play a
>>>> notification on one FE while listening to music on another. What needs
>>>> to happen is only to make sure that the FE and BE are compatible in
>>>> terms of HW_PARAMS and not sending a second TRIGGER_STOP, only checking
>>>> the BE NEW or CLOSE state is way too restrictive.
>>> Sorry for the trouble to your system.
>>>
>>> Idea was to avoid reconfiguration of the same BE DAI again, but not to
>>> stop the provision to add a subsequent FE. In fact I had tested mixing
>>> of streams coming from 10 different FEs.
> Can you describe the sequence that you used to start them? That may be
> useful to understand the criteria you used?

I have something like this:

FE1  --> Crossbar -> Mixer Input1    |
FE2  --> Crossbar -> Mixer Input2    |
...                                  | --> Mixer Output -->
... |
FE10 --> Crossbar -> Mixer Input10   |

All these FEs are started one after the other. This is an example of 
10x1. Similarly we can have 2x1, 3x1 etc.,
In our system, the crossbar [0] and mixer [1] are separate ASoC 
components. Basically audio paths consist of a group of ASoC components 
which are connected back to back.

[0] 
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git/tree/sound/soc/tegra/tegra210_ahub.c
[1] 
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git/tree/sound/soc/tegra/tegra210_mixer.c

>

[...]

> I don't fully understand the notion of mixer input DAI, in our case we
> have a bunch of PCM devices connected to a mixer. The mixer is not
> directly connected to a DAI.

Please see above mixer example. Since mixer is a separate ASoC 
component, it exposes 10 inputs (or DAIs) and outputs. Originally what I 
wanted to do was, for subsequent FE runs (FE2, FE3 ...) mixer output 
need not be configured again and again.

>> The problem as I see is that with this patch one can not connect a new
>> FE to a BE which is _not_ in NEW or CLOSE state.
>>
>> The FE and BE needs to be connected to have DPCM working and this patch
>> makes the code to skip the dpcm_be_connect().
>>
>> Consider this simple setup:
>>
>> FE1 -->|
>>         | --> BE -->
>> FE2- ->|
>>
>> First we start FE1, dpcm_be_connect(FE1, BE, stream) is made.
>>
>> Later FE2 is started but dpcm_be_connect(FE2, BE, stream) would be not
>> made because BE is no longer in NEW/CLOSE state.
> I share Peter's analysis, there cannot be any restrictions on
> connections - at any time. A mixer input might become active and be
> added to the mix. We might have a temporary lock to delay new
> connections but cannot not reject them outright based on BE state.

Yes, I understand how this affects a system like yours. As per mixer 
example above, in our case subsequent FEs always find BE from Crossbar. 
That is why I don't see similar error.

>>> I am just
>>> curious to know, if originally you were reconfiguring the BE DAI again
>>> with same parameters (for a second FE) or some additional configuration
>>> is done?
> That's a different question - and a good one.
>
> In the case of a mixer, the propagation of hw_params is a broken
> concept. It leads to the first FE configuring the BE to define its
> preferred parameters, e.g. S16_LE format. If later on a second FE is
> started which could play S24_LE, the mixer and BE are already configured
> to a lower resolution. A mixer should really have its own parameters and
> be the start of a new 'domain' - as Lars described it several years ago
> at the audio miniconference.

Propagation is one of the problems we want to address and require help 
from DPCM experts. But the scenario you mentioned is a special case 
which need not be supported, because mixer can operate in one 
configuration at a given time and subsequent FEs should agree to the 
already running configuration. However mixer should support both S16_LE 
and S24_LE (whenever possible), but not simultaneously. At least this is 
the expecation from our systems. Yes mixer may require fixup of a 
specific config (we earlier had proposed mixer controls to configure 
mixer parameters, but the idea was disliked), but propagation may help 
avoid fixing up everywhere in the audio path where it is not really 
required. But I don't know how this can be done at the moment.

>
> For now, the only restriction that we could enforce is that the BE
> cannot be reconfigured after the prepare step.
>
> Note that our DAIs tolerate multiple calls to hw_params. If you have a
> case where the hw_params allocates resources, maybe you should consider
> moving that allocation to the prepare step, or free them if you detect a
> reconfiguration. That would be something needed even outside of the DPCM
> scope. Similarly you need to support the case where the DAI hw_free is
> called without hw_params ever being called, it's a known sequence that
> can happen if the FE hw-params fails.

Currently this does not seem to be a problem for us. Patch was to avoid 
reconfiguration which was felt to be redundant for our system.

>>>> I can send a revert with the explanations in the commit message if there
>>>> is a consensus that this patch needs to be revisited.
>>> May be this can be revisited since it appears to be a critical problem
>>> for your system. But I hope this discussion can be alive on following
>>> points for a better fix.
>>>
>>> 1. The original issue at my end was not just a configuration redundancy.
>>> I realize now that with more stream addition following error print is seen.
>>>     "ASoC: too many users playback at open 4"
>>>
>>>     This is because the max DPCM users is capped at 8. Increasing this
>>> may help (need to see what number is better), but does not address the
>>> redundancy problem.
> we haven't used more than 2 users, but it's already broken at 2 with
> race conditions left and right. I am really surprised you managed to
> have more than 2 without hitting inconsistent states - our automated
> play/stop/pause monkey tests reliably break DPCM in less than 20s.

I am not sure what is the exact difference, may be DPCM usage in our 
case is different from what you have. I have mixer tests for different 
combinations (2x1, 3x1 ...), which seem to pass. In general, we want to 
have path like this.

FE -> BE1 -> BE2 -> ... -> BEx

Each BEx could be a mixer, resampler etc., Currently DPCM core sees this 
as multiple BEs for a given FE and that is why multiple "users" are 
reported.

In the interim, may be we can have following patch to keep both systems 
working and keep the discussion going to address the oustanding 
requirements/issues?

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ab25f99..0fbab50 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1395,7 +1395,13 @@ static int dpcm_add_paths(struct 
snd_soc_pcm_runtime *fe, int stream,
                 if (!fe->dpcm[stream].runtime && !fe->fe_compr)
                         continue;

-               if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
+               /*
+                * Filter for systems with 'component_chaining' enabled.
+                * This helps to avoid unnecessary re-configuration of an
+                * already active BE on such systems.
+                */
+               if (fe->card->component_chaining &&
+                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
                     (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
                         continue;

>
>>> 2. If reconfiguration of the same BE is not necessary for a subsequent
>>> FE run, shouldn't we avoid the reconfig itself and somehow avoid FE
>>> failure?
>> I'm not sure, but it might be possible to just skip the
>> dpcm_set_be_update_state(be, stream, SND_SOC_DPCM_UPDATE_BE);
>> call at the end of the loop, but the question is under which condition?
>> Can a BE asked to be reconfigured when STOP/OPEN/HW_PARAMS?
>>
>> Skipping the connect does not sound right for a new FE-BE connection.
> The reconfiguration is one problem, but what also happens is that the BE
> dailink will see multiple triggers. I've been playing with refcounts to
> force consistency and make sure there is only one TRIGGER_START send to
> the dailink, and conversely there are cases where the TRIGGER_STOP is
> never sent...
Just a thought. FE links have dummy codec DAI and core wants to find a 
real BE when FE is started. May be don't fail a FE when no back end DAI 
is found (and/or find if the same BE is already connected to some FE) 
and the above problem becomes simpler?

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

* Re: [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE
  2021-09-30  7:57           ` Sameer Pujar
@ 2021-09-30 14:34             ` Pierre-Louis Bossart
  2021-09-30 15:35               ` Sameer Pujar
  0 siblings, 1 reply; 29+ messages in thread
From: Pierre-Louis Bossart @ 2021-09-30 14:34 UTC (permalink / raw)
  To: Sameer Pujar, Péter Ujfalusi, broonie, lgirdwood, robh+dt,
	thierry.reding, jonathanh, catalin.marinas, will, perex, tiwai,
	kuninori.morimoto.gx
  Cc: devicetree, alsa-devel, linux-kernel, sharadg, linux-tegra,
	linux-arm-kernel


>>>>> But in addition we'd need to agree on what an 'active BE' is. Why
>>>>> can't
>>>>> we connect a second stream while the first one is already in HW_PARAMS
>>>>> or PAUSED or STOP? It's perfectly legal in ALSA/ASoC to have multiple
>>>>> HW_PARAMS calls, and when we reach STOP we have to do a prepare again.
>>>>>
>>>>> And more fundamentally, the ability to add a second FE on a
>>>>> 'active' BE
>>>>> in START state is a basic requirement for a mixer, e.g. to play a
>>>>> notification on one FE while listening to music on another. What needs
>>>>> to happen is only to make sure that the FE and BE are compatible in
>>>>> terms of HW_PARAMS and not sending a second TRIGGER_STOP, only
>>>>> checking
>>>>> the BE NEW or CLOSE state is way too restrictive.
>>>> Sorry for the trouble to your system.
>>>>
>>>> Idea was to avoid reconfiguration of the same BE DAI again, but not to
>>>> stop the provision to add a subsequent FE. In fact I had tested mixing
>>>> of streams coming from 10 different FEs.
>> Can you describe the sequence that you used to start them? That may be
>> useful to understand the criteria you used?
> 
> I have something like this:
> 
> FE1  --> Crossbar -> Mixer Input1    |
> FE2  --> Crossbar -> Mixer Input2    |
> ...                                  | --> Mixer Output -->
> ... |
> FE10 --> Crossbar -> Mixer Input10   |
> 
> All these FEs are started one after the other. This is an example of
> 10x1. Similarly we can have 2x1, 3x1 etc.,
> In our system, the crossbar [0] and mixer [1] are separate ASoC
> components. Basically audio paths consist of a group of ASoC components
> which are connected back to back.

Not following. Can you explain how starting FE1 does not change the
state of the mixer output then?

Or is each 'Crossbar' instance a full-blown BE? In that case you have a
1:1 mapping between FE and BE, a *really* simple topology...

>> I don't fully understand the notion of mixer input DAI, in our case we
>> have a bunch of PCM devices connected to a mixer. The mixer is not
>> directly connected to a DAI.
> 
> Please see above mixer example. Since mixer is a separate ASoC
> component, it exposes 10 inputs (or DAIs) and outputs. Originally what I
> wanted to do was, for subsequent FE runs (FE2, FE3 ...) mixer output
> need not be configured again and again.
> 
>>> The problem as I see is that with this patch one can not connect a new
>>> FE to a BE which is _not_ in NEW or CLOSE state.
>>>
>>> The FE and BE needs to be connected to have DPCM working and this patch
>>> makes the code to skip the dpcm_be_connect().
>>>
>>> Consider this simple setup:
>>>
>>> FE1 -->|
>>>         | --> BE -->
>>> FE2- ->|
>>>
>>> First we start FE1, dpcm_be_connect(FE1, BE, stream) is made.
>>>
>>> Later FE2 is started but dpcm_be_connect(FE2, BE, stream) would be not
>>> made because BE is no longer in NEW/CLOSE state.
>> I share Peter's analysis, there cannot be any restrictions on
>> connections - at any time. A mixer input might become active and be
>> added to the mix. We might have a temporary lock to delay new
>> connections but cannot not reject them outright based on BE state.
> 
> Yes, I understand how this affects a system like yours. As per mixer
> example above, in our case subsequent FEs always find BE from Crossbar.
> That is why I don't see similar error.

Not following either.

>>>> I am just
>>>> curious to know, if originally you were reconfiguring the BE DAI again
>>>> with same parameters (for a second FE) or some additional configuration
>>>> is done?
>> That's a different question - and a good one.
>>
>> In the case of a mixer, the propagation of hw_params is a broken
>> concept. It leads to the first FE configuring the BE to define its
>> preferred parameters, e.g. S16_LE format. If later on a second FE is
>> started which could play S24_LE, the mixer and BE are already configured
>> to a lower resolution. A mixer should really have its own parameters and
>> be the start of a new 'domain' - as Lars described it several years ago
>> at the audio miniconference.
> 
> Propagation is one of the problems we want to address and require help
> from DPCM experts. But the scenario you mentioned is a special case
> which need not be supported, because mixer can operate in one
> configuration at a given time and subsequent FEs should agree to the
> already running configuration. However mixer should support both S16_LE
> and S24_LE (whenever possible), but not simultaneously. At least this is
> the expecation from our systems. Yes mixer may require fixup of a
> specific config (we earlier had proposed mixer controls to configure
> mixer parameters, but the idea was disliked), but propagation may help
> avoid fixing up everywhere in the audio path where it is not really
> required. But I don't know how this can be done at the moment.

What I am saying is that the mixer should be pre-configured with the
desired resolution/sample rate, and some adaptation needs to happen if
the FE provides data in a different format.

This is similar to what sound servers typically do on their sinks, they
define ONE configuration. Dynamic changes are annoying and result in
corner cases where the quality can vary depending on which FE is started
first.

>>>> For now, the only restriction that we could enforce is that the BE
>> cannot be reconfigured after the prepare step.
>>
>> Note that our DAIs tolerate multiple calls to hw_params. If you have a
>> case where the hw_params allocates resources, maybe you should consider
>> moving that allocation to the prepare step, or free them if you detect a
>> reconfiguration. That would be something needed even outside of the DPCM
>> scope. Similarly you need to support the case where the DAI hw_free is
>> called without hw_params ever being called, it's a known sequence that
>> can happen if the FE hw-params fails.
> 
> Currently this does not seem to be a problem for us. Patch was to avoid
> reconfiguration which was felt to be redundant for our system.
> 
>>>>> I can send a revert with the explanations in the commit message if
>>>>> there
>>>>> is a consensus that this patch needs to be revisited.
>>>> May be this can be revisited since it appears to be a critical problem
>>>> for your system. But I hope this discussion can be alive on following
>>>> points for a better fix.
>>>>
>>>> 1. The original issue at my end was not just a configuration
>>>> redundancy.
>>>> I realize now that with more stream addition following error print
>>>> is seen.
>>>>     "ASoC: too many users playback at open 4"
>>>>
>>>>     This is because the max DPCM users is capped at 8. Increasing this
>>>> may help (need to see what number is better), but does not address the
>>>> redundancy problem.
>> we haven't used more than 2 users, but it's already broken at 2 with
>> race conditions left and right. I am really surprised you managed to
>> have more than 2 without hitting inconsistent states - our automated
>> play/stop/pause monkey tests reliably break DPCM in less than 20s.
> 
> I am not sure what is the exact difference, may be DPCM usage in our
> case is different from what you have. I have mixer tests for different
> combinations (2x1, 3x1 ...), which seem to pass. In general, we want to
> have path like this.
> 
> FE -> BE1 -> BE2 -> ... -> BEx
> 
> Each BEx could be a mixer, resampler etc., Currently DPCM core sees this
> as multiple BEs for a given FE and that is why multiple "users" are
> reported.

This sort of flow vastly exceeds the capabilities of DPCM, which is
already badly broken with one BE and 2 FEs... I think what you want is
what Lars described at the audio miniconf with 'domains'.

> In the interim, may be we can have following patch to keep both systems
> working and keep the discussion going to address the oustanding
> requirements/issues?
> 
> diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
> index ab25f99..0fbab50 100644
> --- a/sound/soc/soc-pcm.c
> +++ b/sound/soc/soc-pcm.c
> @@ -1395,7 +1395,13 @@ static int dpcm_add_paths(struct
> snd_soc_pcm_runtime *fe, int stream,
>                 if (!fe->dpcm[stream].runtime && !fe->fe_compr)
>                         continue;
> 
> -               if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
> +               /*
> +                * Filter for systems with 'component_chaining' enabled.
> +                * This helps to avoid unnecessary re-configuration of an
> +                * already active BE on such systems.
> +                */
> +               if (fe->card->component_chaining &&
> +                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
>                     (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
>                         continue;

that wouldn't work. We need to support the STOP and START cases as well.


>>>> 2. If reconfiguration of the same BE is not necessary for a subsequent
>>>> FE run, shouldn't we avoid the reconfig itself and somehow avoid FE
>>>> failure?
>>> I'm not sure, but it might be possible to just skip the
>>> dpcm_set_be_update_state(be, stream, SND_SOC_DPCM_UPDATE_BE);
>>> call at the end of the loop, but the question is under which condition?
>>> Can a BE asked to be reconfigured when STOP/OPEN/HW_PARAMS?
>>>
>>> Skipping the connect does not sound right for a new FE-BE connection.
>> The reconfiguration is one problem, but what also happens is that the BE
>> dailink will see multiple triggers. I've been playing with refcounts to
>> force consistency and make sure there is only one TRIGGER_START send to
>> the dailink, and conversely there are cases where the TRIGGER_STOP is
>> never sent...
> Just a thought. FE links have dummy codec DAI and core wants to find a
> real BE when FE is started. May be don't fail a FE when no back end DAI
> is found (and/or find if the same BE is already connected to some FE)
> and the above problem becomes simpler?

That would be just moving the problem. In our case we would be silently
playing on a dummy output just because the correct output was not found
due to state handling issues.

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

* Re: [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE
  2021-09-30 14:34             ` Pierre-Louis Bossart
@ 2021-09-30 15:35               ` Sameer Pujar
  2021-09-30 16:13                 ` Pierre-Louis Bossart
  0 siblings, 1 reply; 29+ messages in thread
From: Sameer Pujar @ 2021-09-30 15:35 UTC (permalink / raw)
  To: Pierre-Louis Bossart, Péter Ujfalusi, broonie, lgirdwood,
	robh+dt, thierry.reding, jonathanh, catalin.marinas, will, perex,
	tiwai, kuninori.morimoto.gx
  Cc: devicetree, alsa-devel, linux-kernel, sharadg, linux-tegra,
	linux-arm-kernel



On 9/30/2021 8:04 PM, Pierre-Louis Bossart wrote:
>>>>>> But in addition we'd need to agree on what an 'active BE' is. Why
>>>>>> can't
>>>>>> we connect a second stream while the first one is already in HW_PARAMS
>>>>>> or PAUSED or STOP? It's perfectly legal in ALSA/ASoC to have multiple
>>>>>> HW_PARAMS calls, and when we reach STOP we have to do a prepare again.
>>>>>>
>>>>>> And more fundamentally, the ability to add a second FE on a
>>>>>> 'active' BE
>>>>>> in START state is a basic requirement for a mixer, e.g. to play a
>>>>>> notification on one FE while listening to music on another. What needs
>>>>>> to happen is only to make sure that the FE and BE are compatible in
>>>>>> terms of HW_PARAMS and not sending a second TRIGGER_STOP, only
>>>>>> checking
>>>>>> the BE NEW or CLOSE state is way too restrictive.
>>>>> Sorry for the trouble to your system.
>>>>>
>>>>> Idea was to avoid reconfiguration of the same BE DAI again, but not to
>>>>> stop the provision to add a subsequent FE. In fact I had tested mixing
>>>>> of streams coming from 10 different FEs.
>>> Can you describe the sequence that you used to start them? That may be
>>> useful to understand the criteria you used?
>> I have something like this:
>>
>> FE1  --> Crossbar -> Mixer Input1    |
>> FE2  --> Crossbar -> Mixer Input2    |
>> ...                                  | --> Mixer Output -->
>> ... |
>> FE10 --> Crossbar -> Mixer Input10   |
>>
>> All these FEs are started one after the other. This is an example of
>> 10x1. Similarly we can have 2x1, 3x1 etc.,
>> In our system, the crossbar [0] and mixer [1] are separate ASoC
>> components. Basically audio paths consist of a group of ASoC components
>> which are connected back to back.
> Not following. Can you explain how starting FE1 does not change the
> state of the mixer output then?
>
> Or is each 'Crossbar' instance a full-blown BE? In that case you have a
> 1:1 mapping between FE and BE, a *really* simple topology...

Yes 'Crossbar' exposes multiple ports and it is 1:1 mapping with FE. 
Starting FE1 does configure mixer output.

>>> I don't fully understand the notion of mixer input DAI, in our case we
>>> have a bunch of PCM devices connected to a mixer. The mixer is not
>>> directly connected to a DAI.
>> Please see above mixer example. Since mixer is a separate ASoC
>> component, it exposes 10 inputs (or DAIs) and outputs. Originally what I
>> wanted to do was, for subsequent FE runs (FE2, FE3 ...) mixer output
>> need not be configured again and again.
>>
>>>> The problem as I see is that with this patch one can not connect a new
>>>> FE to a BE which is _not_ in NEW or CLOSE state.
>>>>
>>>> The FE and BE needs to be connected to have DPCM working and this patch
>>>> makes the code to skip the dpcm_be_connect().
>>>>
>>>> Consider this simple setup:
>>>>
>>>> FE1 -->|
>>>>          | --> BE -->
>>>> FE2- ->|
>>>>
>>>> First we start FE1, dpcm_be_connect(FE1, BE, stream) is made.
>>>>
>>>> Later FE2 is started but dpcm_be_connect(FE2, BE, stream) would be not
>>>> made because BE is no longer in NEW/CLOSE state.
>>> I share Peter's analysis, there cannot be any restrictions on
>>> connections - at any time. A mixer input might become active and be
>>> added to the mix. We might have a temporary lock to delay new
>>> connections but cannot not reject them outright based on BE state.
>> Yes, I understand how this affects a system like yours. As per mixer
>> example above, in our case subsequent FEs always find BE from Crossbar.
>> That is why I don't see similar error.
> Not following either.

May be it is understandable now with above crossbar point?

>>>>> I am just
>>>>> curious to know, if originally you were reconfiguring the BE DAI again
>>>>> with same parameters (for a second FE) or some additional configuration
>>>>> is done?
>>> That's a different question - and a good one.
>>>
>>> In the case of a mixer, the propagation of hw_params is a broken
>>> concept. It leads to the first FE configuring the BE to define its
>>> preferred parameters, e.g. S16_LE format. If later on a second FE is
>>> started which could play S24_LE, the mixer and BE are already configured
>>> to a lower resolution. A mixer should really have its own parameters and
>>> be the start of a new 'domain' - as Lars described it several years ago
>>> at the audio miniconference.
>> Propagation is one of the problems we want to address and require help
>> from DPCM experts. But the scenario you mentioned is a special case
>> which need not be supported, because mixer can operate in one
>> configuration at a given time and subsequent FEs should agree to the
>> already running configuration. However mixer should support both S16_LE
>> and S24_LE (whenever possible), but not simultaneously. At least this is
>> the expecation from our systems. Yes mixer may require fixup of a
>> specific config (we earlier had proposed mixer controls to configure
>> mixer parameters, but the idea was disliked), but propagation may help
>> avoid fixing up everywhere in the audio path where it is not really
>> required. But I don't know how this can be done at the moment.
> What I am saying is that the mixer should be pre-configured with the
> desired resolution/sample rate, and some adaptation needs to happen if
> the FE provides data in a different format.
>
> This is similar to what sound servers typically do on their sinks, they
> define ONE configuration. Dynamic changes are annoying and result in
> corner cases where the quality can vary depending on which FE is started
> first.

When there are multiple FEs running, yes it is better to run on a 
pre-agreed configuration to minimize the side effects of race between 
FEs. Also there should also be a provision where mixer params directly 
depend on FEs. For example, a 2x1 mixer can mix two 16-bit streams at 
one time and the other time it can mix two 32-bit streams.


[...]

>>>>>> I can send a revert with the explanations in the commit message if
>>>>>> there
>>>>>> is a consensus that this patch needs to be revisited.
>>>>> May be this can be revisited since it appears to be a critical problem
>>>>> for your system. But I hope this discussion can be alive on following
>>>>> points for a better fix.
>>>>>
>>>>> 1. The original issue at my end was not just a configuration
>>>>> redundancy.
>>>>> I realize now that with more stream addition following error print
>>>>> is seen.
>>>>>      "ASoC: too many users playback at open 4"
>>>>>
>>>>>      This is because the max DPCM users is capped at 8. Increasing this
>>>>> may help (need to see what number is better), but does not address the
>>>>> redundancy problem.
>>> we haven't used more than 2 users, but it's already broken at 2 with
>>> race conditions left and right. I am really surprised you managed to
>>> have more than 2 without hitting inconsistent states - our automated
>>> play/stop/pause monkey tests reliably break DPCM in less than 20s.
>> I am not sure what is the exact difference, may be DPCM usage in our
>> case is different from what you have. I have mixer tests for different
>> combinations (2x1, 3x1 ...), which seem to pass. In general, we want to
>> have path like this.
>>
>> FE -> BE1 -> BE2 -> ... -> BEx
>>
>> Each BEx could be a mixer, resampler etc., Currently DPCM core sees this
>> as multiple BEs for a given FE and that is why multiple "users" are
>> reported.
> This sort of flow vastly exceeds the capabilities of DPCM, which is
> already badly broken with one BE and 2 FEs... I think what you want is
> what Lars described at the audio miniconf with 'domains'.

May be the core would require enhancements to fully support such scheme. 
But so far the system is running well for below path:
FE -> BE1 (crossbar) -> BE2 (I2S) -> BE3 (external codec)

I could introduce more BEs like resampler or mixer in the path and 
results seem to be good.

BTW, I don't know what 'domains' mean. I will be curious to know what 
this exactly is. If someone is already using it, a usage reference can help.

>> In the interim, may be we can have following patch to keep both systems
>> working and keep the discussion going to address the oustanding
>> requirements/issues?
>>
>> diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
>> index ab25f99..0fbab50 100644
>> --- a/sound/soc/soc-pcm.c
>> +++ b/sound/soc/soc-pcm.c
>> @@ -1395,7 +1395,13 @@ static int dpcm_add_paths(struct
>> snd_soc_pcm_runtime *fe, int stream,
>>                  if (!fe->dpcm[stream].runtime && !fe->fe_compr)
>>                          continue;
>>
>> -               if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
>> +               /*
>> +                * Filter for systems with 'component_chaining' enabled.
>> +                * This helps to avoid unnecessary re-configuration of an
>> +                * already active BE on such systems.
>> +                */
>> +               if (fe->card->component_chaining &&
>> +                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
>>                      (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
>>                          continue;
> that wouldn't work. We need to support the STOP and START cases as well.
>

I meant with flag 'fe->card->component_chaining', which is currently 
used by Tegra audio only.

>>>>> 2. If reconfiguration of the same BE is not necessary for a subsequent
>>>>> FE run, shouldn't we avoid the reconfig itself and somehow avoid FE
>>>>> failure?
>>>> I'm not sure, but it might be possible to just skip the
>>>> dpcm_set_be_update_state(be, stream, SND_SOC_DPCM_UPDATE_BE);
>>>> call at the end of the loop, but the question is under which condition?
>>>> Can a BE asked to be reconfigured when STOP/OPEN/HW_PARAMS?
>>>>
>>>> Skipping the connect does not sound right for a new FE-BE connection.
>>> The reconfiguration is one problem, but what also happens is that the BE
>>> dailink will see multiple triggers. I've been playing with refcounts to
>>> force consistency and make sure there is only one TRIGGER_START send to
>>> the dailink, and conversely there are cases where the TRIGGER_STOP is
>>> never sent...
>> Just a thought. FE links have dummy codec DAI and core wants to find a
>> real BE when FE is started. May be don't fail a FE when no back end DAI
>> is found (and/or find if the same BE is already connected to some FE)
>> and the above problem becomes simpler?
> That would be just moving the problem. In our case we would be silently
> playing on a dummy output just because the correct output was not found
> due to state handling issues.

OK. In our case, application would report error since the frames would 
never get consumed for given FE due to unavailable BE.


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

* Re: [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE
  2021-09-30 15:35               ` Sameer Pujar
@ 2021-09-30 16:13                 ` Pierre-Louis Bossart
  0 siblings, 0 replies; 29+ messages in thread
From: Pierre-Louis Bossart @ 2021-09-30 16:13 UTC (permalink / raw)
  To: Sameer Pujar, Péter Ujfalusi, broonie, lgirdwood, robh+dt,
	thierry.reding, jonathanh, catalin.marinas, will, perex, tiwai,
	kuninori.morimoto.gx
  Cc: devicetree, alsa-devel, linux-kernel, linux-tegra, sharadg,
	linux-arm-kernel


>>>> Can you describe the sequence that you used to start them? That may be
>>>> useful to understand the criteria you used?
>>> I have something like this:
>>>
>>> FE1  --> Crossbar -> Mixer Input1    |
>>> FE2  --> Crossbar -> Mixer Input2    |
>>> ...                                  | --> Mixer Output -->
>>> ... |
>>> FE10 --> Crossbar -> Mixer Input10   |
>>>
>>> All these FEs are started one after the other. This is an example of
>>> 10x1. Similarly we can have 2x1, 3x1 etc.,
>>> In our system, the crossbar [0] and mixer [1] are separate ASoC
>>> components. Basically audio paths consist of a group of ASoC components
>>> which are connected back to back.
>> Not following. Can you explain how starting FE1 does not change the
>> state of the mixer output then?
>>
>> Or is each 'Crossbar' instance a full-blown BE? In that case you have a
>> 1:1 mapping between FE and BE, a *really* simple topology...
> 
> Yes 'Crossbar' exposes multiple ports and it is 1:1 mapping with FE.
> Starting FE1 does configure mixer output.

Ah ok, now I get the difference with the N:1 topology we used.
Thanks for explaining this.

>>> In the interim, may be we can have following patch to keep both systems
>>> working and keep the discussion going to address the oustanding
>>> requirements/issues?
>>>
>>> diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
>>> index ab25f99..0fbab50 100644
>>> --- a/sound/soc/soc-pcm.c
>>> +++ b/sound/soc/soc-pcm.c
>>> @@ -1395,7 +1395,13 @@ static int dpcm_add_paths(struct
>>> snd_soc_pcm_runtime *fe, int stream,
>>>                  if (!fe->dpcm[stream].runtime && !fe->fe_compr)
>>>                          continue;
>>>
>>> -               if ((be->dpcm[stream].state !=
>>> SND_SOC_DPCM_STATE_NEW) &&
>>> +               /*
>>> +                * Filter for systems with 'component_chaining' enabled.
>>> +                * This helps to avoid unnecessary re-configuration
>>> of an
>>> +                * already active BE on such systems.
>>> +                */
>>> +               if (fe->card->component_chaining &&
>>> +                   (be->dpcm[stream].state !=
>>> SND_SOC_DPCM_STATE_NEW) &&
>>>                      (be->dpcm[stream].state !=
>>> SND_SOC_DPCM_STATE_CLOSE))
>>>                          continue;
>> that wouldn't work. We need to support the STOP and START cases as well.
>>
> 
> I meant with flag 'fe->card->component_chaining', which is currently
> used by Tegra audio only.

Ah yes, this may be a temporary solution that gets us both back to a
'working solution'. Let me give it a try.
Good discussion, thanks!
-Pierre

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

* Re: [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE
  2021-09-29  7:43     ` Sameer Pujar
       [not found]       ` <2f96f1aa-74f2-8ea8-3f43-e4da97400fde@linux.intel.com>
@ 2021-09-30 19:00       ` Pierre-Louis Bossart
  2021-10-04  4:38         ` Sameer Pujar
  1 sibling, 1 reply; 29+ messages in thread
From: Pierre-Louis Bossart @ 2021-09-30 19:00 UTC (permalink / raw)
  To: Sameer Pujar, broonie, lgirdwood, robh+dt, thierry.reding,
	jonathanh, catalin.marinas, will, perex, tiwai,
	kuninori.morimoto.gx
  Cc: devicetree, alsa-devel, linux-kernel, sharadg, linux-tegra,
	linux-arm-kernel


> 1. The original issue at my end was not just a configuration redundancy.
> I realize now that with more stream addition following error print is seen.
>    "ASoC: too many users playback at open 4"
> 
>    This is because the max DPCM users is capped at 8. Increasing this
> may help (need to see what number is better), but does not address the
> redundancy problem.
Going back to this DPCM_MAX_BE_USERS definition, it seems rather
arbitrary and not so useful indeed.

	/* first time the dpcm is open ? */
	if (be->dpcm[stream].users == DPCM_MAX_BE_USERS) {
		dev_err(be->dev, "ASoC: too many users %s at open %d\n",
			stream ? "capture" : "playback",
			be->dpcm[stream].state);
		continue;
	}

The comment is no longer aligned with the code, wondering if this is a
feature or a bug. There's no reason to arbitrarily restrict the number
of users of a BE, or the check would need to use platform-specific
information such as the number of inputs/outputs supported by a mixer/demux.

Maybe Morimoto-san can comment since this was added in:

1db19c151819 ('ASoC: soc-pcm: fixup dpcm_be_dai_startup() user count')

We're not done with soc-pcm.c cleanups :-)

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

* Re: [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE
  2021-09-30 19:00       ` Pierre-Louis Bossart
@ 2021-10-04  4:38         ` Sameer Pujar
  0 siblings, 0 replies; 29+ messages in thread
From: Sameer Pujar @ 2021-10-04  4:38 UTC (permalink / raw)
  To: Pierre-Louis Bossart, broonie, lgirdwood, robh+dt,
	thierry.reding, jonathanh, catalin.marinas, will, perex, tiwai,
	kuninori.morimoto.gx
  Cc: devicetree, alsa-devel, linux-kernel, sharadg, linux-tegra,
	linux-arm-kernel



On 10/1/2021 12:30 AM, Pierre-Louis Bossart wrote:
>> 1. The original issue at my end was not just a configuration redundancy.
>> I realize now that with more stream addition following error print is seen.
>>     "ASoC: too many users playback at open 4"
>>
>>     This is because the max DPCM users is capped at 8. Increasing this
>> may help (need to see what number is better), but does not address the
>> redundancy problem.
> Going back to this DPCM_MAX_BE_USERS definition, it seems rather
> arbitrary and not so useful indeed.

>          /* first time the dpcm is open ? */
>          if (be->dpcm[stream].users == DPCM_MAX_BE_USERS) {
>                  dev_err(be->dev, "ASoC: too many users %s at open %d\n",
>                          stream ? "capture" : "playback",
>                          be->dpcm[stream].state);
>                  continue;
>          }
>
> The comment is no longer aligned with the code, wondering if this is a
> feature or a bug.

Looks like the comment is misplaced and the intention might have been to 
place it like below?

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index e30cb5a..5cb5019 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1508,7 +1508,6 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime 
*fe, int stream)
                 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
                         continue;

-               /* first time the dpcm is open ? */
                 if (be->dpcm[stream].users == DPCM_MAX_BE_USERS) {
                         dev_err(be->dev, "ASoC: too many users %s at 
open %d\n",
                                 stream ? "capture" : "playback",
@@ -1516,6 +1515,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime 
*fe, int stream)
                         continue;
                 }

+               /* first time the dpcm is open ? */
                 if (be->dpcm[stream].users++ != 0)
                         continue;

>   There's no reason to arbitrarily restrict the number
> of users of a BE, or the check would need to use platform-specific
> information such as the number of inputs/outputs supported by a mixer/demux.
>
> Maybe Morimoto-san can comment since this was added in:
>
> 1db19c151819 ('ASoC: soc-pcm: fixup dpcm_be_dai_startup() user count')
>
> We're not done with soc-pcm.c cleanups :-)


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

end of thread, other threads:[~2021-10-04  4:38 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-27  9:33 [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar
2021-08-27  9:33 ` [PATCH 01/13] ASoC: soc-pcm: Don't reconnect an already active BE Sameer Pujar
2021-09-28 21:25   ` Pierre-Louis Bossart
2021-09-29  7:43     ` Sameer Pujar
     [not found]       ` <2f96f1aa-74f2-8ea8-3f43-e4da97400fde@linux.intel.com>
2021-09-29 14:52         ` Pierre-Louis Bossart
2021-09-30  7:57           ` Sameer Pujar
2021-09-30 14:34             ` Pierre-Louis Bossart
2021-09-30 15:35               ` Sameer Pujar
2021-09-30 16:13                 ` Pierre-Louis Bossart
2021-09-30 19:00       ` Pierre-Louis Bossart
2021-10-04  4:38         ` Sameer Pujar
2021-08-27  9:33 ` [PATCH 02/13] ASoC: simple-card-utils: Increase maximum DAI links limit to 512 Sameer Pujar
2021-08-27  9:33 ` [PATCH 03/13] ASoC: audio-graph: Fixup CPU endpoint hw_params in a BE<->BE link Sameer Pujar
2021-08-27  9:33 ` [PATCH 04/13] ASoC: dt-bindings: tegra: Few more Tegra210 AHUB modules Sameer Pujar
2021-08-31 20:21   ` Rob Herring
2021-09-01  7:09     ` Sameer Pujar
2021-08-27  9:33 ` [PATCH 05/13] ASoC: tegra: Add routes for few " Sameer Pujar
2021-08-27  9:33 ` [PATCH 06/13] ASoC: tegra: Add Tegra210 based MVC driver Sameer Pujar
2021-09-03 18:13   ` Mark Brown
     [not found]     ` <7b248062-9a62-524c-4c96-295685e211b1@nvidia.com>
     [not found]       ` <86fc49a3-4cac-78c7-2c0c-eaee8e49d387@nvidia.com>
2021-09-09 14:20         ` Mark Brown
     [not found]     ` <29c785d0-cc70-7cce-c205-77059c11e0e1@nvidia.com>
2021-09-13 14:23       ` Mark Brown
2021-08-27  9:33 ` [PATCH 07/13] ASoC: tegra: Add Tegra210 based SFC driver Sameer Pujar
2021-08-27  9:33 ` [PATCH 08/13] ASoC: tegra: Add Tegra210 based AMX driver Sameer Pujar
2021-08-27  9:33 ` [PATCH 09/13] ASoC: tegra: Add Tegra210 based ADX driver Sameer Pujar
2021-08-27  9:33 ` [PATCH 10/13] ASoC: tegra: Add Tegra210 based Mixer driver Sameer Pujar
2021-08-27  9:33 ` [PATCH 11/13] arm64: defconfig: Enable few Tegra210 based AHUB drivers Sameer Pujar
2021-08-27  9:33 ` [PATCH 12/13] arm64: tegra: Add few AHUB devices for Tegra210 and later Sameer Pujar
2021-08-27  9:33 ` [PATCH 13/13] arm64: tegra: Extend APE audio support on Jetson platforms Sameer Pujar
2021-09-08  4:56 ` [PATCH 00/13] Extend AHUB audio support for Tegra210 and later Sameer Pujar

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