ASoC: ASRC support on Tegra186 and later

Merge series from Sameer Pujar <spujar@nvidia.com>:

This series adds support for Asynchronous Sample Rate Converter (ASRC)
module on Tegra186 and later generations of SoCs. ASRC is a client of
AHUB. The driver and DT support is added to make it work with Tegra
audio graph card. The module can be plugged into audio path using ALSA
mixer controls.

ASRC supports two modes of operation, where it gets the ratio info
from SW and ratio detector module. Presently the support is added for
SW mode.
This commit is contained in:
Mark Brown 2022-04-05 10:25:03 +01:00
commit 66e384d86f
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
7 changed files with 1338 additions and 1 deletions

View File

@ -0,0 +1,81 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra186-asrc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Tegra186 ASRC Device Tree Bindings
description: |
Asynchronous Sample Rate Converter (ASRC) converts the sampling frequency
of the input signal from one frequency to another. It can handle over a
wide range of sample rate ratios (freq_in/freq_out) from 1:24 to 24:1.
ASRC has two modes of operation. One where ratio can be programmed in SW
and the other where it gets the information from ratio estimator module.
It supports sample rate conversions in the range of 8 to 192 kHz and
supports 6 streams upto 12 total channels. The input data size can be
16, 24 and 32 bits.
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Mohan Kumar <mkumard@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: name-prefix.yaml#
properties:
$nodename:
pattern: "^asrc@[0-9a-f]*$"
compatible:
oneOf:
- const: nvidia,tegra186-asrc
- items:
- enum:
- nvidia,tegra234-asrc
- nvidia,tegra194-asrc
- const: nvidia,tegra186-asrc
reg:
maxItems: 1
sound-name-prefix:
pattern: "^ASRC[1-9]$"
ports:
$ref: /schemas/graph.yaml#/properties/ports
description: |
ASRC has seven input ports and six output ports. Accordingly ACIF
(Audio Client Interfaces) port nodes are defined to represent the
ASRC inputs (port 0 to 6) and outputs (port 7 to 12). These are
connected to corresponding ports on AHUB (Audio Hub). Additional
input (port 6) is for receiving ratio information from estimator.
patternProperties:
'^port@[0-6]':
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: ASRC ACIF input ports
'^port@[7-9]|1[1-2]':
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: ASRC ACIF output ports
required:
- compatible
- reg
additionalProperties: false
examples:
- |
asrc@2910000 {
compatible = "nvidia,tegra186-asrc";
reg = <0x2910000 0x2000>;
sound-name-prefix = "ASRC1";
};
...

View File

@ -106,6 +106,10 @@ patternProperties:
type: object
$ref: nvidia,tegra210-mixer.yaml#
'^asrc@[0-9a-f]+$':
type: object
$ref: nvidia,tegra186-asrc.yaml#
required:
- compatible
- reg

View File

@ -85,6 +85,18 @@ config SND_SOC_TEGRA210_I2S
compatible devices.
Say Y or M if you want to add support for Tegra210 I2S module.
config SND_SOC_TEGRA186_ASRC
tristate "Tegra186 ASRC module"
help
Config to enable the Asynchronous Sample Rate Converter (ASRC),
which converts the sampling frequency of the input signal from
one frequency to another. It can handle over a wide range of
sample rate ratios (freq_in/freq_out) from 1:24 to 24:1.
ASRC has two modes of operation. One where ratio can be programmed
in SW and the other where it gets information from ratio estimator
module.
Say Y or M if you want to add support for Tegra186 ASRC module.
config SND_SOC_TEGRA186_DSPK
tristate "Tegra186 DSPK module"
help

View File

@ -11,6 +11,7 @@ snd-soc-tegra30-i2s-objs := tegra30_i2s.o
snd-soc-tegra210-ahub-objs := tegra210_ahub.o
snd-soc-tegra210-dmic-objs := tegra210_dmic.o
snd-soc-tegra210-i2s-objs := tegra210_i2s.o
snd-soc-tegra186-asrc-objs := tegra186_asrc.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
@ -29,6 +30,7 @@ obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o
obj-$(CONFIG_SND_SOC_TEGRA210_DMIC) += snd-soc-tegra210-dmic.o
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_ASRC) += snd-soc-tegra186-asrc.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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,112 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* tegra186_asrc.h - Definitions for Tegra186 ASRC driver
*
* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
*
*/
#ifndef __TEGRA186_ASRC_H__
#define __TEGRA186_ASRC_H__
/* ASRC stream related offset */
#define TEGRA186_ASRC_CFG 0x0
#define TEGRA186_ASRC_RATIO_INT_PART 0x4
#define TEGRA186_ASRC_RATIO_FRAC_PART 0x8
#define TEGRA186_ASRC_RATIO_LOCK_STATUS 0xc
#define TEGRA186_ASRC_MUTE_UNMUTE_DURATION 0x10
#define TEGRA186_ASRC_TX_THRESHOLD 0x14
#define TEGRA186_ASRC_RX_THRESHOLD 0x18
#define TEGRA186_ASRC_RATIO_COMP 0x1c
#define TEGRA186_ASRC_RX_STATUS 0x20
#define TEGRA186_ASRC_RX_CIF_CTRL 0x24
#define TEGRA186_ASRC_TX_STATUS 0x2c
#define TEGRA186_ASRC_TX_CIF_CTRL 0x30
#define TEGRA186_ASRC_ENABLE 0x38
#define TEGRA186_ASRC_SOFT_RESET 0x3c
#define TEGRA186_ASRC_STATUS 0x4c
#define TEGRA186_ASRC_STATEBUF_ADDR 0x5c
#define TEGRA186_ASRC_STATEBUF_CFG 0x60
#define TEGRA186_ASRC_INSAMPLEBUF_ADDR 0x64
#define TEGRA186_ASRC_INSAMPLEBUF_CFG 0x68
#define TEGRA186_ASRC_OUTSAMPLEBUF_ADDR 0x6c
#define TEGRA186_ASRC_OUTSAMPLEBUF_CFG 0x70
/* ASRC Global registers offset */
#define TEGRA186_ASRC_GLOBAL_ENB 0x2f4
#define TEGRA186_ASRC_GLOBAL_SOFT_RESET 0x2f8
#define TEGRA186_ASRC_GLOBAL_CG 0x2fc
#define TEGRA186_ASRC_GLOBAL_CFG 0x300
#define TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR 0x304
#define TEGRA186_ASRC_GLOBAL_SCRATCH_CFG 0x308
#define TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL 0x30c
#define TEGRA186_ASRC_RATIO_UPD_RX_STATUS 0x310
#define TEGRA186_ASRC_GLOBAL_STATUS 0x314
#define TEGRA186_ASRC_GLOBAL_STREAM_ENABLE_STATUS 0x318
#define TEGRA186_ASRC_GLOBAL_INT_STATUS 0x324
#define TEGRA186_ASRC_GLOBAL_INT_MASK 0x328
#define TEGRA186_ASRC_GLOBAL_INT_SET 0x32c
#define TEGRA186_ASRC_GLOBAL_INT_CLEAR 0x330
#define TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG 0x334
#define TEGRA186_ASRC_GLOBAL_APR_CTRL 0x1000
#define TEGRA186_ASRC_GLOBAL_APR_CTRL_ACCESS_CTRL 0x1004
#define TEGRA186_ASRC_GLOBAL_DISARM_APR 0x1008
#define TEGRA186_ASRC_GLOBAL_DISARM_APR_ACCESS_CTRL 0x100c
#define TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS 0x1010
#define TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS_CTRL 0x1014
#define TEGRA186_ASRC_CYA 0x1018
#define TEGRA186_ASRC_STREAM_DEFAULT_HW_COMP_BIAS_VALUE 0xaaaa
#define TEGRA186_ASRC_STREAM_DEFAULT_INPUT_HW_COMP_THRESH_CFG 0x00201002
#define TEGRA186_ASRC_STREAM_DEFAULT_OUTPUT_HW_COMP_THRESH_CFG 0x00201002
#define TEGRA186_ASRC_GLOBAL_CFG_FRAC_28BIT_PRECISION 0
#define TEGRA186_ASRC_GLOBAL_CFG_FRAC_32BIT_PRECISION 1
#define TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_SHIFT 31
#define TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK (1 << TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_SHIFT)
#define TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_ENABLE (1 << TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_SHIFT)
#define TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_DISABLE (0 << TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_SHIFT)
#define TEGRA186_ASRC_STREAM_RATIO_TYPE_SHIFT 0
#define TEGRA186_ASRC_STREAM_RATIO_TYPE_MASK (1 << TEGRA186_ASRC_STREAM_RATIO_TYPE_SHIFT)
#define TEGRA186_ASRC_STREAM_EN_SHIFT 0
#define TEGRA186_ASRC_STREAM_EN (1 << TEGRA186_ASRC_STREAM_EN_SHIFT)
#define TEGRA186_ASRC_GLOBAL_EN_SHIFT 0
#define TEGRA186_ASRC_GLOBAL_EN (1 << TEGRA186_ASRC_GLOBAL_EN_SHIFT)
#define TEGRA186_ASRC_STREAM_STATEBUF_CFG_SIZE_SHIFT 0
#define TEGRA186_ASRC_STREAM_STATEBUF_CFG_SIZE_MASK (0xffff << TEGRA186_ASRC_STREAM_STATEBUF_CFG_SIZE_SHIFT)
#define TEGRA186_ASRC_STREAM_INSAMPLEBUF_CFG_SIZE_SHIFT 0
#define TEGRA186_ASRC_STREAM_INSAMPLEBUF_CFG_SIZE_MASK (0xffff << TEGRA186_ASRC_STREAM_INSAMPLEBUF_CFG_SIZE_SHIFT)
#define TEGRA186_ASRC_STREAM_OUTSAMPLEBUF_CFG_SIZE_SHIFT 0
#define TEGRA186_ASRC_STREAM_OUTSAMPLEBUF_CFG_SIZE_MASK (0xffff << TEGRA186_ASRC_STREAM_OUTSAMPLEBUF_CFG_SIZE_SHIFT)
#define TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK 0x1f
#define TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK 0xffffffff
#define TEGRA186_ASRC_STREAM_STRIDE 0x80
#define TEGRA186_ASRC_STREAM_MAX 0x6
#define TEGRA186_ASRC_STREAM_LIMIT 0x2f0
#define TEGRA186_ASRC_RATIO_SOURCE_ARAD 0x0
#define TEGRA186_ASRC_RATIO_SOURCE_SW 0x1
#define TEGRA186_ASRC_ARAM_START_ADDR 0x3f800000
struct tegra186_asrc_lane {
unsigned int int_part;
unsigned int frac_part;
unsigned int ratio_source;
unsigned int hwcomp_disable;
unsigned int input_thresh;
unsigned int output_thresh;
};
struct tegra186_asrc {
struct tegra186_asrc_lane lane[TEGRA186_ASRC_STREAM_MAX];
struct regmap *regmap;
};
#endif

View File

@ -280,6 +280,20 @@ static struct snd_soc_dai_driver tegra186_ahub_dais[] = {
DAI(MIXER1 TX3),
DAI(MIXER1 TX4),
DAI(MIXER1 TX5),
/* XBAR -> ASRC -> XBAR */
DAI(ASRC1 RX1),
DAI(ASRC1 TX1),
DAI(ASRC1 RX2),
DAI(ASRC1 TX2),
DAI(ASRC1 RX3),
DAI(ASRC1 TX3),
DAI(ASRC1 RX4),
DAI(ASRC1 TX4),
DAI(ASRC1 RX5),
DAI(ASRC1 TX5),
DAI(ASRC1 RX6),
DAI(ASRC1 TX6),
DAI(ASRC1 RX7),
};
static const char * const tegra210_ahub_mux_texts[] = {
@ -388,6 +402,12 @@ static const char * const tegra186_ahub_mux_texts[] = {
"MIXER1 TX3",
"MIXER1 TX4",
"MIXER1 TX5",
"ASRC1 TX1",
"ASRC1 TX2",
"ASRC1 TX3",
"ASRC1 TX4",
"ASRC1 TX5",
"ASRC1 TX6",
};
static const unsigned int tegra210_ahub_mux_values[] = {
@ -513,6 +533,13 @@ static const unsigned int tegra186_ahub_mux_values[] = {
MUX_VALUE(1, 2),
MUX_VALUE(1, 3),
MUX_VALUE(1, 4),
/* ASRC */
MUX_VALUE(3, 24),
MUX_VALUE(3, 25),
MUX_VALUE(3, 26),
MUX_VALUE(3, 27),
MUX_VALUE(3, 28),
MUX_VALUE(3, 29),
};
/* Controls for t210 */
@ -623,6 +650,13 @@ 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);
MUX_ENUM_CTRL_DECL_186(t186_asrc11_tx, 0x6c);
MUX_ENUM_CTRL_DECL_186(t186_asrc12_tx, 0x6d);
MUX_ENUM_CTRL_DECL_186(t186_asrc13_tx, 0x6e);
MUX_ENUM_CTRL_DECL_186(t186_asrc14_tx, 0x6f);
MUX_ENUM_CTRL_DECL_186(t186_asrc15_tx, 0x70);
MUX_ENUM_CTRL_DECL_186(t186_asrc16_tx, 0x71);
MUX_ENUM_CTRL_DECL_186(t186_asrc17_tx, 0x72);
/* Controls for t234 */
MUX_ENUM_CTRL_DECL_234(t234_mvc1_tx, 0x44);
@ -651,6 +685,13 @@ MUX_ENUM_CTRL_DECL_234(t234_admaif17_tx, 0x60);
MUX_ENUM_CTRL_DECL_234(t234_admaif18_tx, 0x61);
MUX_ENUM_CTRL_DECL_234(t234_admaif19_tx, 0x62);
MUX_ENUM_CTRL_DECL_234(t234_admaif20_tx, 0x63);
MUX_ENUM_CTRL_DECL_234(t234_asrc11_tx, 0x64);
MUX_ENUM_CTRL_DECL_234(t234_asrc12_tx, 0x65);
MUX_ENUM_CTRL_DECL_234(t234_asrc13_tx, 0x66);
MUX_ENUM_CTRL_DECL_234(t234_asrc14_tx, 0x67);
MUX_ENUM_CTRL_DECL_234(t234_asrc15_tx, 0x68);
MUX_ENUM_CTRL_DECL_234(t234_asrc16_tx, 0x69);
MUX_ENUM_CTRL_DECL_234(t234_asrc17_tx, 0x6a);
/*
* The number of entries in, and order of, this array is closely tied to the
@ -813,6 +854,19 @@ static const struct snd_soc_dapm_widget tegra186_ahub_widgets[] = {
TX_WIDGETS("MIXER1 TX3"),
TX_WIDGETS("MIXER1 TX4"),
TX_WIDGETS("MIXER1 TX5"),
WIDGETS("ASRC1 RX1", t186_asrc11_tx),
WIDGETS("ASRC1 RX2", t186_asrc12_tx),
WIDGETS("ASRC1 RX3", t186_asrc13_tx),
WIDGETS("ASRC1 RX4", t186_asrc14_tx),
WIDGETS("ASRC1 RX5", t186_asrc15_tx),
WIDGETS("ASRC1 RX6", t186_asrc16_tx),
WIDGETS("ASRC1 RX7", t186_asrc17_tx),
TX_WIDGETS("ASRC1 TX1"),
TX_WIDGETS("ASRC1 TX2"),
TX_WIDGETS("ASRC1 TX3"),
TX_WIDGETS("ASRC1 TX4"),
TX_WIDGETS("ASRC1 TX5"),
TX_WIDGETS("ASRC1 TX6"),
};
static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = {
@ -909,6 +963,19 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = {
TX_WIDGETS("MIXER1 TX3"),
TX_WIDGETS("MIXER1 TX4"),
TX_WIDGETS("MIXER1 TX5"),
WIDGETS("ASRC1 RX1", t234_asrc11_tx),
WIDGETS("ASRC1 RX2", t234_asrc12_tx),
WIDGETS("ASRC1 RX3", t234_asrc13_tx),
WIDGETS("ASRC1 RX4", t234_asrc14_tx),
WIDGETS("ASRC1 RX5", t234_asrc15_tx),
WIDGETS("ASRC1 RX6", t234_asrc16_tx),
WIDGETS("ASRC1 RX7", t234_asrc17_tx),
TX_WIDGETS("ASRC1 TX1"),
TX_WIDGETS("ASRC1 TX2"),
TX_WIDGETS("ASRC1 TX3"),
TX_WIDGETS("ASRC1 TX4"),
TX_WIDGETS("ASRC1 TX5"),
TX_WIDGETS("ASRC1 TX6"),
};
#define TEGRA_COMMON_MUX_ROUTES(name) \
@ -975,7 +1042,13 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = {
{ 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" },
{ name " Mux", "ADX4 TX4", "ADX4 TX4 XBAR-RX" }, \
{ name " Mux", "ASRC1 TX1", "ASRC1 TX1 XBAR-RX" }, \
{ name " Mux", "ASRC1 TX2", "ASRC1 TX2 XBAR-RX" }, \
{ name " Mux", "ASRC1 TX3", "ASRC1 TX3 XBAR-RX" }, \
{ name " Mux", "ASRC1 TX4", "ASRC1 TX4 XBAR-RX" }, \
{ name " Mux", "ASRC1 TX5", "ASRC1 TX5 XBAR-RX" }, \
{ name " Mux", "ASRC1 TX6", "ASRC1 TX6 XBAR-RX" },
#define TEGRA210_MUX_ROUTES(name) \
TEGRA_COMMON_MUX_ROUTES(name)
@ -1135,6 +1208,13 @@ static const struct snd_soc_dapm_route tegra186_ahub_routes[] = {
TEGRA186_MUX_ROUTES("MIXER1 RX8")
TEGRA186_MUX_ROUTES("MIXER1 RX9")
TEGRA186_MUX_ROUTES("MIXER1 RX10")
TEGRA186_MUX_ROUTES("ASRC1 RX1")
TEGRA186_MUX_ROUTES("ASRC1 RX2")
TEGRA186_MUX_ROUTES("ASRC1 RX3")
TEGRA186_MUX_ROUTES("ASRC1 RX4")
TEGRA186_MUX_ROUTES("ASRC1 RX5")
TEGRA186_MUX_ROUTES("ASRC1 RX6")
TEGRA186_MUX_ROUTES("ASRC1 RX7")
};
static const struct snd_soc_component_driver tegra210_ahub_component = {