提交 dec36c09 编写于 作者: T Takashi Iwai

Merge tag 'asoc-v5.17' of...

Merge tag 'asoc-v5.17' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Updates for v5.17

Not much going on framework release this time, but a big update for
drivers especially the Intel and SOF ones.

 - Refinements and cleanups around the delay() APIs.
 - Wider use of dev_err_probe().
 - Continuing cleanups and improvements to the SOF code.
 - Support for pin switches in simple-card derived cards.
 - Support for AMD Renoir ACP, Asahi Kasei Microdevices AKM4375, Intel
   systems using NAU8825 and MAX98390, Mediatek MT8915, nVidia Tegra20
   S/PDIF, Qualcomm systems using ALC5682I-VS and Texas Instruments
   TLV320ADC3xxx.
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ak4375.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: AK4375 DAC and headphones amplifier Device Tree Bindings
maintainers:
- Vincent Knecht <vincent.knecht@mailoo.org>
properties:
compatible:
const: asahi-kasei,ak4375
reg:
maxItems: 1
'#sound-dai-cells':
const: 0
avdd-supply:
description: regulator phandle for the AVDD power supply.
tvdd-supply:
description: regulator phandle for the TVDD power supply.
pdn-gpios:
description: optional GPIO to set the PDN pin.
required:
- compatible
- reg
- '#sound-dai-cells'
- avdd-supply
- tvdd-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
headphones: audio-codec@10 {
compatible = "asahi-kasei,ak4375";
reg = <0x10>;
avdd-supply = <&reg_headphones_avdd>;
tvdd-supply = <&pm8916_l6>;
pdn-gpios = <&msmgpio 114 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&headphones_pdn_default>;
#sound-dai-cells = <0>;
};
};
......@@ -9,6 +9,9 @@ title: Amlogic AIU audio output controller
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
allOf:
- $ref: name-prefix.yaml#
properties:
$nodename:
pattern: "^audio-controller@.*"
......@@ -65,6 +68,8 @@ properties:
resets:
maxItems: 1
sound-name-prefix: true
required:
- "#sound-dai-cells"
- compatible
......
......@@ -9,6 +9,9 @@ title: Amlogic G12a Internal DAC Control Glue
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
allOf:
- $ref: name-prefix.yaml#
properties:
$nodename:
pattern: "^audio-controller@.*"
......@@ -31,6 +34,8 @@ properties:
resets:
maxItems: 1
sound-name-prefix: true
required:
- "#sound-dai-cells"
- compatible
......
......@@ -9,6 +9,9 @@ title: Amlogic T9015 Internal Audio DAC
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
allOf:
- $ref: name-prefix.yaml#
properties:
$nodename:
pattern: "^audio-controller@.*"
......@@ -38,6 +41,8 @@ properties:
description:
Analogue power supply.
sound-name-prefix: true
required:
- "#sound-dai-cells"
- compatible
......
......@@ -42,10 +42,15 @@ patternProperties:
$ref: /schemas/types.yaml#/definitions/flag
frame-master:
description: Indicates dai-link frame master.
$ref: /schemas/types.yaml#/definitions/phandle
oneOf:
- $ref: /schemas/types.yaml#/definitions/flag
- $ref: /schemas/types.yaml#/definitions/phandle
bitclock-master:
description: Indicates dai-link bit clock master
$ref: /schemas/types.yaml#/definitions/phandle
oneOf:
- $ref: /schemas/types.yaml#/definitions/flag
- $ref: /schemas/types.yaml#/definitions/phandle
dai-format:
description: audio format.
items:
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/cirrus,cs42l42.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cirrus Logic CS42L42 audio CODEC
maintainers:
- patches@opensource.cirrus.com
description:
The CS42L42 is a low-power audio codec designed for portable applications.
It provides a high-dynamic range, stereo DAC for audio playback and a mono
high-dynamic-range ADC for audio capture. There is an integrated headset
detection block.
properties:
compatible:
enum:
- cirrus,cs42l42
reg:
description:
The I2C address of the CS42L42.
maxItems: 1
VP-supply:
description:
VP power supply.
VCP-supply:
description:
Charge pump power supply.
VD_FILT-supply:
description:
FILT+ power supply.
VL-supply:
description:
Logic power supply.
VA-supply:
description:
Analog power supply.
reset-gpios:
description:
This pin will be asserted and then deasserted to reset the
CS42L42 before communication starts.
maxItems: 1
interrupts:
description:
Interrupt for CS42L42 IRQ line.
maxItems: 1
cirrus,ts-inv:
description: |
Sets the behaviour of the jack plug detect switch.
0 - (Default) Shorted to tip when unplugged, open when plugged.
This is "inverted tip sense (ITS)" in the datasheet.
1 - Open when unplugged, shorted to tip when plugged.
This is "normal tip sense (TS)" in the datasheet.
The CS42L42_TS_INV_* defines are available for this.
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 1
cirrus,ts-dbnc-rise:
description: |
Debounce the rising edge of TIP_SENSE_PLUG. With no
debounce, the tip sense pin might be noisy on a plug event.
0 - 0ms
1 - 125ms
2 - 250ms
3 - 500ms
4 - 750ms
5 - 1s (Default)
6 - 1.25s
7 - 1.5s
The CS42L42_TS_DBNCE_* defines are available for this.
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 7
cirrus,ts-dbnc-fall:
description: |
Debounce the falling edge of TIP_SENSE_UNPLUG. With no
debounce, the tip sense pin might be noisy on an unplug event.
0 - 0ms
1 - 125ms
2 - 250ms
3 - 500ms
4 - 750ms
5 - 1s (Default)
6 - 1.25s
7 - 1.5s
The CS42L42_TS_DBNCE_* defines are available for this.
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 7
cirrus,btn-det-init-dbnce:
description: |
This sets how long to wait after enabling button detection
interrupts before servicing button interrupts, to allow the
HS bias time to settle. Value is in milliseconds.
There may be erroneous button interrupts if this debounce time
is too short.
0ms - 200ms,
Default = 100ms
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 200
cirrus,btn-det-event-dbnce:
description: |
This sets how long to wait after receiving a button press
interrupt before processing it. Allows time for the button
press to make a clean connection with the bias resistors.
Value is in milliseconds.
0ms - 20ms,
Default = 10ms
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 20
cirrus,bias-lvls:
description: |
For a level-detect headset button scheme, each button will bias
the mic pin to a certain voltage. To determine which button was
pressed, the voltage is compared to sequential, decreasing
voltages, until the compared voltage < bias voltage.
For different hardware setups, a designer might want to tweak this.
This is an array of descending values for the comparator voltage,
given as percent of the HSBIAS voltage.
Array of 4 values, each 0-63
< x1 x2 x3 x4 >
Default = < 15 8 4 1 >
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 4
maxItems: 4
items:
minimum: 0
maximum: 63
cirrus,hs-bias-ramp-rate:
description: |
If present this sets the rate that the HS bias should rise and fall.
The actual rise and fall times depend on external hardware (the
datasheet gives several rise and fall time examples).
0 - Fast rise time; slow, load-dependent fall time
1 - Fast
2 - Slow (default)
3 - Slowest
The CS42L42_HSBIAS_RAMP_* defines are available for this.
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 3
cirrus,hs-bias-sense-disable:
description: |
If present the HSBIAS sense is disabled. Configures HSBIAS output
current sense through the external 2.21-k resistor. HSBIAS_SENSE
is a hardware feature to reduce the potential pop noise when the
headset plug is removed slowly. But on some platforms ESD voltage
will affect it causing plug detection to fail, especially with CTIA
headset type. For different hardware setups, a designer might want
to tweak default behavior.
type: boolean
required:
- compatible
- reg
- VP-supply
- VCP-supply
- VD_FILT-supply
- VL-supply
- VA-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/sound/cs42l42.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
cs42l42: cs42l42@48 {
compatible = "cirrus,cs42l42";
reg = <0x48>;
VA-supply = <&dummy_vreg>;
VP-supply = <&dummy_vreg>;
VCP-supply = <&dummy_vreg>;
VD_FILT-supply = <&dummy_vreg>;
VL-supply = <&dummy_vreg>;
reset-gpios = <&axi_gpio_0 1 0>;
interrupt-parent = <&gpio0>;
interrupts = <55 8>;
cirrus,ts-inv = <CS42L42_TS_INV_DIS>;
cirrus,ts-dbnc-rise = <CS42L42_TS_DBNCE_1000>;
cirrus,ts-dbnc-fall = <CS42L42_TS_DBNCE_0>;
cirrus,btn-det-init-dbnce = <100>;
cirrus,btn-det-event-dbnce = <10>;
cirrus,bias-lvls = <0x0F 0x08 0x04 0x01>;
cirrus,hs-bias-ramp-rate = <CS42L42_HSBIAS_RAMP_SLOW>;
};
};
CS42L42 audio CODEC
Required properties:
- compatible : "cirrus,cs42l42"
- reg : the I2C address of the device for I2C.
- VP-supply, VCP-supply, VD_FILT-supply, VL-supply, VA-supply :
power supplies for the device, as covered in
Documentation/devicetree/bindings/regulator/regulator.txt.
Optional properties:
- reset-gpios : a GPIO spec for the reset pin. If specified, it will be
deasserted before communication to the codec starts.
- interrupts : IRQ line info CS42L42.
(See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
for further information relating to interrupt properties)
- cirrus,ts-inv : Boolean property. Sets the behaviour of the jack plug
detect switch.
0 = (Default) Shorted to tip when unplugged, open when plugged.
This is "inverted tip sense (ITS)" in the datasheet.
1 = Open when unplugged, shorted to tip when plugged.
This is "normal tip sense (TS)" in the datasheet.
- cirrus,ts-dbnc-rise : Debounce the rising edge of TIP_SENSE_PLUG. With no
debounce, the tip sense pin might be noisy on a plug event.
0 - 0ms,
1 - 125ms,
2 - 250ms,
3 - 500ms,
4 - 750ms,
5 - (Default) 1s,
6 - 1.25s,
7 - 1.5s,
- cirrus,ts-dbnc-fall : Debounce the falling edge of TIP_SENSE_UNPLUG.
With no debounce, the tip sense pin might be noisy on an unplug event.
0 - 0ms,
1 - 125ms,
2 - 250ms,
3 - 500ms,
4 - 750ms,
5 - (Default) 1s,
6 - 1.25s,
7 - 1.5s,
- cirrus,btn-det-init-dbnce : This sets how long the driver sleeps after
enabling button detection interrupts. After auto-detection and before
servicing button interrupts, the HS bias needs time to settle. If you
don't wait, there is possibility for erroneous button interrupt.
0ms - 200ms,
Default = 100ms
- cirrus,btn-det-event-dbnce : This sets how long the driver delays after
receiving a button press interrupt. With level detect interrupts, you want
to wait a small amount of time to make sure the button press is making a
clean connection with the bias resistors.
0ms - 20ms,
Default = 10ms
- cirrus,bias-lvls : For a level-detect headset button scheme, each button
will bias the mic pin to a certain voltage. To determine which button was
pressed, the driver will compare this biased voltage to sequential,
decreasing voltages and will stop when a comparator is tripped,
indicating a comparator voltage < bias voltage. This value represents a
percentage of the internally generated HS bias voltage. For different
hardware setups, a designer might want to tweak this. This is an array of
descending values for the comparator voltage.
Array of 4 values
Each 0-63
< x1 x2 x3 x4 >
Default = < 15 8 4 1>
- cirrus,hs-bias-sense-disable: This is boolean property. If present the
HSBIAS sense is disabled. Configures HSBIAS output current sense through
the external 2.21-k resistor. HSBIAS_SENSE is hardware feature to reduce
the potential pop noise during the headset plug out slowly. But on some
platforms ESD voltage will affect it causing test to fail, especially
with CTIA headset type. For different hardware setups, a designer might
want to tweak default behavior.
Example:
cs42l42: cs42l42@48 {
compatible = "cirrus,cs42l42";
reg = <0x48>;
VA-supply = <&dummy_vreg>;
VP-supply = <&dummy_vreg>;
VCP-supply = <&dummy_vreg>;
VD_FILT-supply = <&dummy_vreg>;
VL-supply = <&dummy_vreg>;
reset-gpios = <&axi_gpio_0 1 0>;
interrupt-parent = <&gpio0>;
interrupts = <55 8>
cirrus,ts-inv = <0x00>;
cirrus,ts-dbnc-rise = <0x05>;
cirrus,ts-dbnc-fall = <0x00>;
cirrus,btn-det-init-dbnce = <100>;
cirrus,btn-det-event-dbnce = <10>;
cirrus,bias-lvls = <0x0F 0x08 0x04 0x01>;
cirrus,hs-bias-ramp-rate = <0x02>;
};
......@@ -9,6 +9,9 @@ title: Dummy SPDIF Transmitter Device Tree Bindings
maintainers:
- Mark Brown <broonie@kernel.org>
allOf:
- $ref: name-prefix.yaml#
properties:
compatible:
const: linux,spdif-dit
......@@ -16,6 +19,8 @@ properties:
"#sound-dai-cells":
const: 0
sound-name-prefix: true
required:
- "#sound-dai-cells"
- compatible
......
......@@ -19,6 +19,12 @@ properties:
interrupts:
maxItems: 1
memory-region:
maxItems: 1
description: |
Shared memory region for AFE memif. A "shared-dma-pool".
See ../reserved-memory/reserved-memory.txt for details.
mediatek,topckgen:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of the mediatek topckgen controller
......@@ -125,6 +131,7 @@ required:
- power-domains
- clocks
- clock-names
- memory-region
additionalProperties: false
......@@ -139,6 +146,7 @@ examples:
interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
mediatek,topckgen = <&topckgen>;
power-domains = <&spm 7>; //MT8195_POWER_DOMAIN_AUDIO
memory-region = <&snd_dma_mem_reserved>;
clocks = <&clk26m>,
<&topckgen 163>, //CLK_TOP_APLL1
<&topckgen 166>, //CLK_TOP_APLL2
......
......@@ -16,6 +16,10 @@ properties:
compatible:
const: mediatek,mt8195_mt6359_rt1011_rt5682
model:
$ref: /schemas/types.yaml#/definitions/string
description: User specified audio sound card name
mediatek,platform:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8195 ASoC platform.
......
......@@ -16,6 +16,10 @@ properties:
compatible:
const: mediatek,mt8195_mt6359_rt1019_rt5682
model:
$ref: /schemas/types.yaml#/definitions/string
description: User specified audio sound card name
mediatek,platform:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8195 ASoC platform.
......@@ -28,6 +32,16 @@ properties:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8195 HDMI codec node.
mediatek,adsp:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8195 ADSP platform.
mediatek,dai-link:
$ref: /schemas/types.yaml#/definitions/string-array
description:
A list of the desired dai-links in the sound card. Each entry is a
name defined in the machine driver.
additionalProperties: false
required:
......
NVIDIA Tegra audio complex
Required properties:
- compatible : "nvidia,tegra-audio-alc5632"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the ALC5632's pins as documented in the binding for the device
and:
* Headset Stereophone
* Int Spk
* Headset Mic
* Digital Mic
- nvidia,i2s-controller : The phandle of the Tegra I2S controller
- nvidia,audio-codec : The phandle of the ALC5632 audio codec
Example:
sound {
compatible = "nvidia,tegra-audio-alc5632-paz00",
"nvidia,tegra-audio-alc5632";
nvidia,model = "Compal PAZ00";
nvidia,audio-routing =
"Int Spk", "SPK_OUTP",
"Int Spk", "SPK_OUTN",
"Headset Mic","MICBIAS1",
"MIC1_N", "Headset Mic",
"MIC1_P", "Headset Mic",
"Headset Stereophone", "HP_OUT_R",
"Headset Stereophone", "HP_OUT_L";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&alc5632>;
clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-alc5632.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra audio complex with ALC5632 CODEC
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Thierry Reding <thierry.reding@gmail.com>
allOf:
- $ref: nvidia,tegra-audio-common.yaml#
properties:
compatible:
items:
- pattern: '^[a-z0-9]+,tegra-audio-alc5632(-[a-z0-9]+)+$'
- const: nvidia,tegra-audio-alc5632
nvidia,audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description: |
A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the pins (documented in the binding document),
and the jacks on the board.
minItems: 2
items:
enum:
# Board Connectors
- "Headset Stereophone"
- "Int Spk"
- "Headset Mic"
- "Digital Mic"
# CODEC Pins
- SPKOUT
- SPKOUTN
- MICBIAS1
- MIC1
- HPR
- HPL
- DMICDAT
required:
- nvidia,i2s-controller
unevaluatedProperties: false
examples:
- |
sound {
compatible = "nvidia,tegra-audio-alc5632-paz00",
"nvidia,tegra-audio-alc5632";
nvidia,model = "Compal PAZ00";
nvidia,audio-routing = "Int Spk", "SPKOUT",
"Int Spk", "SPKOUTN",
"Headset Mic", "MICBIAS1",
"MIC1", "Headset Mic",
"Headset Stereophone", "HPR",
"Headset Stereophone", "HPL",
"DMICDAT", "Digital Mic";
nvidia,i2s-controller = <&i2s>;
nvidia,audio-codec = <&codec>;
clocks = <&clk 112>, <&clk 113>, <&clk 93>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/sound/nvidia,tegra-audio-common.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Common properties for NVIDIA Tegra audio complexes
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Thierry Reding <thierry.reding@gmail.com>
properties:
clocks:
items:
- description: PLL A clock
- description: PLL A OUT0 clock
- description: The Tegra cdev1/extern1 clock, which feeds the card's mclk
clock-names:
items:
- const: pll_a
- const: pll_a_out0
- const: mclk
nvidia,model:
$ref: /schemas/types.yaml#/definitions/string
description: The user-visible name of this sound complex.
nvidia,audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description: |
A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the pins (documented in the binding document),
and the jacks on the board.
nvidia,ac97-controller:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of the AC97 controller
nvidia,i2s-controller:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of the Tegra I2S controller
nvidia,audio-codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of audio codec
nvidia,spkr-en-gpios:
maxItems: 1
description: The GPIO that enables the speakers
nvidia,hp-mute-gpios:
maxItems: 1
description: The GPIO that mutes the headphones
nvidia,hp-det-gpios:
maxItems: 1
description: The GPIO that detect headphones are plugged in
nvidia,mic-det-gpios:
maxItems: 1
description: The GPIO that detect microphone is plugged in
nvidia,ear-sel-gpios:
maxItems: 1
description: The GPIO that switch between the microphones
nvidia,int-mic-en-gpios:
maxItems: 1
description: The GPIO that enables the internal microphone
nvidia,ext-mic-en-gpios:
maxItems: 1
description: The GPIO that enables the external microphone
nvidia,headset:
type: boolean
description: The Mic Jack represents state of the headset microphone pin
additionalProperties: true
......@@ -44,6 +44,16 @@ properties:
minItems: 1
maxItems: 3
interconnects:
items:
- description: APE read memory client
- description: APE write memory client
interconnect-names:
items:
- const: dma-mem # read
- const: write
iommus:
maxItems: 1
......
NVIDIA Tegra audio complex, with MAX98090 CODEC
Required properties:
- compatible : "nvidia,tegra-audio-max98090"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the MAX98090's pins (as documented in its binding), and the jacks
on the board:
* Headphones
* Speakers
* Mic Jack
* Int Mic
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
connected to the CODEC.
- nvidia,audio-codec : The phandle of the MAX98090 audio codec.
Optional properties:
- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
- nvidia,mic-det-gpios : The GPIO that detect microphones are plugged in
Example:
sound {
compatible = "nvidia,tegra-audio-max98090-venice2",
"nvidia,tegra-audio-max98090";
nvidia,model = "NVIDIA Tegra Venice2";
nvidia,audio-routing =
"Headphones", "HPR",
"Headphones", "HPL",
"Speakers", "SPKR",
"Speakers", "SPKL",
"Mic Jack", "MICBIAS",
"IN34", "Mic Jack";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&acodec>;
clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
<&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA124_CLK_EXTERN1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-max98090.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra audio complex with MAX98090 CODEC
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Thierry Reding <thierry.reding@gmail.com>
allOf:
- $ref: nvidia,tegra-audio-common.yaml#
properties:
compatible:
oneOf:
- items:
- pattern: '^[a-z0-9]+,tegra-audio-max98090(-[a-z0-9]+)+$'
- const: nvidia,tegra-audio-max98090
- items:
- enum:
- nvidia,tegra-audio-max98090-nyan-big
- nvidia,tegra-audio-max98090-nyan-blaze
- const: nvidia,tegra-audio-max98090-nyan
- const: nvidia,tegra-audio-max98090
nvidia,audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description: |
A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the pins (documented in the binding document),
and the jacks on the board.
minItems: 2
items:
enum:
# Board Connectors
- "Headphones"
- "Speakers"
- "Mic Jack"
- "Int Mic"
# CODEC Pins
- MIC1
- MIC2
- DMICL
- DMICR
- IN1
- IN2
- IN3
- IN4
- IN5
- IN6
- IN12
- IN34
- IN56
- HPL
- HPR
- SPKL
- SPKR
- RCVL
- RCVR
- MICBIAS
required:
- nvidia,i2s-controller
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/tegra124-car.h>
sound {
compatible = "nvidia,tegra-audio-max98090-venice2",
"nvidia,tegra-audio-max98090";
nvidia,model = "NVIDIA Tegra Venice2";
nvidia,audio-routing =
"Headphones", "HPR",
"Headphones", "HPL",
"Speakers", "SPKR",
"Speakers", "SPKL",
"Mic Jack", "MICBIAS",
"IN34", "Mic Jack";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&acodec>;
clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
<&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA124_CLK_EXTERN1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
NVIDIA Tegra audio complex, with RT5640 CODEC
Required properties:
- compatible : "nvidia,tegra-audio-rt5640"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the RT5640's pins (as documented in its binding), and the jacks
on the board:
* Headphones
* Speakers
* Mic Jack
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
connected to the CODEC.
- nvidia,audio-codec : The phandle of the RT5640 audio codec. This binding
assumes that AIF1 on the CODEC is connected to Tegra.
Optional properties:
- nvidia,hp-det-gpios : The GPIO that detects headphones are plugged in
Example:
sound {
compatible = "nvidia,tegra-audio-rt5640-dalmore",
"nvidia,tegra-audio-rt5640";
nvidia,model = "NVIDIA Tegra Dalmore";
nvidia,audio-routing =
"Headphones", "HPOR",
"Headphones", "HPOL",
"Speakers", "SPORP",
"Speakers", "SPORN",
"Speakers", "SPOLP",
"Speakers", "SPOLN";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&rt5640>;
nvidia,hp-det-gpios = <&gpio 143 0>; /* GPIO PR7 */
clocks = <&tegra_car 216>, <&tegra_car 217>, <&tegra_car 120>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-rt5640.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra audio complex with RT5639 or RT5640 CODEC
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Thierry Reding <thierry.reding@gmail.com>
allOf:
- $ref: nvidia,tegra-audio-common.yaml#
properties:
compatible:
items:
- pattern: '^[a-z0-9]+,tegra-audio-rt56(39|40)(-[a-z0-9]+)+$'
- const: nvidia,tegra-audio-rt5640
nvidia,audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description: |
A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the pins (documented in the binding document),
and the jacks on the board.
minItems: 2
items:
enum:
# Board Connectors
- "Headphones"
- "Speakers"
- "Mic Jack"
# CODEC Pins
- DMIC1
- DMIC2
- MICBIAS1
- IN1P
- IN1R
- IN2P
- IN2R
- HPOL
- HPOR
- LOUTL
- LOUTR
- MONOP
- MONON
- SPOLP
- SPOLN
- SPORP
- SPORN
required:
- nvidia,i2s-controller
unevaluatedProperties: false
examples:
- |
sound {
compatible = "nvidia,tegra-audio-rt5640-dalmore",
"nvidia,tegra-audio-rt5640";
nvidia,model = "NVIDIA Tegra Dalmore";
nvidia,audio-routing =
"Headphones", "HPOR",
"Headphones", "HPOL",
"Speakers", "SPORP",
"Speakers", "SPORN",
"Speakers", "SPOLP",
"Speakers", "SPOLN";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&rt5640>;
nvidia,hp-det-gpios = <&gpio 143 0>;
clocks = <&clk 216>, <&clk 217>, <&clk 120>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
NVIDIA Tegra audio complex, with RT5677 CODEC
Required properties:
- compatible : "nvidia,tegra-audio-rt5677"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the RT5677's pins (as documented in its binding), and the jacks
on the board:
* Headphone
* Speaker
* Headset Mic
* Internal Mic 1
* Internal Mic 2
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
connected to the CODEC.
- nvidia,audio-codec : The phandle of the RT5677 audio codec. This binding
assumes that AIF1 on the CODEC is connected to Tegra.
Optional properties:
- nvidia,hp-det-gpios : The GPIO that detects headphones are plugged in
- nvidia,hp-en-gpios : The GPIO that enables headphone amplifier
- nvidia,mic-present-gpios: The GPIO that mic jack is plugged in
- nvidia,dmic-clk-en-gpios : The GPIO that gates DMIC clock signal
Example:
sound {
compatible = "nvidia,tegra-audio-rt5677-ryu",
"nvidia,tegra-audio-rt5677";
nvidia,model = "NVIDIA Tegra Ryu";
nvidia,audio-routing =
"Headphone", "LOUT2",
"Headphone", "LOUT1",
"Headset Mic", "MICBIAS1",
"IN1P", "Headset Mic",
"IN1N", "Headset Mic",
"DMIC L1", "Internal Mic 1",
"DMIC R1", "Internal Mic 1",
"DMIC L2", "Internal Mic 2",
"DMIC R2", "Internal Mic 2",
"Speaker", "PDM1L",
"Speaker", "PDM1R";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&rt5677>;
nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_HIGH>;
nvidia,mic-present-gpios = <&gpio TEGRA_GPIO(O, 5) GPIO_ACTIVE_LOW>;
nvidia,hp-en-gpios = <&rt5677 1 GPIO_ACTIVE_HIGH>;
nvidia,dmic-clk-en-gpios = <&rt5677 2 GPIO_ACTIVE_HIGH>;
clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
<&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA124_CLK_EXTERN1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-rt5677.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra audio complex with RT5677 CODEC
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Thierry Reding <thierry.reding@gmail.com>
allOf:
- $ref: nvidia,tegra-audio-common.yaml#
properties:
compatible:
items:
- pattern: '^[a-z0-9]+,tegra-audio-rt5677(-[a-z0-9]+)+$'
- const: nvidia,tegra-audio-rt5677
nvidia,audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description: |
A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the pins (documented in the binding document),
and the jacks on the board.
minItems: 2
items:
enum:
# Board Connectors
- "Headphone"
- "Speaker"
- "Headset Mic"
- "Internal Mic 1"
- "Internal Mic 2"
# CODEC Pins
- IN1P
- IN1N
- IN2P
- IN2N
- MICBIAS1
- DMIC1
- DMIC2
- DMIC3
- DMIC4
- "DMIC L1"
- "DMIC L2"
- "DMIC L3"
- "DMIC L4"
- "DMIC R1"
- "DMIC R2"
- "DMIC R3"
- "DMIC R4"
- LOUT1
- LOUT2
- LOUT3
- PDM1L
- PDM1R
- PDM2L
- PDM2R
required:
- nvidia,i2s-controller
unevaluatedProperties: false
examples:
- |
sound {
compatible = "nvidia,tegra-audio-rt5677-ryu",
"nvidia,tegra-audio-rt5677";
nvidia,model = "NVIDIA Tegra Ryu";
nvidia,audio-routing =
"Headphone", "LOUT2",
"Headphone", "LOUT1",
"Headset Mic", "MICBIAS1",
"IN1P", "Headset Mic",
"IN1N", "Headset Mic",
"DMIC L1", "Internal Mic 1",
"DMIC R1", "Internal Mic 1",
"DMIC L2", "Internal Mic 2",
"DMIC R2", "Internal Mic 2",
"Speaker", "PDM1L",
"Speaker", "PDM1R";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&rt5677>;
nvidia,hp-det-gpios = <&gpio 143 0>;
clocks = <&clk 216>,
<&clk 217>,
<&clk 121>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
NVIDIA Tegra audio complex, with SGTL5000 CODEC
Required properties:
- compatible : "nvidia,tegra-audio-sgtl5000"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the SGTL5000's pins (as documented in its binding), and the jacks
on the board:
* Headphone Jack
* Line In Jack
* Mic Jack
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
connected to the CODEC.
- nvidia,audio-codec : The phandle of the SGTL5000 audio codec.
Example:
sound {
compatible = "toradex,tegra-audio-sgtl5000-apalis_t30",
"nvidia,tegra-audio-sgtl5000";
nvidia,model = "Toradex Apalis T30";
nvidia,audio-routing =
"Headphone Jack", "HP_OUT",
"LINE_IN", "Line In Jack",
"MIC_IN", "Mic Jack";
nvidia,i2s-controller = <&tegra_i2s2>;
nvidia,audio-codec = <&sgtl5000>;
clocks = <&tegra_car TEGRA30_CLK_PLL_A>,
<&tegra_car TEGRA30_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA30_CLK_EXTERN1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-sgtl5000.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra audio complex with SGTL5000 CODEC
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Thierry Reding <thierry.reding@gmail.com>
allOf:
- $ref: nvidia,tegra-audio-common.yaml#
properties:
compatible:
items:
- pattern: '^[a-z0-9]+,tegra-audio-sgtl5000([-_][a-z0-9]+)+$'
- const: nvidia,tegra-audio-sgtl5000
nvidia,audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description: |
A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the pins (documented in the binding document),
and the jacks on the board.
minItems: 2
items:
enum:
# Board Connectors
- "Headphone Jack"
- "Line In Jack"
- "Mic Jack"
# CODEC Pins
- HP_OUT
- LINE_OUT
- LINE_IN
- MIC_IN
required:
- nvidia,i2s-controller
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/tegra30-car.h>
sound {
compatible = "toradex,tegra-audio-sgtl5000-apalis_t30",
"nvidia,tegra-audio-sgtl5000";
nvidia,model = "Toradex Apalis T30 SGTL5000";
nvidia,audio-routing =
"Headphone Jack", "HP_OUT",
"LINE_IN", "Line In Jack",
"MIC_IN", "Mic Jack";
nvidia,i2s-controller = <&tegra_i2s2>;
nvidia,audio-codec = <&codec>;
clocks = <&tegra_car TEGRA30_CLK_PLL_A>,
<&tegra_car TEGRA30_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA30_CLK_EXTERN1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
NVIDIA Tegra audio complex for TrimSlice
Required properties:
- compatible : "nvidia,tegra-audio-trimslice"
- clocks : Must contain an entry for each entry in clock-names.
- clock-names : Must include the following entries:
"pll_a" (The Tegra clock of that name),
"pll_a_out0" (The Tegra clock of that name),
"mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
- nvidia,audio-codec : The phandle of the WM8903 audio codec
Example:
sound {
compatible = "nvidia,tegra-audio-trimslice";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&codec>;
clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-trimslice.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra audio complex with TrimSlice CODEC
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Thierry Reding <thierry.reding@gmail.com>
allOf:
- $ref: nvidia,tegra-audio-common.yaml#
properties:
compatible:
const: nvidia,tegra-audio-trimslice
required:
- nvidia,i2s-controller
unevaluatedProperties: false
examples:
- |
sound {
compatible = "nvidia,tegra-audio-trimslice";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&codec>;
clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
NVIDIA Tegra audio complex
Required properties:
- compatible : "nvidia,tegra-audio-wm8753"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the WM8753's pins as documented in the binding for the WM8753,
and the jacks on the board:
* Headphone Jack
* Mic Jack
- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
- nvidia,audio-codec : The phandle of the WM8753 audio codec
Example:
sound {
compatible = "nvidia,tegra-audio-wm8753-whistler",
"nvidia,tegra-audio-wm8753"
nvidia,model = "tegra-wm8753-harmony";
nvidia,audio-routing =
"Headphone Jack", "LOUT1",
"Headphone Jack", "ROUT1";
nvidia,i2s-controller = <&i2s1>;
nvidia,audio-codec = <&wm8753>;
clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-wm8753.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra audio complex with WM8753 CODEC
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Thierry Reding <thierry.reding@gmail.com>
allOf:
- $ref: nvidia,tegra-audio-common.yaml#
properties:
compatible:
items:
- pattern: '^[a-z0-9]+,tegra-audio-wm8753(-[a-z0-9]+)+$'
- const: nvidia,tegra-audio-wm8753
nvidia,audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description: |
A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the pins (documented in the binding document),
and the jacks on the board.
minItems: 2
items:
enum:
# Board Connectors
- "Headphone Jack"
- "Mic Jack"
# CODEC Pins
- LOUT1
- LOUT2
- ROUT1
- ROUT2
- MONO1
- MONO2
- OUT3
- OUT4
- LINE1
- LINE2
- RXP
- RXN
- ACIN
- ACOP
- MIC1N
- MIC1
- MIC2N
- MIC2
- "Mic Bias"
required:
- nvidia,i2s-controller
unevaluatedProperties: false
examples:
- |
sound {
compatible = "nvidia,tegra-audio-wm8753-whistler",
"nvidia,tegra-audio-wm8753";
nvidia,model = "tegra-wm8753-harmony";
nvidia,audio-routing =
"Headphone Jack", "LOUT1",
"Headphone Jack", "ROUT1";
nvidia,i2s-controller = <&i2s1>;
nvidia,audio-codec = <&wm8753>;
clocks = <&clk 112>, <&clk 113>, <&clk 93>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
NVIDIA Tegra audio complex
Required properties:
- compatible : "nvidia,tegra-audio-wm8903"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the WM8903's pins (documented in the WM8903 binding document),
and the jacks on the board:
* Headphone Jack
* Int Spk
* Mic Jack
* Int Mic
- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
- nvidia,audio-codec : The phandle of the WM8903 audio codec
Optional properties:
- nvidia,spkr-en-gpios : The GPIO that enables the speakers
- nvidia,hp-mute-gpios : The GPIO that mutes the headphones
- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
- nvidia,int-mic-en-gpios : The GPIO that enables the internal microphone
- nvidia,ext-mic-en-gpios : The GPIO that enables the external microphone
- nvidia,headset : The Mic Jack represents state of the headset microphone pin
Example:
sound {
compatible = "nvidia,tegra-audio-wm8903-harmony",
"nvidia,tegra-audio-wm8903"
nvidia,model = "tegra-wm8903-harmony";
nvidia,audio-routing =
"Headphone Jack", "HPOUTR",
"Headphone Jack", "HPOUTL",
"Int Spk", "ROP",
"Int Spk", "RON",
"Int Spk", "LOP",
"Int Spk", "LON",
"Mic Jack", "MICBIAS",
"IN1L", "Mic Jack";
nvidia,i2s-controller = <&i2s1>;
nvidia,audio-codec = <&wm8903>;
nvidia,spkr-en-gpios = <&codec 2 0>;
nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-wm8903.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra audio complex with WM8903 CODEC
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Thierry Reding <thierry.reding@gmail.com>
allOf:
- $ref: nvidia,tegra-audio-common.yaml#
properties:
compatible:
oneOf:
- items:
- pattern: '^[a-z0-9]+,tegra-audio-wm8903(-[a-z0-9]+)+$'
- const: nvidia,tegra-audio-wm8903
- items:
- pattern: ad,tegra-audio-plutux
- const: nvidia,tegra-audio-wm8903
nvidia,audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description: |
A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the pins (documented in the binding document),
and the jacks on the board.
minItems: 2
items:
enum:
# Board Connectors
- "Headphone Jack"
- "Int Spk"
- "Mic Jack"
- "Int Mic"
# CODEC Pins
- IN1L
- IN1R
- IN2L
- IN2R
- IN3L
- IN3R
- DMICDAT
- HPOUTL
- HPOUTR
- LINEOUTL
- LINEOUTR
- LOP
- LON
- ROP
- RON
- MICBIAS
required:
- nvidia,i2s-controller
unevaluatedProperties: false
examples:
- |
sound {
compatible = "nvidia,tegra-audio-wm8903-harmony",
"nvidia,tegra-audio-wm8903";
nvidia,model = "tegra-wm8903-harmony";
nvidia,audio-routing =
"Headphone Jack", "HPOUTR",
"Headphone Jack", "HPOUTL",
"Int Spk", "ROP",
"Int Spk", "RON",
"Int Spk", "LOP",
"Int Spk", "LON",
"Mic Jack", "MICBIAS",
"IN1L", "Mic Jack";
nvidia,i2s-controller = <&i2s1>;
nvidia,audio-codec = <&wm8903>;
nvidia,spkr-en-gpios = <&codec 2 0>;
nvidia,hp-det-gpios = <&gpio 178 0>;
nvidia,int-mic-en-gpios = <&gpio 184 0>;
nvidia,ext-mic-en-gpios = <&gpio 185 0>;
clocks = <&clk 112>, <&clk 113>, <&clk 93>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
NVIDIA Tegra audio complex
Required properties:
- compatible : "nvidia,tegra-audio-wm9712"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the WM9712's pins, and the jacks on the board:
WM9712 pins:
* MONOOUT
* HPOUTL
* HPOUTR
* LOUT2
* ROUT2
* OUT3
* LINEINL
* LINEINR
* PHONE
* PCBEEP
* MIC1
* MIC2
* Mic Bias
Board connectors:
* Headphone
* LineIn
* Mic
- nvidia,ac97-controller : The phandle of the Tegra AC97 controller
Example:
sound {
compatible = "nvidia,tegra-audio-wm9712-colibri_t20",
"nvidia,tegra-audio-wm9712";
nvidia,model = "Toradex Colibri T20";
nvidia,audio-routing =
"Headphone", "HPOUTL",
"Headphone", "HPOUTR",
"LineIn", "LINEINL",
"LineIn", "LINEINR",
"Mic", "MIC1";
nvidia,ac97-controller = <&ac97>;
clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-wm9712.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra audio complex with WM9712 CODEC
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Thierry Reding <thierry.reding@gmail.com>
allOf:
- $ref: nvidia,tegra-audio-common.yaml#
properties:
compatible:
items:
- pattern: '^[a-z0-9]+,tegra-audio-wm9712([-_][a-z0-9]+)+$'
- const: nvidia,tegra-audio-wm9712
nvidia,audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description: |
A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the pins (documented in the binding document),
and the jacks on the board.
minItems: 2
items:
enum:
# Board Connectors
- "Headphone"
- "LineIn"
- "Mic"
# CODEC Pins
- MONOOUT
- HPOUTL
- HPOUTR
- LOUT2
- ROUT2
- OUT3
- LINEINL
- LINEINR
- PHONE
- PCBEEP
- MIC1
- MIC2
- "Mic Bias"
required:
- nvidia,ac97-controller
unevaluatedProperties: false
examples:
- |
sound {
compatible = "nvidia,tegra-audio-wm9712-colibri_t20",
"nvidia,tegra-audio-wm9712";
nvidia,model = "Toradex Colibri T20";
nvidia,audio-routing =
"Headphone", "HPOUTL",
"Headphone", "HPOUTR",
"LineIn", "LINEINL",
"LineIn", "LINEINR",
"Mic", "MIC1";
nvidia,ac97-controller = <&ac97>;
clocks = <&clk 112>, <&clk 113>, <&clk 93>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
NVIDIA Tegra 20 I2S controller
Required properties:
- compatible : "nvidia,tegra20-i2s"
- reg : Should contain I2S registers location and length
- interrupts : Should contain I2S interrupt
- resets : Must contain an entry for each entry in reset-names.
See ../reset/reset.txt for details.
- reset-names : Must include the following entries:
- i2s
- dmas : Must contain an entry for each entry in clock-names.
See ../dma/dma.txt for details.
- dma-names : Must include the following entries:
- rx
- tx
- clocks : Must contain one entry, for the module clock.
See ../clocks/clock-bindings.txt for details.
Example:
i2s@70002800 {
compatible = "nvidia,tegra20-i2s";
reg = <0x70002800 0x200>;
interrupts = < 45 >;
clocks = <&tegra_car 11>;
resets = <&tegra_car 11>;
reset-names = "i2s";
dmas = <&apbdma 21>, <&apbdma 21>;
dma-names = "rx", "tx";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra20-i2s.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra20 I2S Controller
description: |
The I2S Controller streams synchronous serial audio data between system
memory and an external audio device. The controller supports the I2S Left
Justified Mode, Right Justified Mode, and DSP mode formats.
maintainers:
- Thierry Reding <treding@nvidia.com>
- Jon Hunter <jonathanh@nvidia.com>
properties:
compatible:
const: nvidia,tegra20-i2s
reg:
maxItems: 1
resets:
maxItems: 1
reset-names:
const: i2s
interrupts:
maxItems: 1
clocks:
minItems: 1
dmas:
minItems: 2
dma-names:
items:
- const: rx
- const: tx
nvidia,fixed-parent-rate:
description: |
Specifies whether board prefers parent clock to stay at a fixed rate.
This allows multiple Tegra20 audio components work simultaneously by
limiting number of supportable audio rates.
type: boolean
required:
- compatible
- reg
- resets
- reset-names
- interrupts
- clocks
- dmas
- dma-names
additionalProperties: false
examples:
- |
i2s@70002800 {
compatible = "nvidia,tegra20-i2s";
reg = <0x70002800 0x200>;
interrupts = <45>;
clocks = <&tegra_car 11>;
resets = <&tegra_car 11>;
reset-names = "i2s";
dmas = <&apbdma 21>, <&apbdma 21>;
dma-names = "rx", "tx";
};
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra20-spdif.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra20 S/PDIF Controller
description: |
The S/PDIF controller supports both input and output in serial audio
digital interface format. The input controller can digitally recover
a clock from the received stream. The S/PDIF controller is also used
to generate the embedded audio for HDMI output channel.
maintainers:
- Thierry Reding <treding@nvidia.com>
- Jon Hunter <jonathanh@nvidia.com>
properties:
compatible:
const: nvidia,tegra20-spdif
reg:
maxItems: 1
resets:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 2
clock-names:
items:
- const: out
- const: in
dmas:
minItems: 2
dma-names:
items:
- const: rx
- const: tx
"#sound-dai-cells":
const: 0
nvidia,fixed-parent-rate:
description: |
Specifies whether board prefers parent clock to stay at a fixed rate.
This allows multiple Tegra20 audio components work simultaneously by
limiting number of supportable audio rates.
type: boolean
required:
- compatible
- reg
- resets
- interrupts
- clocks
- clock-names
- dmas
- dma-names
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
spdif@70002400 {
compatible = "nvidia,tegra20-spdif";
reg = <0x70002400 0x200>;
interrupts = <77>;
clocks = <&clk 99>, <&clk 98>;
clock-names = "out", "in";
resets = <&rst 10>;
dmas = <&apbdma 3>, <&apbdma 3>;
dma-names = "rx", "tx";
#sound-dai-cells = <0>;
};
...
......@@ -24,11 +24,23 @@ properties:
'#sound-dai-cells':
const: 0
rcv-gpios:
description: optional GPIO to be asserted when receiver mode is enabled.
sound-name-prefix: true
vddd-supply:
description: regulator phandle for the VDDD power supply.
if:
not:
properties:
compatible:
const: nxp,tfa9897
then:
properties:
rcv-gpios: false
required:
- compatible
- reg
......@@ -55,3 +67,32 @@ examples:
#sound-dai-cells = <0>;
};
};
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
speaker_codec_top: audio-codec@34 {
compatible = "nxp,tfa9897";
reg = <0x34>;
vddd-supply = <&pm8916_l6>;
rcv-gpios = <&msmgpio 50 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&speaker_top_default>;
sound-name-prefix = "Speaker Top";
#sound-dai-cells = <0>;
};
speaker_codec_bottom: audio-codec@36 {
compatible = "nxp,tfa9897";
reg = <0x36>;
vddd-supply = <&pm8916_l6>;
rcv-gpios = <&msmgpio 111 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&speaker_bottom_default>;
sound-name-prefix = "Speaker Bottom";
#sound-dai-cells = <0>;
};
};
* Qualcomm Technologies APQ8016 SBC ASoC machine driver
This node models the Qualcomm Technologies APQ8016 SBC ASoC machine driver
Required properties:
- compatible : "qcom,apq8016-sbc-sndcard"
- pinctrl-N : One property must exist for each entry in
pinctrl-names. See ../pinctrl/pinctrl-bindings.txt
for details of the property values.
- pinctrl-names : Must contain a "default" entry.
- reg : Must contain an address for each entry in reg-names.
- reg-names : A list which must include the following entries:
* "mic-iomux"
* "spkr-iomux"
- qcom,model : Name of the sound card.
- qcom,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the
connection's sink, the second being the connection's
source. Valid names could be power supplies, MicBias
of msm8x16_wcd codec and the jacks on the board:
Power supplies:
* MIC BIAS External1
* MIC BIAS External2
* MIC BIAS Internal1
* MIC BIAS Internal2
Board connectors:
* Headset Mic
* Secondary Mic
* DMIC
* Ext Spk
Optional properties:
- aux-devs : A list of phandles for auxiliary devices (e.g. analog
amplifiers) that do not appear directly within the DAI
links. Should be connected to another audio component
using "qcom,audio-routing".
Dai-link subnode properties and subnodes:
Required dai-link subnodes:
- cpu : CPU sub-node
- codec : CODEC sub-node
Required CPU/CODEC subnodes properties:
-link-name : Name of the dai link.
-sound-dai : phandle/s and port of CPU/CODEC
Example:
sound: sound {
compatible = "qcom,apq8016-sbc-sndcard";
reg = <0x07702000 0x4>, <0x07702004 0x4>;
reg-names = "mic-iomux", "spkr-iomux";
qcom,model = "DB410c";
qcom,audio-routing =
"MIC BIAS External1", "Handset Mic",
"MIC BIAS Internal2", "Headset Mic",
"MIC BIAS External1", "Secondary Mic",
"AMIC1", "MIC BIAS External1",
"AMIC2", "MIC BIAS Internal2",
"AMIC3", "MIC BIAS External1",
"DMIC1", "MIC BIAS Internal1",
"MIC BIAS Internal1", "Digital Mic1",
"DMIC2", "MIC BIAS Internal1",
"MIC BIAS Internal1", "Digital Mic2";
/* I2S - Internal codec */
internal-dai-link@0 {
cpu { /* PRIMARY */
sound-dai = <&lpass MI2S_PRIMARY>;
};
codec {
sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
};
};
/* External Primary or External Secondary -ADV7533 HDMI */
external-dai-link@0 {
link-name = "ADV7533";
cpu { /* QUAT */
sound-dai = <&lpass MI2S_QUATERNARY>;
};
codec {
sound-dai = <&adv_bridge 0>;
};
};
};
......@@ -4,18 +4,20 @@
$id: http://devicetree.org/schemas/sound/qcom,sm8250.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies Inc. SM8250 ASoC sound card driver
title: Qualcomm Technologies Inc. ASoC sound card drivers
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
description:
This bindings describes SC8250 SoC based sound cards
This bindings describes Qualcomm SoC based sound cards
which uses LPASS internal codec for audio.
properties:
compatible:
enum:
- qcom,apq8016-sbc-sndcard
- qcom,msm8916-qdsp6-sndcard
- qcom,sm8250-sndcard
- qcom,qrb5165-rb5-sndcard
......@@ -27,10 +29,28 @@ properties:
being the connection's source. Valid names could be power supplies,
MicBias of codec and the jacks on the board.
aux-devs:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: |
List of phandles pointing to auxiliary devices, such
as amplifiers, to be added to the sound card.
model:
$ref: /schemas/types.yaml#/definitions/string
description: User visible long sound card name
pin-switches:
description: List of widget names for which pin switches should be created.
$ref: /schemas/types.yaml#/definitions/string-array
widgets:
description: User specified audio sound widgets.
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
# Only valid for some compatibles (see allOf if below)
reg: true
reg-names: true
patternProperties:
".*-dai-link$":
description:
......@@ -73,6 +93,34 @@ required:
- compatible
- model
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,apq8016-sbc-sndcard
- qcom,msm8916-qdsp6-sndcard
then:
properties:
reg:
items:
- description: Microphone I/O mux register address
- description: Speaker I/O mux register address
reg-names:
items:
- const: mic-iomux
- const: spkr-iomux
required:
- compatible
- model
- reg
- reg-names
else:
properties:
reg: false
reg-names: false
additionalProperties: false
examples:
......@@ -86,10 +134,7 @@ examples:
audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT",
"SpkrRight IN", "WSA_SPK2 OUT",
"VA DMIC0", "vdd-micb",
"VA DMIC1", "vdd-micb",
"MM_DL1", "MultiMedia1 Playback",
"MM_DL2", "MultiMedia2 Playback",
"MultiMedia3 Capture", "MM_UL3";
"VA DMIC1", "vdd-micb";
mm1-dai-link {
link-name = "MultiMedia0";
......@@ -157,3 +202,98 @@ examples:
};
};
};
- |
#include <dt-bindings/sound/qcom,lpass.h>
sound@7702000 {
compatible = "qcom,apq8016-sbc-sndcard";
reg = <0x07702000 0x4>, <0x07702004 0x4>;
reg-names = "mic-iomux", "spkr-iomux";
model = "DB410c";
audio-routing =
"AMIC2", "MIC BIAS Internal2",
"AMIC3", "MIC BIAS External1";
pinctrl-0 = <&cdc_pdm_lines_act &ext_sec_tlmm_lines_act &ext_mclk_tlmm_lines_act>;
pinctrl-1 = <&cdc_pdm_lines_sus &ext_sec_tlmm_lines_sus &ext_mclk_tlmm_lines_sus>;
pinctrl-names = "default", "sleep";
quaternary-dai-link {
link-name = "ADV7533";
cpu {
sound-dai = <&lpass MI2S_QUATERNARY>;
};
codec {
sound-dai = <&adv_bridge 0>;
};
};
primary-dai-link {
link-name = "WCD";
cpu {
sound-dai = <&lpass MI2S_PRIMARY>;
};
codec {
sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
};
};
tertiary-dai-link {
link-name = "WCD-Capture";
cpu {
sound-dai = <&lpass MI2S_TERTIARY>;
};
codec {
sound-dai = <&lpass_codec 1>, <&wcd_codec 1>;
};
};
};
- |
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
sound@7702000 {
compatible = "qcom,msm8916-qdsp6-sndcard";
reg = <0x07702000 0x4>, <0x07702004 0x4>;
reg-names = "mic-iomux", "spkr-iomux";
model = "msm8916";
widgets =
"Speaker", "Speaker",
"Headphone", "Headphones";
pin-switches = "Speaker";
audio-routing =
"Speaker", "Speaker Amp OUT",
"Speaker Amp IN", "HPH_R",
"Headphones", "HPH_L",
"Headphones", "HPH_R",
"AMIC1", "MIC BIAS Internal1",
"AMIC2", "MIC BIAS Internal2",
"AMIC3", "MIC BIAS Internal3";
aux-devs = <&speaker_amp>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cdc_pdm_lines_act>;
pinctrl-1 = <&cdc_pdm_lines_sus>;
mm1-dai-link {
link-name = "MultiMedia1";
cpu {
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
};
};
primary-dai-link {
link-name = "Primary MI2S";
cpu {
sound-dai = <&q6afedai PRIMARY_MI2S_RX>;
};
platform {
sound-dai = <&q6routing>;
};
codec {
sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
};
};
};
......@@ -61,6 +61,10 @@ properties:
description: |
Set the delay time (ms) for the requirement of the particular DMIC.
realtek,amic-delay-ms:
description: |
Set the delay time (ms) for the requirement of the particular platform or AMIC.
realtek,dmic-clk-driving-high:
type: boolean
description: |
......
......@@ -9,6 +9,9 @@ title: Simple Audio Amplifier Device Tree Bindings
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
allOf:
- $ref: name-prefix.yaml#
properties:
compatible:
enum:
......@@ -22,10 +25,7 @@ properties:
description: >
power supply for the device
sound-name-prefix:
$ref: /schemas/types.yaml#/definitions/string
description: >
See ./name-prefix.txt
sound-name-prefix: true
required:
- compatible
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,tlv320adc3xxx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TLV320ADC3001/TLV320ADC3101 Stereo ADC
maintainers:
- Ricard Wanderlof <ricardw@axis.com>
description: |
Texas Instruments TLV320ADC3001 and TLV320ADC3101 Stereo ADC
https://www.ti.com/product/TLV320ADC3001
https://www.ti.com/product/TLV320ADC3101
properties:
compatible:
enum:
- ti,tlv320adc3001
- ti,tlv320adc3101
reg:
maxItems: 1
description: I2C address
'#sound-dai-cells':
const: 0
'#gpio-cells':
const: 2
gpio-controller: true
reset-gpios:
maxItems: 1
description: GPIO pin used for codec reset (RESET pin)
clocks:
maxItems: 1
description: Master clock (MCLK)
ti,dmdin-gpio1:
$ref: /schemas/types.yaml#/definitions/uint32
enum:
- 0 # ADC3XXX_GPIO_DISABLED - I/O buffers powered down and not used
- 1 # ADC3XXX_GPIO_INPUT - Various non-GPIO input functions
- 2 # ADC3XXX_GPIO_GPI - General purpose input
- 3 # ADC3XXX_GPIO_GPO - General purpose output
- 4 # ADC3XXX_GPIO_CLKOUT - Clock source set in CLKOUT_MUX reg
- 5 # ADC3XXX_GPIO_INT1 - INT1 output
- 6 # ADC3XXX_GPIO_SECONDARY_BCLK - Codec interface secondary BCLK
- 7 # ADC3XXX_GPIO_SECONDARY_WCLK - Codec interface secondary WCLK
default: 0
description: |
Configuration for DMDIN/GPIO1 pin.
When ADC3XXX_GPIO_GPO is configured, this causes corresponding the
ALSA control "GPIOx Output" to appear, as a switch control.
ti,dmclk-gpio2:
$ref: /schemas/types.yaml#/definitions/uint32
enum:
- 0 # ADC3XXX_GPIO_DISABLED - I/O buffers powered down and not used
- 1 # ADC3XXX_GPIO_INPUT - Various non-GPIO input functions
- 2 # ADC3XXX_GPIO_GPI - General purpose input
- 3 # ADC3XXX_GPIO_GPO - General purpose output
- 4 # ADC3XXX_GPIO_CLKOUT - Clock source set in CLKOUT_MUX reg
- 5 # ADC3XXX_GPIO_INT1 - INT1 output
- 6 # ADC3XXX_GPIO_SECONDARY_BCLK - Codec interface secondary BCLK
- 7 # ADC3XXX_GPIO_SECONDARY_WCLK - Codec interface secondary WCLK
default: 0
description: |
Configuration for DMCLK/GPIO2 pin.
When ADC3XXX_GPIO_GPO is configured, this causes corresponding the
ALSA control "GPIOx Output" to appear, as a switch control.
Note that there is currently no support for reading the GPIO pins as
inputs.
ti,micbias1-vg:
$ref: /schemas/types.yaml#/definitions/uint32
enum:
- 0 # ADC3XXX_MICBIAS_OFF - Mic bias is powered down
- 1 # ADC3XXX_MICBIAS_2_0V - Mic bias is set to 2.0V
- 2 # ADC3XXX_MICBIAS_2_5V - Mic bias is set to 2.5V
- 3 # ADC3XXX_MICBIAS_AVDD - Mic bias is same as AVDD supply
default: 0
description: |
Mic bias voltage output on MICBIAS1 pin
ti,micbias2-vg:
$ref: /schemas/types.yaml#/definitions/uint32
enum:
- 0 # ADC3XXX_MICBIAS_OFF - Mic bias is powered down
- 1 # ADC3XXX_MICBIAS_2_0V - Mic bias is set to 2.0V
- 2 # ADC3XXX_MICBIAS_2_5V - Mic bias is set to 2.5V
- 3 # ADC3XXX_MICBIAS_AVDD - Mic bias is same as AVDD supply
default: 0
description: |
Mic bias voltage output on MICBIAS2 pin
required:
- compatible
- reg
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/sound/tlv320adc3xxx.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
tlv320adc3101: audio-codec@18 {
compatible = "ti,tlv320adc3101";
reg = <0x18>;
reset-gpios = <&gpio_pc 3 GPIO_ACTIVE_LOW>;
clocks = <&audio_mclk>;
gpio-controller;
#gpio-cells = <2>;
ti,dmdin-gpio1 = <ADC3XXX_GPIO_GPO>;
ti,micbias1-vg = <ADC3XXX_MICBIAS_AVDD>;
};
};
audio_mclk: clock {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24576000>;
};
...
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/sound/wlf,wm8903.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: WM8903 audio codec
description: |
This device supports I2C only.
Pins on the device (for linking into audio routes):
* IN1L
* IN1R
* IN2L
* IN2R
* IN3L
* IN3R
* DMICDAT
* HPOUTL
* HPOUTR
* LINEOUTL
* LINEOUTR
* LOP
* LON
* ROP
* RON
* MICBIAS
maintainers:
- patches@opensource.cirrus.com
properties:
compatible:
const: wlf,wm8903
reg:
maxItems: 1
gpio-controller: true
'#gpio-cells':
const: 2
interrupts:
maxItems: 1
micdet-cfg:
$ref: /schemas/types.yaml#/definitions/uint32
default: 0
description: Default register value for R6 (Mic Bias).
micdet-delay:
$ref: /schemas/types.yaml#/definitions/uint32
default: 100
description: The debounce delay for microphone detection in mS.
gpio-cfg:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: |
minItems: 5
maxItems: 5
A list of GPIO configuration register values.
If absent, no configuration of these registers is performed.
If any entry has the value 0xffffffff, that GPIO's
configuration will not be modified.
AVDD-supply:
description: Analog power supply regulator on the AVDD pin.
CPVDD-supply:
description: Charge pump supply regulator on the CPVDD pin.
DBVDD-supply:
description: Digital buffer supply regulator for the DBVDD pin.
DCVDD-supply:
description: Digital core supply regulator for the DCVDD pin.
required:
- compatible
- reg
- gpio-controller
- '#gpio-cells'
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
wm8903: codec@1a {
compatible = "wlf,wm8903";
reg = <0x1a>;
interrupts = <347>;
AVDD-supply = <&fooreg_a>;
CPVDD-supply = <&fooreg_b>;
DBVDD-supply = <&fooreg_c>;
DCVDD-supply = <&fooreg_d>;
gpio-controller;
#gpio-cells = <2>;
micdet-cfg = <0>;
micdet-delay = <100>;
gpio-cfg = <
0x0600 /* DMIC_LR, output */
0x0680 /* DMIC_DAT, input */
0x0000 /* GPIO, output, low */
0x0200 /* Interrupt, output */
0x01a0 /* BCLK, input, active high */
>;
};
};
WM8903 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "wlf,wm8903"
- reg : the I2C address of the device.
- gpio-controller : Indicates this device is a GPIO controller.
- #gpio-cells : Should be two. The first cell is the pin number and the
second cell is used to specify optional parameters (currently unused).
Optional properties:
- interrupts : The interrupt line the codec is connected to.
- micdet-cfg : Default register value for R6 (Mic Bias). If absent, the
default is 0.
- micdet-delay : The debounce delay for microphone detection in mS. If
absent, the default is 100.
- gpio-cfg : A list of GPIO configuration register values. The list must
be 5 entries long. If absent, no configuration of these registers is
performed. If any entry has the value 0xffffffff, that GPIO's
configuration will not be modified.
- AVDD-supply : Analog power supply regulator on the AVDD pin.
- CPVDD-supply : Charge pump supply regulator on the CPVDD pin.
- DBVDD-supply : Digital buffer supply regulator for the DBVDD pin.
- DCVDD-supply : Digital core supply regulator for the DCVDD pin.
Pins on the device (for linking into audio routes):
* IN1L
* IN1R
* IN2L
* IN2R
* IN3L
* IN3R
* DMICDAT
* HPOUTL
* HPOUTR
* LINEOUTL
* LINEOUTR
* LOP
* LON
* ROP
* RON
* MICBIAS
Example:
wm8903: codec@1a {
compatible = "wlf,wm8903";
reg = <0x1a>;
interrupts = < 347 >;
AVDD-supply = <&fooreg_a>;
CPVDD-supply = <&fooreg_b>;
DBVDD-supply = <&fooreg_c>;
DCVDC-supply = <&fooreg_d>;
gpio-controller;
#gpio-cells = <2>;
micdet-cfg = <0>;
micdet-delay = <100>;
gpio-cfg = <
0x0600 /* DMIC_LR, output */
0x0680 /* DMIC_DAT, input */
0x0000 /* GPIO, output, low */
0x0200 /* Interrupt, output */
0x01a0 /* BCLK, input, active high */
>;
};
......@@ -4514,6 +4514,7 @@ M: David Rhodes <david.rhodes@cirrus.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
L: patches@opensource.cirrus.com
S: Maintained
F: Documentation/devicetree/bindings/sound/cirrus,cs*
F: sound/soc/codecs/cs*
CIRRUS LOGIC DSP FIRMWARE DRIVER
......
......@@ -727,12 +727,6 @@ static int mmp_pdma_config_write(struct dma_chan *dchan,
chan->dir = direction;
chan->dev_addr = addr;
/* FIXME: drivers should be ported over to use the filter
* function. Once that's done, the following two lines can
* be removed.
*/
if (cfg->slave_id)
chan->drcmr = cfg->slave_id;
return 0;
}
......
......@@ -909,13 +909,6 @@ static void pxad_get_config(struct pxad_chan *chan,
*dcmd |= PXA_DCMD_BURST16;
else if (maxburst == 32)
*dcmd |= PXA_DCMD_BURST32;
/* FIXME: drivers should be ported over to use the filter
* function. Once that's done, the following two lines can
* be removed.
*/
if (chan->cfg.slave_id)
chan->drcmr = chan->cfg.slave_id;
}
static struct dma_async_tx_descriptor *
......
......@@ -8,6 +8,7 @@
#include <linux/device.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/dma/qcom_adm.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
......@@ -140,6 +141,8 @@ struct adm_chan {
struct adm_async_desc *curr_txd;
struct dma_slave_config slave;
u32 crci;
u32 mux;
struct list_head node;
int error;
......@@ -379,8 +382,8 @@ static struct dma_async_tx_descriptor *adm_prep_slave_sg(struct dma_chan *chan,
return ERR_PTR(-EINVAL);
}
crci = achan->slave.slave_id & 0xf;
if (!crci || achan->slave.slave_id > 0x1f) {
crci = achan->crci & 0xf;
if (!crci || achan->crci > 0x1f) {
dev_err(adev->dev, "invalid crci value\n");
return ERR_PTR(-EINVAL);
}
......@@ -403,9 +406,7 @@ static struct dma_async_tx_descriptor *adm_prep_slave_sg(struct dma_chan *chan,
if (!async_desc)
return ERR_PTR(-ENOMEM);
if (crci)
async_desc->mux = achan->slave.slave_id & ADM_CRCI_MUX_SEL ?
ADM_CRCI_CTL_MUX_SEL : 0;
async_desc->mux = achan->mux ? ADM_CRCI_CTL_MUX_SEL : 0;
async_desc->crci = crci;
async_desc->blk_size = blk_size;
async_desc->dma_len = single_count * sizeof(struct adm_desc_hw_single) +
......@@ -488,10 +489,13 @@ static int adm_terminate_all(struct dma_chan *chan)
static int adm_slave_config(struct dma_chan *chan, struct dma_slave_config *cfg)
{
struct adm_chan *achan = to_adm_chan(chan);
struct qcom_adm_peripheral_config *config = cfg->peripheral_config;
unsigned long flag;
spin_lock_irqsave(&achan->vc.lock, flag);
memcpy(&achan->slave, cfg, sizeof(struct dma_slave_config));
if (cfg->peripheral_size == sizeof(config))
achan->crci = config->crci;
spin_unlock_irqrestore(&achan->vc.lock, flag);
return 0;
......@@ -694,6 +698,45 @@ static void adm_channel_init(struct adm_device *adev, struct adm_chan *achan,
achan->vc.desc_free = adm_dma_free_desc;
}
/**
* adm_dma_xlate
* @dma_spec: pointer to DMA specifier as found in the device tree
* @ofdma: pointer to DMA controller data
*
* This can use either 1-cell or 2-cell formats, the first cell
* identifies the slave device, while the optional second cell
* contains the crci value.
*
* Returns pointer to appropriate dma channel on success or NULL on error.
*/
static struct dma_chan *adm_dma_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma)
{
struct dma_device *dev = ofdma->of_dma_data;
struct dma_chan *chan, *candidate = NULL;
struct adm_chan *achan;
if (!dev || dma_spec->args_count > 2)
return NULL;
list_for_each_entry(chan, &dev->channels, device_node)
if (chan->chan_id == dma_spec->args[0]) {
candidate = chan;
break;
}
if (!candidate)
return NULL;
achan = to_adm_chan(candidate);
if (dma_spec->args_count == 2)
achan->crci = dma_spec->args[1];
else
achan->crci = 0;
return dma_get_slave_channel(candidate);
}
static int adm_dma_probe(struct platform_device *pdev)
{
struct adm_device *adev;
......@@ -838,8 +881,7 @@ static int adm_dma_probe(struct platform_device *pdev)
goto err_disable_clks;
}
ret = of_dma_controller_register(pdev->dev.of_node,
of_dma_xlate_by_chan_id,
ret = of_dma_controller_register(pdev->dev.of_node, adm_dma_xlate,
&adev->common);
if (ret)
goto err_unregister_dma;
......
......@@ -786,14 +786,6 @@ static int shdma_config(struct dma_chan *chan,
if (!config)
return -EINVAL;
/*
* overriding the slave_id through dma_slave_config is deprecated,
* but possibly some out-of-tree drivers still do it.
*/
if (WARN_ON_ONCE(config->slave_id &&
config->slave_id != schan->real_slave_id))
schan->real_slave_id = config->slave_id;
/*
* We could lock this, but you shouldn't be configuring the
* channel, while using it...
......
......@@ -795,9 +795,6 @@ static int sprd_dma_fill_desc(struct dma_chan *chan,
return dst_datawidth;
}
if (slave_cfg->slave_id)
schan->dev_id = slave_cfg->slave_id;
hw->cfg = SPRD_DMA_DONOT_WAIT_BDONE << SPRD_DMA_WAIT_BDONE_OFFSET;
/*
......
......@@ -343,12 +343,6 @@ static int tegra_dma_slave_config(struct dma_chan *dc,
}
memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig));
if (tdc->slave_id == TEGRA_APBDMA_SLAVE_ID_INVALID &&
sconfig->device_fc) {
if (sconfig->slave_id > TEGRA_APBDMA_CSR_REQ_SEL_MASK)
return -EINVAL;
tdc->slave_id = sconfig->slave_id;
}
tdc->config_init = true;
return 0;
......
......@@ -12,6 +12,7 @@
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/dma/xilinx_dpdma.h>
#include <linux/dmaengine.h>
#include <linux/dmapool.h>
#include <linux/interrupt.h>
......@@ -1273,6 +1274,7 @@ static int xilinx_dpdma_config(struct dma_chan *dchan,
struct dma_slave_config *config)
{
struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan);
struct xilinx_dpdma_peripheral_config *pconfig;
unsigned long flags;
/*
......@@ -1282,15 +1284,18 @@ static int xilinx_dpdma_config(struct dma_chan *dchan,
* fixed both on the DPDMA side and on the DP controller side.
*/
spin_lock_irqsave(&chan->lock, flags);
/*
* Abuse the slave_id to indicate that the channel is part of a video
* group.
* Use the peripheral_config to indicate that the channel is part
* of a video group. This requires matching use of the custom
* structure in each driver.
*/
if (chan->id <= ZYNQMP_DPDMA_VIDEO2)
chan->video_group = config->slave_id != 0;
pconfig = config->peripheral_config;
if (WARN_ON(pconfig && config->peripheral_size != sizeof(*pconfig)))
return -EINVAL;
spin_lock_irqsave(&chan->lock, flags);
if (chan->id <= ZYNQMP_DPDMA_VIDEO2 && pconfig)
chan->video_group = pconfig->video_group;
spin_unlock_irqrestore(&chan->lock, flags);
return 0;
......
......@@ -12,16 +12,10 @@
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <linux/firmware/cirrus/cs_dsp.h>
#include <linux/firmware/cirrus/wmfw.h>
......@@ -622,7 +616,8 @@ static void cs_dsp_halo_show_fw_status(struct cs_dsp *dsp)
offs[0], offs[1], offs[2], offs[3]);
}
static int cs_dsp_coeff_base_reg(struct cs_dsp_coeff_ctl *ctl, unsigned int *reg)
static int cs_dsp_coeff_base_reg(struct cs_dsp_coeff_ctl *ctl, unsigned int *reg,
unsigned int off)
{
const struct cs_dsp_alg_region *alg_region = &ctl->alg_region;
struct cs_dsp *dsp = ctl->dsp;
......@@ -635,7 +630,7 @@ static int cs_dsp_coeff_base_reg(struct cs_dsp_coeff_ctl *ctl, unsigned int *reg
return -EINVAL;
}
*reg = dsp->ops->region_to_reg(mem, ctl->alg_region.base + ctl->offset);
*reg = dsp->ops->region_to_reg(mem, ctl->alg_region.base + ctl->offset + off);
return 0;
}
......@@ -659,10 +654,12 @@ int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int
unsigned int reg;
int i, ret;
lockdep_assert_held(&dsp->pwr_lock);
if (!dsp->running)
return -EPERM;
ret = cs_dsp_coeff_base_reg(ctl, &reg);
ret = cs_dsp_coeff_base_reg(ctl, &reg, 0);
if (ret)
return ret;
......@@ -716,14 +713,14 @@ int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int
EXPORT_SYMBOL_GPL(cs_dsp_coeff_write_acked_control);
static int cs_dsp_coeff_write_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
const void *buf, size_t len)
unsigned int off, const void *buf, size_t len)
{
struct cs_dsp *dsp = ctl->dsp;
void *scratch;
int ret;
unsigned int reg;
ret = cs_dsp_coeff_base_reg(ctl, &reg);
ret = cs_dsp_coeff_base_reg(ctl, &reg, off);
if (ret)
return ret;
......@@ -749,38 +746,49 @@ static int cs_dsp_coeff_write_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
/**
* cs_dsp_coeff_write_ctrl() - Writes the given buffer to the given coefficient control
* @ctl: pointer to coefficient control
* @off: word offset at which data should be written
* @buf: the buffer to write to the given control
* @len: the length of the buffer
* @len: the length of the buffer in bytes
*
* Must be called with pwr_lock held.
*
* Return: Zero for success, a negative number on error.
*/
int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, const void *buf, size_t len)
int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl,
unsigned int off, const void *buf, size_t len)
{
int ret = 0;
if (!ctl)
return -ENOENT;
lockdep_assert_held(&ctl->dsp->pwr_lock);
if (len + off * sizeof(u32) > ctl->len)
return -EINVAL;
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
ret = -EPERM;
else if (buf != ctl->cache)
memcpy(ctl->cache, buf, len);
memcpy(ctl->cache + off * sizeof(u32), buf, len);
ctl->set = 1;
if (ctl->enabled && ctl->dsp->running)
ret = cs_dsp_coeff_write_ctrl_raw(ctl, buf, len);
ret = cs_dsp_coeff_write_ctrl_raw(ctl, off, buf, len);
return ret;
}
EXPORT_SYMBOL_GPL(cs_dsp_coeff_write_ctrl);
static int cs_dsp_coeff_read_ctrl_raw(struct cs_dsp_coeff_ctl *ctl, void *buf, size_t len)
static int cs_dsp_coeff_read_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
unsigned int off, void *buf, size_t len)
{
struct cs_dsp *dsp = ctl->dsp;
void *scratch;
int ret;
unsigned int reg;
ret = cs_dsp_coeff_base_reg(ctl, &reg);
ret = cs_dsp_coeff_base_reg(ctl, &reg, off);
if (ret)
return ret;
......@@ -806,28 +814,38 @@ static int cs_dsp_coeff_read_ctrl_raw(struct cs_dsp_coeff_ctl *ctl, void *buf, s
/**
* cs_dsp_coeff_read_ctrl() - Reads the given coefficient control into the given buffer
* @ctl: pointer to coefficient control
* @off: word offset at which data should be read
* @buf: the buffer to store to the given control
* @len: the length of the buffer
* @len: the length of the buffer in bytes
*
* Must be called with pwr_lock held.
*
* Return: Zero for success, a negative number on error.
*/
int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, void *buf, size_t len)
int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl,
unsigned int off, void *buf, size_t len)
{
int ret = 0;
if (!ctl)
return -ENOENT;
lockdep_assert_held(&ctl->dsp->pwr_lock);
if (len + off * sizeof(u32) > ctl->len)
return -EINVAL;
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
if (ctl->enabled && ctl->dsp->running)
return cs_dsp_coeff_read_ctrl_raw(ctl, buf, len);
return cs_dsp_coeff_read_ctrl_raw(ctl, off, buf, len);
else
return -EPERM;
} else {
if (!ctl->flags && ctl->enabled && ctl->dsp->running)
ret = cs_dsp_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
ret = cs_dsp_coeff_read_ctrl_raw(ctl, 0, ctl->cache, ctl->len);
if (buf != ctl->cache)
memcpy(buf, ctl->cache, len);
memcpy(buf, ctl->cache + off * sizeof(u32), len);
}
return ret;
......@@ -851,7 +869,7 @@ static int cs_dsp_coeff_init_control_caches(struct cs_dsp *dsp)
* created so we don't need to do anything.
*/
if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) {
ret = cs_dsp_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
ret = cs_dsp_coeff_read_ctrl_raw(ctl, 0, ctl->cache, ctl->len);
if (ret < 0)
return ret;
}
......@@ -869,7 +887,7 @@ static int cs_dsp_coeff_sync_controls(struct cs_dsp *dsp)
if (!ctl->enabled)
continue;
if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
ret = cs_dsp_coeff_write_ctrl_raw(ctl, ctl->cache,
ret = cs_dsp_coeff_write_ctrl_raw(ctl, 0, ctl->cache,
ctl->len);
if (ret < 0)
return ret;
......@@ -1159,6 +1177,7 @@ static int cs_dsp_parse_coeff(struct cs_dsp *dsp,
return -EINVAL;
break;
case WMFW_CTL_TYPE_HOSTEVENT:
case WMFW_CTL_TYPE_FWEVENT:
ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk,
WMFW_CTL_FLAG_SYS |
WMFW_CTL_FLAG_VOLATILE |
......@@ -1459,6 +1478,8 @@ struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, in
{
struct cs_dsp_coeff_ctl *pos, *rslt = NULL;
lockdep_assert_held(&dsp->pwr_lock);
list_for_each_entry(pos, &dsp->ctl_list, list) {
if (!pos->subname)
continue;
......@@ -1554,6 +1575,8 @@ struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
{
struct cs_dsp_alg_region *alg_region;
lockdep_assert_held(&dsp->pwr_lock);
list_for_each_entry(alg_region, &dsp->alg_regions, list) {
if (id == alg_region->alg && type == alg_region->type)
return alg_region;
......@@ -1565,7 +1588,7 @@ EXPORT_SYMBOL_GPL(cs_dsp_find_alg_region);
static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp,
int type, __be32 id,
__be32 base)
__be32 ver, __be32 base)
{
struct cs_dsp_alg_region *alg_region;
......@@ -1575,6 +1598,7 @@ static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp,
alg_region->type = type;
alg_region->alg = be32_to_cpu(id);
alg_region->ver = be32_to_cpu(ver);
alg_region->base = be32_to_cpu(base);
list_add_tail(&alg_region->list, &dsp->alg_regions);
......@@ -1624,14 +1648,14 @@ static void cs_dsp_parse_wmfw_v3_id_header(struct cs_dsp *dsp,
nalgs);
}
static int cs_dsp_create_regions(struct cs_dsp *dsp, __be32 id, int nregions,
const int *type, __be32 *base)
static int cs_dsp_create_regions(struct cs_dsp *dsp, __be32 id, __be32 ver,
int nregions, const int *type, __be32 *base)
{
struct cs_dsp_alg_region *alg_region;
int i;
for (i = 0; i < nregions; i++) {
alg_region = cs_dsp_create_region(dsp, type[i], id, base[i]);
alg_region = cs_dsp_create_region(dsp, type[i], id, ver, base[i]);
if (IS_ERR(alg_region))
return PTR_ERR(alg_region);
}
......@@ -1666,12 +1690,14 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp)
cs_dsp_parse_wmfw_id_header(dsp, &adsp1_id.fw, n_algs);
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_ZM,
adsp1_id.fw.id, adsp1_id.zm);
adsp1_id.fw.id, adsp1_id.fw.ver,
adsp1_id.zm);
if (IS_ERR(alg_region))
return PTR_ERR(alg_region);
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_DM,
adsp1_id.fw.id, adsp1_id.dm);
adsp1_id.fw.id, adsp1_id.fw.ver,
adsp1_id.dm);
if (IS_ERR(alg_region))
return PTR_ERR(alg_region);
......@@ -1694,6 +1720,7 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp)
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_DM,
adsp1_alg[i].alg.id,
adsp1_alg[i].alg.ver,
adsp1_alg[i].dm);
if (IS_ERR(alg_region)) {
ret = PTR_ERR(alg_region);
......@@ -1715,6 +1742,7 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp)
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_ZM,
adsp1_alg[i].alg.id,
adsp1_alg[i].alg.ver,
adsp1_alg[i].zm);
if (IS_ERR(alg_region)) {
ret = PTR_ERR(alg_region);
......@@ -1767,17 +1795,20 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
cs_dsp_parse_wmfw_id_header(dsp, &adsp2_id.fw, n_algs);
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM,
adsp2_id.fw.id, adsp2_id.xm);
adsp2_id.fw.id, adsp2_id.fw.ver,
adsp2_id.xm);
if (IS_ERR(alg_region))
return PTR_ERR(alg_region);
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_YM,
adsp2_id.fw.id, adsp2_id.ym);
adsp2_id.fw.id, adsp2_id.fw.ver,
adsp2_id.ym);
if (IS_ERR(alg_region))
return PTR_ERR(alg_region);
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_ZM,
adsp2_id.fw.id, adsp2_id.zm);
adsp2_id.fw.id, adsp2_id.fw.ver,
adsp2_id.zm);
if (IS_ERR(alg_region))
return PTR_ERR(alg_region);
......@@ -1802,6 +1833,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM,
adsp2_alg[i].alg.id,
adsp2_alg[i].alg.ver,
adsp2_alg[i].xm);
if (IS_ERR(alg_region)) {
ret = PTR_ERR(alg_region);
......@@ -1823,6 +1855,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_YM,
adsp2_alg[i].alg.id,
adsp2_alg[i].alg.ver,
adsp2_alg[i].ym);
if (IS_ERR(alg_region)) {
ret = PTR_ERR(alg_region);
......@@ -1844,6 +1877,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_ZM,
adsp2_alg[i].alg.id,
adsp2_alg[i].alg.ver,
adsp2_alg[i].zm);
if (IS_ERR(alg_region)) {
ret = PTR_ERR(alg_region);
......@@ -1869,7 +1903,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
return ret;
}
static int cs_dsp_halo_create_regions(struct cs_dsp *dsp, __be32 id,
static int cs_dsp_halo_create_regions(struct cs_dsp *dsp, __be32 id, __be32 ver,
__be32 xm_base, __be32 ym_base)
{
static const int types[] = {
......@@ -1878,7 +1912,7 @@ static int cs_dsp_halo_create_regions(struct cs_dsp *dsp, __be32 id,
};
__be32 bases[] = { xm_base, xm_base, ym_base, ym_base };
return cs_dsp_create_regions(dsp, id, ARRAY_SIZE(types), types, bases);
return cs_dsp_create_regions(dsp, id, ver, ARRAY_SIZE(types), types, bases);
}
static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp)
......@@ -1906,7 +1940,7 @@ static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp)
cs_dsp_parse_wmfw_v3_id_header(dsp, &halo_id.fw, n_algs);
ret = cs_dsp_halo_create_regions(dsp, halo_id.fw.id,
ret = cs_dsp_halo_create_regions(dsp, halo_id.fw.id, halo_id.fw.ver,
halo_id.xm_base, halo_id.ym_base);
if (ret)
return ret;
......@@ -1930,6 +1964,7 @@ static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp)
be32_to_cpu(halo_alg[i].ym_base));
ret = cs_dsp_halo_create_regions(dsp, halo_alg[i].alg.id,
halo_alg[i].alg.ver,
halo_alg[i].xm_base,
halo_alg[i].ym_base);
if (ret)
......@@ -1951,7 +1986,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
const struct cs_dsp_region *mem;
struct cs_dsp_alg_region *alg_region;
const char *region_name;
int ret, pos, blocks, type, offset, reg;
int ret, pos, blocks, type, offset, reg, version;
char *text = NULL;
struct cs_dsp_buf *buf;
if (!firmware)
......@@ -1973,6 +2009,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
switch (be32_to_cpu(hdr->rev) & 0xff) {
case 1:
case 2:
break;
default:
cs_dsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
......@@ -1995,6 +2032,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
type = le16_to_cpu(blk->type);
offset = le16_to_cpu(blk->offset);
version = le32_to_cpu(blk->ver) >> 8;
cs_dsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
file, blocks, le32_to_cpu(blk->id),
......@@ -2008,6 +2046,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
region_name = "Unknown";
switch (type) {
case (WMFW_NAME_TEXT << 8):
text = kzalloc(le32_to_cpu(blk->len) + 1, GFP_KERNEL);
break;
case (WMFW_INFO_TEXT << 8):
case (WMFW_METADATA << 8):
break;
......@@ -2052,6 +2092,16 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
alg_region = cs_dsp_find_alg_region(dsp, type,
le32_to_cpu(blk->id));
if (alg_region) {
if (version != alg_region->ver)
cs_dsp_warn(dsp,
"Algorithm coefficient version %d.%d.%d but expected %d.%d.%d\n",
(version >> 16) & 0xFF,
(version >> 8) & 0xFF,
version & 0xFF,
(alg_region->ver >> 16) & 0xFF,
(alg_region->ver >> 8) & 0xFF,
alg_region->ver & 0xFF);
reg = alg_region->base;
reg = dsp->ops->region_to_reg(mem, reg);
reg += offset;
......@@ -2067,6 +2117,13 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
break;
}
if (text) {
memcpy(text, blk->data, le32_to_cpu(blk->len));
cs_dsp_info(dsp, "%s: %s\n", dsp->fw_name, text);
kfree(text);
text = NULL;
}
if (reg) {
if (le32_to_cpu(blk->len) >
firmware->size - pos - sizeof(*blk)) {
......@@ -2117,6 +2174,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
out_fw:
regmap_async_complete(regmap);
cs_dsp_buf_free(&buf_list);
kfree(text);
return ret;
}
......@@ -2600,6 +2658,12 @@ int cs_dsp_run(struct cs_dsp *dsp)
goto err;
}
if (dsp->client_ops->pre_run) {
ret = dsp->client_ops->pre_run(dsp);
if (ret)
goto err;
}
/* Sync set controls */
ret = cs_dsp_coeff_sync_controls(dsp);
if (ret != 0)
......@@ -2789,6 +2853,8 @@ int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int me
unsigned int reg;
int ret;
lockdep_assert_held(&dsp->pwr_lock);
if (!mem)
return -EINVAL;
......@@ -2842,6 +2908,8 @@ int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_ad
__be32 val = cpu_to_be32(data & 0x00ffffffu);
unsigned int reg;
lockdep_assert_held(&dsp->pwr_lock);
if (!mem)
return -EINVAL;
......
......@@ -24,6 +24,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma/xilinx_dpdma.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/module.h>
......@@ -1058,14 +1059,18 @@ static void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt);
/*
* Set slave_id for each DMA channel to indicate they're part of a
* Set pconfig for each DMA channel to indicate they're part of a
* video group.
*/
for (i = 0; i < info->num_planes; i++) {
struct zynqmp_disp_layer_dma *dma = &layer->dmas[i];
struct xilinx_dpdma_peripheral_config pconfig = {
.video_group = true,
};
struct dma_slave_config config = {
.direction = DMA_MEM_TO_DEV,
.slave_id = 1,
.peripheral_config = &pconfig,
.peripheral_size = sizeof(pconfig),
};
dmaengine_slave_config(dma->chan, &config);
......
......@@ -1293,14 +1293,12 @@ static int bcm2835_add_host(struct bcm2835_host *host)
host->dma_cfg_tx.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
host->dma_cfg_tx.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
host->dma_cfg_tx.slave_id = 13; /* DREQ channel */
host->dma_cfg_tx.direction = DMA_MEM_TO_DEV;
host->dma_cfg_tx.src_addr = 0;
host->dma_cfg_tx.dst_addr = host->phys_addr + SDDATA;
host->dma_cfg_rx.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
host->dma_cfg_rx.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
host->dma_cfg_rx.slave_id = 13; /* DREQ channel */
host->dma_cfg_rx.direction = DMA_DEV_TO_MEM;
host->dma_cfg_rx.src_addr = host->phys_addr + SDDATA;
host->dma_cfg_rx.dst_addr = 0;
......
......@@ -6,6 +6,7 @@
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/dma/qcom_adm.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/module.h>
......@@ -952,6 +953,7 @@ static int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read,
struct dma_async_tx_descriptor *dma_desc;
struct scatterlist *sgl;
struct dma_slave_config slave_conf;
struct qcom_adm_peripheral_config periph_conf = {};
enum dma_transfer_direction dir_eng;
int ret;
......@@ -983,11 +985,19 @@ static int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read,
if (read) {
slave_conf.src_maxburst = 16;
slave_conf.src_addr = nandc->base_dma + reg_off;
slave_conf.slave_id = nandc->data_crci;
if (nandc->data_crci) {
periph_conf.crci = nandc->data_crci;
slave_conf.peripheral_config = &periph_conf;
slave_conf.peripheral_size = sizeof(periph_conf);
}
} else {
slave_conf.dst_maxburst = 16;
slave_conf.dst_addr = nandc->base_dma + reg_off;
slave_conf.slave_id = nandc->cmd_crci;
if (nandc->cmd_crci) {
periph_conf.crci = nandc->cmd_crci;
slave_conf.peripheral_config = &periph_conf;
slave_conf.peripheral_size = sizeof(periph_conf);
}
}
ret = dmaengine_slave_config(nandc->chan, &slave_conf);
......
......@@ -411,12 +411,17 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
return ret;
}
static void init_clks(struct platform_device *pdev, struct clk **clk)
static int init_clks(struct platform_device *pdev, struct clk **clk)
{
int i;
for (i = CLK_NONE + 1; i < CLK_MAX; i++)
for (i = CLK_NONE + 1; i < CLK_MAX; i++) {
clk[i] = devm_clk_get(&pdev->dev, clk_names[i]);
if (IS_ERR(clk[i]))
return PTR_ERR(clk[i]);
}
return 0;
}
static struct scp *init_scp(struct platform_device *pdev,
......@@ -426,7 +431,7 @@ static struct scp *init_scp(struct platform_device *pdev,
{
struct genpd_onecell_data *pd_data;
struct resource *res;
int i, j;
int i, j, ret;
struct scp *scp;
struct clk *clk[CLK_MAX];
......@@ -481,7 +486,9 @@ static struct scp *init_scp(struct platform_device *pdev,
pd_data->num_domains = num;
init_clks(pdev, clk);
ret = init_clks(pdev, clk);
if (ret)
return ERR_PTR(ret);
for (i = 0; i < num; i++) {
struct scp_domain *scpd = &scp->domains[i];
......
......@@ -1178,9 +1178,6 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
cdns->pcm.num_bd = config.pcm_bd;
cdns->pcm.num_in = config.pcm_in;
cdns->pcm.num_out = config.pcm_out;
cdns->pdm.num_bd = config.pdm_bd;
cdns->pdm.num_in = config.pdm_in;
cdns->pdm.num_out = config.pdm_out;
/* Allocate PDIs for PCMs */
stream = &cdns->pcm;
......@@ -1211,32 +1208,6 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
stream->num_pdi = stream->num_bd + stream->num_in + stream->num_out;
cdns->num_ports = stream->num_pdi;
/* Allocate PDIs for PDMs */
stream = &cdns->pdm;
ret = cdns_allocate_pdi(cdns, &stream->bd,
stream->num_bd, offset);
if (ret)
return ret;
offset += stream->num_bd;
ret = cdns_allocate_pdi(cdns, &stream->in,
stream->num_in, offset);
if (ret)
return ret;
offset += stream->num_in;
ret = cdns_allocate_pdi(cdns, &stream->out,
stream->num_out, offset);
if (ret)
return ret;
/* Update total number of PDM PDIs */
stream->num_pdi = stream->num_bd + stream->num_in + stream->num_out;
cdns->num_ports += stream->num_pdi;
return 0;
}
EXPORT_SYMBOL(sdw_cdns_pdi_init);
......@@ -1681,7 +1652,7 @@ int sdw_cdns_probe(struct sdw_cdns *cdns)
EXPORT_SYMBOL(sdw_cdns_probe);
int cdns_set_sdw_stream(struct snd_soc_dai *dai,
void *stream, bool pcm, int direction)
void *stream, int direction)
{
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_cdns_dma_data *dma;
......@@ -1705,10 +1676,7 @@ int cdns_set_sdw_stream(struct snd_soc_dai *dai,
if (!dma)
return -ENOMEM;
if (pcm)
dma->stream_type = SDW_STREAM_PCM;
else
dma->stream_type = SDW_STREAM_PDM;
dma->stream_type = SDW_STREAM_PCM;
dma->bus = &cdns->bus;
dma->link_id = cdns->instance;
......
......@@ -17,7 +17,7 @@
* @h_ch_num: high channel for PDI
* @ch_count: total channel count for PDI
* @dir: data direction
* @type: stream type, PDM or PCM
* @type: stream type, (only PCM supported)
*/
struct sdw_cdns_pdi {
int num;
......@@ -62,17 +62,11 @@ struct sdw_cdns_streams {
* @pcm_bd: number of bidirectional PCM streams supported
* @pcm_in: number of input PCM streams supported
* @pcm_out: number of output PCM streams supported
* @pdm_bd: number of bidirectional PDM streams supported
* @pdm_in: number of input PDM streams supported
* @pdm_out: number of output PDM streams supported
*/
struct sdw_cdns_stream_config {
unsigned int pcm_bd;
unsigned int pcm_in;
unsigned int pcm_out;
unsigned int pdm_bd;
unsigned int pdm_in;
unsigned int pdm_out;
};
/**
......@@ -86,6 +80,7 @@ struct sdw_cdns_stream_config {
* @link_id: Master link id
* @hw_params: hw_params to be applied in .prepare step
* @suspended: status set when suspended, to be used in .prepare
* @paused: status set in .trigger, to be used in suspend
*/
struct sdw_cdns_dma_data {
char *name;
......@@ -96,6 +91,7 @@ struct sdw_cdns_dma_data {
int link_id;
struct snd_pcm_hw_params *hw_params;
bool suspended;
bool paused;
};
/**
......@@ -109,7 +105,6 @@ struct sdw_cdns_dma_data {
* @ports: Data ports
* @num_ports: Total number of data ports
* @pcm: PCM streams
* @pdm: PDM streams
* @registers: Cadence registers
* @link_up: Link status
* @msg_count: Messages sent on bus
......@@ -127,7 +122,6 @@ struct sdw_cdns {
int num_ports;
struct sdw_cdns_streams pcm;
struct sdw_cdns_streams pdm;
int pdi_loopback_source;
int pdi_loopback_target;
......@@ -186,7 +180,7 @@ cdns_xfer_msg_defer(struct sdw_bus *bus,
int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params);
int cdns_set_sdw_stream(struct snd_soc_dai *dai,
void *stream, bool pcm, int direction);
void *stream, int direction);
void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string,
bool initial_delay, int reset_iterations);
......
......@@ -564,7 +564,7 @@ static void intel_pdi_init(struct sdw_intel *sdw,
{
void __iomem *shim = sdw->link_res->shim;
unsigned int link_id = sdw->instance;
int pcm_cap, pdm_cap;
int pcm_cap;
/* PCM Stream Capability */
pcm_cap = intel_readw(shim, SDW_SHIM_PCMSCAP(link_id));
......@@ -575,41 +575,25 @@ static void intel_pdi_init(struct sdw_intel *sdw,
dev_dbg(sdw->cdns.dev, "PCM cap bd:%d in:%d out:%d\n",
config->pcm_bd, config->pcm_in, config->pcm_out);
/* PDM Stream Capability */
pdm_cap = intel_readw(shim, SDW_SHIM_PDMSCAP(link_id));
config->pdm_bd = FIELD_GET(SDW_SHIM_PDMSCAP_BSS, pdm_cap);
config->pdm_in = FIELD_GET(SDW_SHIM_PDMSCAP_ISS, pdm_cap);
config->pdm_out = FIELD_GET(SDW_SHIM_PDMSCAP_OSS, pdm_cap);
dev_dbg(sdw->cdns.dev, "PDM cap bd:%d in:%d out:%d\n",
config->pdm_bd, config->pdm_in, config->pdm_out);
}
static int
intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int pdi_num, bool pcm)
intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int pdi_num)
{
void __iomem *shim = sdw->link_res->shim;
unsigned int link_id = sdw->instance;
int count;
if (pcm) {
count = intel_readw(shim, SDW_SHIM_PCMSYCHC(link_id, pdi_num));
count = intel_readw(shim, SDW_SHIM_PCMSYCHC(link_id, pdi_num));
/*
* WORKAROUND: on all existing Intel controllers, pdi
* number 2 reports channel count as 1 even though it
* supports 8 channels. Performing hardcoding for pdi
* number 2.
*/
if (pdi_num == 2)
count = 7;
} else {
count = intel_readw(shim, SDW_SHIM_PDMSCAP(link_id));
count = FIELD_GET(SDW_SHIM_PDMSCAP_CPSS, count);
}
/*
* WORKAROUND: on all existing Intel controllers, pdi
* number 2 reports channel count as 1 even though it
* supports 8 channels. Performing hardcoding for pdi
* number 2.
*/
if (pdi_num == 2)
count = 7;
/* zero based values for channel count in register */
count++;
......@@ -620,12 +604,12 @@ intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int pdi_num, bool pcm)
static int intel_pdi_get_ch_update(struct sdw_intel *sdw,
struct sdw_cdns_pdi *pdi,
unsigned int num_pdi,
unsigned int *num_ch, bool pcm)
unsigned int *num_ch)
{
int i, ch_count = 0;
for (i = 0; i < num_pdi; i++) {
pdi->ch_count = intel_pdi_get_ch_cap(sdw, pdi->num, pcm);
pdi->ch_count = intel_pdi_get_ch_cap(sdw, pdi->num);
ch_count += pdi->ch_count;
pdi++;
}
......@@ -635,25 +619,23 @@ static int intel_pdi_get_ch_update(struct sdw_intel *sdw,
}
static int intel_pdi_stream_ch_update(struct sdw_intel *sdw,
struct sdw_cdns_streams *stream, bool pcm)
struct sdw_cdns_streams *stream)
{
intel_pdi_get_ch_update(sdw, stream->bd, stream->num_bd,
&stream->num_ch_bd, pcm);
&stream->num_ch_bd);
intel_pdi_get_ch_update(sdw, stream->in, stream->num_in,
&stream->num_ch_in, pcm);
&stream->num_ch_in);
intel_pdi_get_ch_update(sdw, stream->out, stream->num_out,
&stream->num_ch_out, pcm);
&stream->num_ch_out);
return 0;
}
static int intel_pdi_ch_update(struct sdw_intel *sdw)
{
/* First update PCM streams followed by PDM streams */
intel_pdi_stream_ch_update(sdw, &sdw->cdns.pcm, true);
intel_pdi_stream_ch_update(sdw, &sdw->cdns.pdm, false);
intel_pdi_stream_ch_update(sdw, &sdw->cdns.pcm);
return 0;
}
......@@ -711,7 +693,7 @@ intel_pdi_alh_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi)
}
static int intel_params_stream(struct sdw_intel *sdw,
struct snd_pcm_substream *substream,
int stream,
struct snd_soc_dai *dai,
struct snd_pcm_hw_params *hw_params,
int link_id, int alh_stream_id)
......@@ -719,7 +701,7 @@ static int intel_params_stream(struct sdw_intel *sdw,
struct sdw_intel_link_res *res = sdw->link_res;
struct sdw_intel_stream_params_data params_data;
params_data.substream = substream;
params_data.stream = stream; /* direction */
params_data.dai = dai;
params_data.hw_params = hw_params;
params_data.link_id = link_id;
......@@ -732,14 +714,14 @@ static int intel_params_stream(struct sdw_intel *sdw,
}
static int intel_free_stream(struct sdw_intel *sdw,
struct snd_pcm_substream *substream,
int stream,
struct snd_soc_dai *dai,
int link_id)
{
struct sdw_intel_link_res *res = sdw->link_res;
struct sdw_intel_stream_free_data free_data;
free_data.substream = substream;
free_data.stream = stream; /* direction */
free_data.dai = dai;
free_data.link_id = link_id;
......@@ -840,7 +822,6 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
struct sdw_port_config *pconfig;
int ch, dir;
int ret;
bool pcm = true;
dma = snd_soc_dai_get_dma_data(dai, substream);
if (!dma)
......@@ -852,13 +833,7 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
else
dir = SDW_DATA_DIR_TX;
if (dma->stream_type == SDW_STREAM_PDM)
pcm = false;
if (pcm)
pdi = sdw_cdns_alloc_pdi(cdns, &cdns->pcm, ch, dir, dai->id);
else
pdi = sdw_cdns_alloc_pdi(cdns, &cdns->pdm, ch, dir, dai->id);
pdi = sdw_cdns_alloc_pdi(cdns, &cdns->pcm, ch, dir, dai->id);
if (!pdi) {
ret = -EINVAL;
......@@ -871,12 +846,13 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
sdw_cdns_config_stream(cdns, ch, dir, pdi);
/* store pdi and hw_params, may be needed in prepare step */
dma->paused = false;
dma->suspended = false;
dma->pdi = pdi;
dma->hw_params = params;
/* Inform DSP about PDI stream number */
ret = intel_params_stream(sdw, substream, dai, params,
ret = intel_params_stream(sdw, substream->stream, dai, params,
sdw->instance,
pdi->intel_alh_id);
if (ret)
......@@ -887,12 +863,7 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
sconfig.frame_rate = params_rate(params);
sconfig.type = dma->stream_type;
if (dma->stream_type == SDW_STREAM_PDM) {
sconfig.frame_rate *= 50;
sconfig.bps = 1;
} else {
sconfig.bps = snd_pcm_format_width(params_format(params));
}
sconfig.bps = snd_pcm_format_width(params_format(params));
/* Port configuration */
pconfig = kzalloc(sizeof(*pconfig), GFP_KERNEL);
......@@ -953,7 +924,7 @@ static int intel_prepare(struct snd_pcm_substream *substream,
sdw_cdns_config_stream(cdns, ch, dir, dma->pdi);
/* Inform DSP about PDI stream number */
ret = intel_params_stream(sdw, substream, dai,
ret = intel_params_stream(sdw, substream->stream, dai,
dma->hw_params,
sdw->instance,
dma->pdi->intel_alh_id);
......@@ -987,7 +958,7 @@ intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
return ret;
}
ret = intel_free_stream(sdw, substream, dai, sdw->instance);
ret = intel_free_stream(sdw, substream->stream, dai, sdw->instance);
if (ret < 0) {
dev_err(dai->dev, "intel_free_stream: failed %d\n", ret);
return ret;
......@@ -1008,39 +979,10 @@ static void intel_shutdown(struct snd_pcm_substream *substream,
pm_runtime_put_autosuspend(cdns->dev);
}
static int intel_component_dais_suspend(struct snd_soc_component *component)
{
struct sdw_cdns_dma_data *dma;
struct snd_soc_dai *dai;
for_each_component_dais(component, dai) {
/*
* we don't have a .suspend dai_ops, and we don't have access
* to the substream, so let's mark both capture and playback
* DMA contexts as suspended
*/
dma = dai->playback_dma_data;
if (dma)
dma->suspended = true;
dma = dai->capture_dma_data;
if (dma)
dma->suspended = true;
}
return 0;
}
static int intel_pcm_set_sdw_stream(struct snd_soc_dai *dai,
void *stream, int direction)
{
return cdns_set_sdw_stream(dai, stream, true, direction);
}
static int intel_pdm_set_sdw_stream(struct snd_soc_dai *dai,
void *stream, int direction)
{
return cdns_set_sdw_stream(dai, stream, false, direction);
return cdns_set_sdw_stream(dai, stream, direction);
}
static void *intel_get_sdw_stream(struct snd_soc_dai *dai,
......@@ -1059,24 +1001,100 @@ static void *intel_get_sdw_stream(struct snd_soc_dai *dai,
return dma->stream;
}
static const struct snd_soc_dai_ops intel_pcm_dai_ops = {
.startup = intel_startup,
.hw_params = intel_hw_params,
.prepare = intel_prepare,
.hw_free = intel_hw_free,
.shutdown = intel_shutdown,
.set_sdw_stream = intel_pcm_set_sdw_stream,
.get_sdw_stream = intel_get_sdw_stream,
};
static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
{
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_intel *sdw = cdns_to_intel(cdns);
struct sdw_cdns_dma_data *dma;
int ret = 0;
static const struct snd_soc_dai_ops intel_pdm_dai_ops = {
dma = snd_soc_dai_get_dma_data(dai, substream);
if (!dma) {
dev_err(dai->dev, "failed to get dma data in %s\n",
__func__);
return -EIO;
}
switch (cmd) {
case SNDRV_PCM_TRIGGER_SUSPEND:
/*
* The .prepare callback is used to deal with xruns and resume operations.
* In the case of xruns, the DMAs and SHIM registers cannot be touched,
* but for resume operations the DMAs and SHIM registers need to be initialized.
* the .trigger callback is used to track the suspend case only.
*/
dma->suspended = true;
ret = intel_free_stream(sdw, substream->stream, dai, sdw->instance);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
dma->paused = true;
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
dma->paused = false;
break;
default:
break;
}
return ret;
}
static int intel_component_dais_suspend(struct snd_soc_component *component)
{
struct snd_soc_dai *dai;
/*
* In the corner case where a SUSPEND happens during a PAUSE, the ALSA core
* does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state.
* Since the component suspend is called last, we can trap this corner case
* and force the DAIs to release their resources.
*/
for_each_component_dais(component, dai) {
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_intel *sdw = cdns_to_intel(cdns);
struct sdw_cdns_dma_data *dma;
int stream;
int ret;
dma = dai->playback_dma_data;
stream = SNDRV_PCM_STREAM_PLAYBACK;
if (!dma) {
dma = dai->capture_dma_data;
stream = SNDRV_PCM_STREAM_CAPTURE;
}
if (!dma)
continue;
if (dma->suspended)
continue;
if (dma->paused) {
dma->suspended = true;
ret = intel_free_stream(sdw, stream, dai, sdw->instance);
if (ret < 0)
return ret;
}
}
return 0;
}
static const struct snd_soc_dai_ops intel_pcm_dai_ops = {
.startup = intel_startup,
.hw_params = intel_hw_params,
.prepare = intel_prepare,
.hw_free = intel_hw_free,
.trigger = intel_trigger,
.shutdown = intel_shutdown,
.set_sdw_stream = intel_pdm_set_sdw_stream,
.get_sdw_stream = intel_get_sdw_stream,
.set_stream = intel_pcm_set_sdw_stream,
.get_stream = intel_get_sdw_stream,
};
static const struct snd_soc_component_driver dai_component = {
......@@ -1087,7 +1105,7 @@ static const struct snd_soc_component_driver dai_component = {
static int intel_create_dai(struct sdw_cdns *cdns,
struct snd_soc_dai_driver *dais,
enum intel_pdi_type type,
u32 num, u32 off, u32 max_ch, bool pcm)
u32 num, u32 off, u32 max_ch)
{
int i;
......@@ -1116,10 +1134,7 @@ static int intel_create_dai(struct sdw_cdns *cdns,
dais[i].capture.formats = SNDRV_PCM_FMTBIT_S16_LE;
}
if (pcm)
dais[i].ops = &intel_pcm_dai_ops;
else
dais[i].ops = &intel_pdm_dai_ops;
dais[i].ops = &intel_pcm_dai_ops;
}
return 0;
......@@ -1133,7 +1148,7 @@ static int intel_register_dai(struct sdw_intel *sdw)
int num_dai, ret, off = 0;
/* DAIs are created based on total number of PDIs supported */
num_dai = cdns->pcm.num_pdi + cdns->pdm.num_pdi;
num_dai = cdns->pcm.num_pdi;
dais = devm_kcalloc(cdns->dev, num_dai, sizeof(*dais), GFP_KERNEL);
if (!dais)
......@@ -1143,39 +1158,19 @@ static int intel_register_dai(struct sdw_intel *sdw)
stream = &cdns->pcm;
ret = intel_create_dai(cdns, dais, INTEL_PDI_IN, cdns->pcm.num_in,
off, stream->num_ch_in, true);
off, stream->num_ch_in);
if (ret)
return ret;
off += cdns->pcm.num_in;
ret = intel_create_dai(cdns, dais, INTEL_PDI_OUT, cdns->pcm.num_out,
off, stream->num_ch_out, true);
off, stream->num_ch_out);
if (ret)
return ret;
off += cdns->pcm.num_out;
ret = intel_create_dai(cdns, dais, INTEL_PDI_BD, cdns->pcm.num_bd,
off, stream->num_ch_bd, true);
if (ret)
return ret;
/* Create PDM DAIs */
stream = &cdns->pdm;
off += cdns->pcm.num_bd;
ret = intel_create_dai(cdns, dais, INTEL_PDI_IN, cdns->pdm.num_in,
off, stream->num_ch_in, false);
if (ret)
return ret;
off += cdns->pdm.num_in;
ret = intel_create_dai(cdns, dais, INTEL_PDI_OUT, cdns->pdm.num_out,
off, stream->num_ch_out, false);
if (ret)
return ret;
off += cdns->pdm.num_out;
ret = intel_create_dai(cdns, dais, INTEL_PDI_BD, cdns->pdm.num_bd,
off, stream->num_ch_bd, false);
off, stream->num_ch_bd);
if (ret)
return ret;
......@@ -1549,7 +1544,7 @@ static int __maybe_unused intel_pm_prepare(struct device *dev)
struct sdw_intel *sdw = cdns_to_intel(cdns);
struct sdw_bus *bus = &cdns->bus;
u32 clock_stop_quirks;
int ret = 0;
int ret;
if (bus->prop.hw_disabled || !sdw->startup_done) {
dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n",
......
......@@ -1024,8 +1024,8 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream,
ctrl->sruntime[dai->id] = sruntime;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_sdw_stream(codec_dai, sruntime,
substream->stream);
ret = snd_soc_dai_set_stream(codec_dai, sruntime,
substream->stream);
if (ret < 0 && ret != -ENOTSUPP) {
dev_err(dai->dev, "Failed to set sdw stream on %s\n",
codec_dai->name);
......@@ -1051,8 +1051,8 @@ static const struct snd_soc_dai_ops qcom_swrm_pdm_dai_ops = {
.hw_free = qcom_swrm_hw_free,
.startup = qcom_swrm_startup,
.shutdown = qcom_swrm_shutdown,
.set_sdw_stream = qcom_swrm_set_sdw_stream,
.get_sdw_stream = qcom_swrm_get_sdw_stream,
.set_stream = qcom_swrm_set_sdw_stream,
.get_stream = qcom_swrm_get_sdw_stream,
};
static const struct snd_soc_component_driver qcom_swrm_dai_component = {
......
......@@ -1863,7 +1863,7 @@ static int set_stream(struct snd_pcm_substream *substream,
/* Set stream pointer on all DAIs */
for_each_rtd_dais(rtd, i, dai) {
ret = snd_soc_dai_set_sdw_stream(dai, sdw_stream, substream->stream);
ret = snd_soc_dai_set_stream(dai, sdw_stream, substream->stream);
if (ret < 0) {
dev_err(rtd->dev, "failed to set stream pointer on dai %s\n", dai->name);
break;
......@@ -1934,7 +1934,7 @@ void sdw_shutdown_stream(void *sdw_substream)
/* Find stream from first CPU DAI */
dai = asoc_rtd_to_cpu(rtd, 0);
sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream);
sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
if (IS_ERR(sdw_stream)) {
dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name);
......
......@@ -370,7 +370,6 @@ static int pic32_spi_dma_config(struct pic32_spi *pic32s, u32 dma_width)
cfg.src_addr_width = dma_width;
cfg.dst_addr_width = dma_width;
/* tx channel */
cfg.slave_id = pic32s->tx_irq;
cfg.direction = DMA_MEM_TO_DEV;
ret = dmaengine_slave_config(master->dma_tx, &cfg);
if (ret) {
......@@ -378,7 +377,6 @@ static int pic32_spi_dma_config(struct pic32_spi *pic32s, u32 dma_width)
return ret;
}
/* rx channel */
cfg.slave_id = pic32s->rx_irq;
cfg.direction = DMA_DEV_TO_MEM;
ret = dmaengine_slave_config(master->dma_rx, &cfg);
if (ret)
......
......@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/atomic.h>
#include <linux/dma/qcom_adm.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/module.h>
......@@ -290,6 +291,7 @@ static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base)
{
struct device *dev = msm_port->uart.dev;
struct dma_slave_config conf;
struct qcom_adm_peripheral_config periph_conf = {};
struct msm_dma *dma;
u32 crci = 0;
int ret;
......@@ -308,7 +310,11 @@ static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base)
conf.device_fc = true;
conf.dst_addr = base + UARTDM_TF;
conf.dst_maxburst = UARTDM_BURST_SIZE;
conf.slave_id = crci;
if (crci) {
conf.peripheral_config = &periph_conf;
conf.peripheral_size = sizeof(periph_conf);
periph_conf.crci = crci;
}
ret = dmaengine_slave_config(dma->chan, &conf);
if (ret)
......@@ -333,6 +339,7 @@ static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base)
{
struct device *dev = msm_port->uart.dev;
struct dma_slave_config conf;
struct qcom_adm_peripheral_config periph_conf = {};
struct msm_dma *dma;
u32 crci = 0;
int ret;
......@@ -355,7 +362,11 @@ static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base)
conf.device_fc = true;
conf.src_addr = base + UARTDM_RF;
conf.src_maxburst = UARTDM_BURST_SIZE;
conf.slave_id = crci;
if (crci) {
conf.peripheral_config = &periph_conf;
conf.peripheral_size = sizeof(periph_conf);
periph_conf.crci = crci;
}
ret = dmaengine_slave_config(dma->chan, &conf);
if (ret)
......
......@@ -16,6 +16,7 @@
#define RT5640_JD_SRC_GPIO2 4
#define RT5640_JD_SRC_GPIO3 5
#define RT5640_JD_SRC_GPIO4 6
#define RT5640_JD_SRC_HDA_HEADER 7
#define RT5640_OVCD_SF_0P5 0
#define RT5640_OVCD_SF_0P75 1
......
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Devicetree bindings definitions for tlv320adc3xxx driver.
*
* Copyright (C) 2021 Axis Communications AB
*/
#ifndef __DT_TLV320ADC3XXX_H
#define __DT_TLV320ADC3XXX_H
#define ADC3XXX_GPIO_DISABLED 0 /* I/O buffers powered down */
#define ADC3XXX_GPIO_INPUT 1 /* Various non-GPIO inputs */
#define ADC3XXX_GPIO_GPI 2 /* General purpose input */
#define ADC3XXX_GPIO_GPO 3 /* General purpose output */
#define ADC3XXX_GPIO_CLKOUT 4 /* Source set in reg. CLKOUT_MUX */
#define ADC3XXX_GPIO_INT1 5 /* INT1 output */
#define ADC3XXX_GPIO_INT2 6 /* INT2 output */
/* value 7 is reserved */
#define ADC3XXX_GPIO_SECONDARY_BCLK 8 /* Codec interface secondary BCLK */
#define ADC3XXX_GPIO_SECONDARY_WCLK 9 /* Codec interface secondary WCLK */
#define ADC3XXX_GPIO_ADC_MOD_CLK 10 /* Clock output for digital mics */
/* values 11-15 reserved */
#define ADC3XXX_MICBIAS_OFF 0 /* Micbias pin powered off */
#define ADC3XXX_MICBIAS_2_0V 1 /* Micbias pin set to 2.0V */
#define ADC3XXX_MICBIAS_2_5V 2 /* Micbias pin set to 2.5V */
#define ADC3XXX_MICBIAS_AVDD 3 /* Use AVDD voltage for micbias pin */
#endif /* __DT_TLV320ADC3XXX_H */
// SPDX-License-Identifier: GPL-2.0-only
#ifndef __LINUX_DMA_QCOM_ADM_H
#define __LINUX_DMA_QCOM_ADM_H
#include <linux/types.h>
struct qcom_adm_peripheral_config {
u32 crci;
u32 mux;
};
#endif /* __LINUX_DMA_QCOM_ADM_H */
// SPDX-License-Identifier: GPL-2.0
#ifndef __LINUX_DMA_XILINX_DPDMA_H
#define __LINUX_DMA_XILINX_DPDMA_H
#include <linux/types.h>
struct xilinx_dpdma_peripheral_config {
bool video_group;
};
#endif /* __LINUX_DMA_XILINX_DPDMA_H */
......@@ -418,9 +418,6 @@ enum dma_slave_buswidth {
* @device_fc: Flow Controller Settings. Only valid for slave channels. Fill
* with 'true' if peripheral should be flow controller. Direction will be
* selected at Runtime.
* @slave_id: Slave requester id. Only valid for slave channels. The dma
* slave peripheral will have unique id as dma requester which need to be
* pass as slave config.
* @peripheral_config: peripheral configuration for programming peripheral
* for dmaengine transfer
* @peripheral_size: peripheral configuration buffer size
......@@ -448,7 +445,6 @@ struct dma_slave_config {
u32 src_port_window_size;
u32 dst_port_window_size;
bool device_fc;
unsigned int slave_id;
void *peripheral_config;
size_t peripheral_size;
};
......
......@@ -11,6 +11,11 @@
#ifndef __CS_DSP_H
#define __CS_DSP_H
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/list.h>
#include <linux/regmap.h>
#define CS_ADSP2_REGION_0 BIT(0)
#define CS_ADSP2_REGION_1 BIT(1)
#define CS_ADSP2_REGION_2 BIT(2)
......@@ -49,12 +54,14 @@ struct cs_dsp_region {
* struct cs_dsp_alg_region - Describes a logical algorithm region in DSP address space
* @list: List node for internal use
* @alg: Algorithm id
* @ver: Expected algorithm version
* @type: Memory region type
* @base: Address of region
*/
struct cs_dsp_alg_region {
struct list_head list;
unsigned int alg;
unsigned int ver;
int type;
unsigned int base;
};
......@@ -69,8 +76,8 @@ struct cs_dsp_alg_region {
* @enabled: Flag indicating whether control is enabled
* @list: List node for internal use
* @cache: Cached value of the control
* @offset: Offset of control within alg_region
* @len: Length of the cached value
* @offset: Offset of control within alg_region in words
* @len: Length of the cached value in bytes
* @set: Flag indicating the value has been written by the user
* @flags: Bitfield of WMFW_CTL_FLAG_ control flags defined in wmfw.h
* @type: One of the WMFW_CTL_TYPE_ control types defined in wmfw.h
......@@ -180,7 +187,8 @@ struct cs_dsp {
* struct cs_dsp_client_ops - client callbacks
* @control_add: Called under the pwr_lock when a control is created
* @control_remove: Called under the pwr_lock when a control is destroyed
* @post_run: Called under the pwr_lock by cs_dsp_run()
* @pre_run: Called under the pwr_lock by cs_dsp_run() before the core is started
* @post_run: Called under the pwr_lock by cs_dsp_run() after the core is started
* @post_stop: Called under the pwr_lock by cs_dsp_stop()
* @watchdog_expired: Called when a watchdog expiry is detected
*
......@@ -190,6 +198,7 @@ struct cs_dsp {
struct cs_dsp_client_ops {
int (*control_add)(struct cs_dsp_coeff_ctl *ctl);
void (*control_remove)(struct cs_dsp_coeff_ctl *ctl);
int (*pre_run)(struct cs_dsp *dsp);
int (*post_run)(struct cs_dsp *dsp);
void (*post_stop)(struct cs_dsp *dsp);
void (*watchdog_expired)(struct cs_dsp *dsp);
......@@ -223,8 +232,10 @@ void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root);
void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp);
int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int event_id);
int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, const void *buf, size_t len);
int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, void *buf, size_t len);
int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
const void *buf, size_t len);
int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
void *buf, size_t len);
struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type,
unsigned int alg);
......
......@@ -29,6 +29,7 @@
#define WMFW_CTL_TYPE_ACKED 0x1000 /* acked control */
#define WMFW_CTL_TYPE_HOSTEVENT 0x1001 /* event control */
#define WMFW_CTL_TYPE_HOST_BUFFER 0x1002 /* host buffer pointer */
#define WMFW_CTL_TYPE_FWEVENT 0x1004 /* firmware event control */
struct wmfw_header {
char magic[4];
......
......@@ -92,7 +92,7 @@
* firmware.
*/
struct sdw_intel_stream_params_data {
struct snd_pcm_substream *substream;
int stream;
struct snd_soc_dai *dai;
struct snd_pcm_hw_params *hw_params;
int link_id;
......@@ -105,7 +105,7 @@ struct sdw_intel_stream_params_data {
* firmware.
*/
struct sdw_intel_stream_free_data {
struct snd_pcm_substream *substream;
int stream;
struct snd_soc_dai *dai;
int link_id;
};
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册