Commit 2a07ef63 authored by Mark Brown's avatar Mark Brown

Merge series "Extend AHUB audio support for Tegra210 and later" from Sameer...

Merge series "Extend AHUB audio support for Tegra210 and later" from Sameer Pujar <spujar@nvidia.com>:

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

Changelog
=========

v1 -> v2
--------
 * Put comments for soft reset application in the drivers.
 * Split out mute/volume control logic in put() calls of MVC driver and
   use separate callbacks for the respective kcontrols.
 * Update kcontrol put() callback in MVC driver to return 1 whenever
   there is change. Similar change is done in other drivers too.
 * Use name-prefix.yaml reference for the driver documentation now.
 * Add sound-name-prefix pattern for MIXER driver and use prefix
   accordingly in DT.

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        |   76 +
 .../bindings/sound/nvidia,tegra210-ahub.yaml       |   20 +
 .../bindings/sound/nvidia,tegra210-amx.yaml        |   76 +
 .../bindings/sound/nvidia,tegra210-mixer.yaml      |   74 +
 .../bindings/sound/nvidia,tegra210-mvc.yaml        |   76 +
 .../bindings/sound/nvidia,tegra210-sfc.yaml        |   73 +
 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                     |  531 +++
 sound/soc/tegra/tegra210_adx.h                     |   72 +
 sound/soc/tegra/tegra210_ahub.c                    |  511 ++-
 sound/soc/tegra/tegra210_amx.c                     |  600 ++++
 sound/soc/tegra/tegra210_amx.h                     |   93 +
 sound/soc/tegra/tegra210_mixer.c                   |  674 ++++
 sound/soc/tegra/tegra210_mixer.h                   |  100 +
 sound/soc/tegra/tegra210_mvc.c                     |  645 ++++
 sound/soc/tegra/tegra210_mvc.h                     |  117 +
 sound/soc/tegra/tegra210_sfc.c                     | 3549 ++++++++++++++++++++
 sound/soc/tegra/tegra210_sfc.h                     |   78 +
 31 files changed, 13647 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
parents 0f9a84b2 05bb3d5e
# 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>
allOf:
- $ref: name-prefix.yaml#
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]$"
ports:
$ref: /schemas/graph.yaml#/properties/ports
description: |
ADX has one input and four outputs. Accordingly ACIF (Audio Client
Interface) port nodes are defined to represent ADX input (port 0)
and outputs (ports 1 to 4). These are connected to corresponding
ports on AHUB (Audio Hub).
properties:
port@0:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: ADX ACIF input port
patternProperties:
'^port@[1-4]':
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: ADX ACIF output ports
required:
- compatible
- reg
additionalProperties: false
examples:
- |
adx@702d3800 {
compatible = "nvidia,tegra210-adx";
reg = <0x702d3800 0x100>;
sound-name-prefix = "ADX1";
};
...
......@@ -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#
'^amixer@[0-9a-f]+$':
type: object
$ref: nvidia,tegra210-mixer.yaml#
required:
- compatible
- reg
......
# 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>
allOf:
- $ref: name-prefix.yaml#
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]$"
ports:
$ref: /schemas/graph.yaml#/properties/ports
description: |
AMX has four inputs and one output. Accordingly ACIF (Audio Client
Interfaces) port nodes are defined to represent AMX inputs (port 0
to 3) and output (port 4). These are connected to corresponding
ports on AHUB (Audio Hub).
patternProperties:
'^port@[0-3]':
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: AMX ACIF input ports
properties:
port@4:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: AMX ACIF output port
required:
- compatible
- reg
additionalProperties: false
examples:
- |
amx@702d3000 {
compatible = "nvidia,tegra210-amx";
reg = <0x702d3000 0x100>;
sound-name-prefix = "AMX1";
};
...
# 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>
allOf:
- $ref: name-prefix.yaml#
properties:
$nodename:
pattern: "^amixer@[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:
pattern: "^MIXER[1-9]$"
ports:
$ref: /schemas/graph.yaml#/properties/ports
description: |
Mixer has ten inputs and five outputs. Accordingly ACIF (Audio
Client Interfaces) port nodes are defined to represent Mixer
inputs (port 0 to 9) and outputs (port 10 to 14). These are
connected to corresponding ports on AHUB (Audio Hub).
patternProperties:
'^port@[0-9]':
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: Mixer ACIF input ports
'^port@[10-14]':
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: Mixer ACIF output ports
required:
- compatible
- reg
additionalProperties: false
examples:
- |
amixer@702dbb00 {
compatible = "nvidia,tegra210-amixer";
reg = <0x702dbb00 0x800>;
sound-name-prefix = "MIXER1";
};
...
# 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>
allOf:
- $ref: name-prefix.yaml#
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]$"
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: |
MVC ACIF (Audio Client Interface) input port. This is connected
to corresponding ACIF output port on AHUB (Audio Hub).
port@1:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: |
MVC ACIF output port. This is connected to corresponding ACIF
input port on AHUB.
required:
- compatible
- reg
additionalProperties: false
examples:
- |
mvc@702da000 {
compatible = "nvidia,tegra210-mvc";
reg = <0x702da000 0x200>;
sound-name-prefix = "MVC1";
};
...
# 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>
allOf:
- $ref: name-prefix.yaml#
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]$"
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: |
SFC ACIF (Audio Client Interface) input port. This is connected
to corresponding ACIF output port on AHUB (Audio Hub).
port@1:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: |
SFC ACIF output port. This is connected to corresponding ACIF
input port on AHUB.
required:
- compatible
- reg
additionalProperties: false
examples:
- |
sfc@702d2000 {
compatible = "nvidia,tegra210-sfc";
reg = <0x702d2000 0x200>;
sound-name-prefix = "SFC1";
};
...
......@@ -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 */
......
......@@ -310,8 +310,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);
asoc_simple_canonicalize_platform(platforms, cpus);
......
......@@ -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) {
......
......@@ -108,6 +108,54 @@ 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_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_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_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_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
......
......@@ -13,6 +13,11 @@ 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
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
......@@ -26,6 +31,11 @@ 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
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
......
This diff is collapsed.
/* 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
This diff is collapsed.
This diff is collapsed.
/* 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
This diff is collapsed.
/* 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
This diff is collapsed.
/* 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
This diff is collapsed.
/* 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment