Merge tag 'sound-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound updates from Takashi Iwai:
 "The AI flood continues, which brought us a fairly busy development
  cycle again with changes spread across the subsystem, ranging from
  (lots of) core hardening to new platforms and codecs.

  Here are some highlights.

  ALSA core:
   - PCM: race fixes around channel-map controls, draining/unlink, drop
     sync-stop handling, and DMA buffer delay sync
   - Compress-offload: state and geometry validations, buffer leak fix,
     and stream/card lifetime management
   - Jack: module pinning during debugfs access, control removal race
     fix, and early injection exposure
   - Timer & sequencer: module pinning for user timers, RCU grace period
     wait on port deletion, UMP bounds fixes
   - Mark OSS sequencer emulation as deprecated
   - RawMIDI: proper disconnect handling and input work drain cleanup
   - Control: fixes for vmaster racy setups and control callback
     serialization, UAF fix on card disconnect

  ASoC core:
   - Continued framework refactoring, deployment of
     auto_selectable_formats across codecs and platform DAIs
   - Generic card cleanup: free jack GPIOs on card remove for
     simple-card and audio-graph-card variants
   - SDCA improvements: SimpleJack function type support, library
     helpers, and non-ACPI build support
   - Conversion of deprecated DMA API calls

  ASoC SOF:
   - Support for compressed audio playback on SOF IPC4 with Intel TGL+
   - AMD ACP 7.B / 7.F SoundWire and PDM controller support, ASP
     carveout firmware loading
   - Function topology support for Intel I2S machines

  ASoC platforms & codecs:
   - Qualcomm: New QAIF driver for Shikra platform, WCD9378 SDCA codec,
     Nord Ride/RRD and Motorola Edge 30 boards, LPASS macro cache
     converted to maple tree
   - New codec drivers: ESS ES9039Q2M, Nuvoton NAU83G60 amplifier,
     Senary SN624x SoundWire SDCA codec
   - MediaTek / Airoha: New Airoha AN7581 AFE and WM8960 machine
     drivers, extensive clock and error-handling cleanups across
     MediaTek SoCs
   - NVIDIA Tegra: WM8994 machine driver and CS35L45 MDSYNC support
   - Realtek: RT766/RT767, RT721_U, RT718 variants, RT712 GPIO LED
     control
   - Cirrus Logic: CS35L45 MDSYNC support, CS35L56 regmap default tests
   - TI: TAS2573 DSP support in TAS2781, TAS2783 SoundWire fixes
   - Everest Semi: ES8326 standby / HPF controls, ES8389 / ES8375 resume
     fixes
   - Removal of obsolete ST-Ericsson Ux500 MOP500 machine driver

  HD-audio:
   - ACPI controller runtime PM suspend/resume support
   - Controller shutdown and unbind race fixes for unsol events and jack
     polling
   - HDMI: High Bit Rate (HBR) audio capability enabled, ELD proc and
     converter bounds checks
   - AW88399 side codec SSID-specific firmware naming and Lenovo Legion
     R9000P enablement
   - Realtek / Conexant / Cirrus / TI quirks for numerous laptops
     (Lenovo, ASUS, HP, Acer, HONOR, Minisforum, MSI, etc.)
   - Creative CA0132 Sound BlasterX AE-5 external RGB LED strip support

  USB-audio:
   - Dedicated mixer driver for Audient EVO4
   - Native Instruments Kore controller LCD support and keymap fix
   - Pioneer DJ DDJ-SZ and Roland (OCTA-CAPTURE / QUAD-CAPTURE
     multirate, TD-11) support
   - UAC2/3 mixer unit matrix evaluation and bounds checking
   - Hardening for LINE6 and caiaq drivers against malformed packets and
     races
   - Device-specific quirks for PreSonus, TASCAM, Logitech, Mayflower,
     MOONDROP, Yamaha, etc.

  Misc:
   - Auto-cleanup conversion for snd_card_free() and devres migration
     across dozens of legacy PCI, ISA, and Sparc drivers
   - ALSA loopback (aloop) timer lifecycle fixes and new aloop selftest
   - pcmtest driver fixes and kselftest updates"

* tag 'sound-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (924 commits)
  ALSA: hda/realtek: Add mute and mic-mute LEDs for HP ENVY 16 (103c:8be5)
  selftests: ALSA: pcmtest: Compare all captured bytes in ni_capture
  ALSA: usb-audio: Use strscpy() in append_ctl_name()
  ALSA: caiaq: Use strscpy() in snd_usb_caiaq_input_init()
  ALSA: hiface: Use scnprintf() in hiface_chip_create()
  selftests/alsa: Check the aloop PCM Slave controls for a matching playback
  ALSA: aloop: Update the PCM Slave controls for a matching playback
  selftests: ALSA: pcmtest: Make room for the longest fill pattern
  selftests: ALSA: pcmtest: Check the frame count of each transfer
  ALSA: hda/realtek: Fix speakers on COLORFUL L1 Plus
  ALSA: hda/realtek: enable AW88399 on Lenovo Legion R9000P AFR10
  ALSA: line6: Handle period elapsed calls outside the locks
  ALSA: emux: Stop voices before freeing zones in all cases
  ALSA: emux: Fix UAF of soundfont zones at note-on
  ALSA: mtpav: restore negation dropped in guard() conversion
  ALSA: compress: reject restarting an ACTIVE task via origin_seqno
  ALSA: compress: add missing OPEN-state gate to SET_METADATA
  ALSA: compress: reject buffer geometry change on gapless next_track
  ALSA: compress: fix buffer leak on failed SET_PARAMS
  ALSA: hda/realtek: Enable jack detection on Minisforum AI X1
  ...
This commit is contained in:
Linus Torvalds committed 2026-10-24 19:16:20 -10:00
commit 75c1cb8178
832 files changed
+37044 -6793

No files matched your search

@@ -52,11 +52,11 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
audio-codec@3c {
compatible = "adi,adau1372";
reg = <0x3c>;
#sound-dai-cells = <0>;
clock-names = "mclk";
clocks = <&adau1372z_xtal>;
compatible = "adi,adau1372";
reg = <0x3c>;
#sound-dai-cells = <0>;
clock-names = "mclk";
clocks = <&adau1372z_xtal>;
};
};
@@ -68,20 +68,20 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
adau7118_codec: audio-codec@14 {
compatible = "adi,adau7118";
reg = <0x14>;
#sound-dai-cells = <0>;
iovdd-supply = <&supply>;
dvdd-supply = <&supply>;
adi,pdm-clk-map = <1 1 0 0>;
adi,decimation-ratio = <16>;
compatible = "adi,adau7118";
reg = <0x14>;
#sound-dai-cells = <0>;
iovdd-supply = <&supply>;
dvdd-supply = <&supply>;
adi,pdm-clk-map = <1 1 0 0>;
adi,decimation-ratio = <16>;
};
};
/* example with hw standalone mode */
adau7118_codec_hw: adau7118-codec-hw {
compatible = "adi,adau7118";
#sound-dai-cells = <0>;
iovdd-supply = <&supply>;
dvdd-supply = <&supply>;
compatible = "adi,adau7118";
#sound-dai-cells = <0>;
iovdd-supply = <&supply>;
dvdd-supply = <&supply>;
};
@@ -0,0 +1,41 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/airoha,an7581-afe.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Airoha AFE PCM controller for AN7581
maintainers:
- Christian Marangi <ansuelsmth@gmail.com>
properties:
compatible:
const: airoha,an7581-afe
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
afe@1fbe2200 {
compatible = "airoha,an7581-afe";
reg = <0x1fbe2200 0x9000>;
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
};
...
@@ -0,0 +1,71 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/airoha,an7581-wm8960.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Airoha AN7581 sound card with WM8960 codec
maintainers:
- Christian Marangi <ansuelsmth@gmail.com>
allOf:
- $ref: sound-card-common.yaml#
properties:
compatible:
const: airoha,an7581-wm8960-sound
platform:
type: object
additionalProperties: false
properties:
sound-dai:
items:
- description: The phandle of AN7581 platform.
required:
- sound-dai
codec:
type: object
additionalProperties: false
properties:
sound-dai:
items:
- description: The phandle of WM8960 i2c codec.
required:
- sound-dai
required:
- compatible
- audio-routing
- platform
- codec
unevaluatedProperties: false
examples:
- |
sound {
compatible = "airoha,an7581-wm8960-sound";
model = "an7581-wm8960";
audio-routing =
"Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
platform {
sound-dai = <&afe>;
};
codec {
sound-dai = <&wm8960>;
};
};
@@ -94,20 +94,20 @@ examples:
audio-routing = "I2S ENCODER I2S IN", "I2S FIFO Playback";
dai-link-0 {
sound-dai = <&i2s_fifo>;
sound-dai = <&i2s_fifo>;
};
dai-link-1 {
sound-dai = <&i2s_encoder>;
dai-format = "i2s";
mclk-fs = <256>;
sound-dai = <&i2s_encoder>;
dai-format = "i2s";
mclk-fs = <256>;
codec-0 {
sound-dai = <&codec0>;
};
codec-0 {
sound-dai = <&codec0>;
};
codec-1 {
sound-dai = <&codec1>;
};
codec-1 {
sound-dai = <&codec1>;
};
};
};
@@ -34,6 +34,12 @@ properties:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
powerdown-gpios:
maxItems: 1
description:
GPIO connected to the 'PDN' pin, if any. Needs to be set low to
power down the codec, hence the GPIO must be GPIO_ACTIVE_LOW.
required:
- compatible
- reg
@@ -42,6 +48,8 @@ unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
@@ -49,14 +57,16 @@ examples:
compatible = "asahi-kasei,ak4619";
reg = <0x10>;
powerdown-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
clocks = <&rcar_sound>;
clock-names = "mclk";
#sound-dai-cells = <0>;
port {
ak4619_endpoint: endpoint {
remote-endpoint = <&rsnd_endpoint>;
};
ak4619_endpoint: endpoint {
remote-endpoint = <&rsnd_endpoint>;
};
};
};
};
@@ -39,6 +39,7 @@ definitions:
allOf:
- $ref: /schemas/graph.yaml#/$defs/endpoint-base
- $ref: /schemas/sound/dai-params.yaml#
- $ref: /schemas/sound/tdm-slot.yaml#
properties:
mclk-fs:
$ref: simple-card.yaml#/definitions/mclk-fs
@@ -48,6 +49,9 @@ definitions:
bitclock-inversion:
description: dai-link uses bit clock inversion
$ref: /schemas/types.yaml#/definitions/flag
continuous-clock:
description: dai-link bit clock runs continuously rather than gated
$ref: /schemas/types.yaml#/definitions/flag
frame-master:
description: Indicates dai-link frame master.
oneOf:
@@ -82,12 +86,6 @@ definitions:
- msb
- lsb
dai-tdm-slot-num:
description: Number of slots in use.
$ref: /schemas/types.yaml#/definitions/uint32
dai-tdm-slot-width:
description: Width in bits for each slot.
$ref: /schemas/types.yaml#/definitions/uint32
dai-tdm-slot-width-map:
description: Mapping of sample widths to slot widths. For hardware
that cannot support a fixed slot width or a slot width always
@@ -53,6 +53,76 @@ properties:
maximum: 3
default: 2
cirrus,sync-lsw-txid:
description:
Transmitter ID to use for long software (LSW) data packets
on the SYNC bus.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 7
default: 0
cirrus,sync-sw-txid:
description:
Transmitter ID to use for short software (SW) data packets
on the SYNC bus.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 7
default: 0
cirrus,ldpm-group1-boost-select:
type: boolean
description:
When in a valid group 1 level dependent power management (LDPM) state
the integrated boost converter will enter the configured low power mode.
cirrus,boost-low-power-mode:
description:
Configures the integrated boost converter reaction to a low power mode
request.
0 = No reaction
1 = Force boost DCM low power mode
2 = Force boost static bypass
$ref: /schemas/types.yaml#/definitions/uint32
default: 2
enum:
- 0
- 1
- 2
cirrus,ldpm-group1-amp-select:
type: boolean
description:
When in a valid group 1 level dependent power management (LDPM) state
the amplifier will enter the configured low power mode.
cirrus,amplifier-low-power-mode:
description:
Configures the amplifier output stage reaction to a low power mode
request.
0 = Stop output switching (noise gate mode)
1 = Noise floor reduction mode
$ref: /schemas/types.yaml#/definitions/uint32
default: 1
enum:
- 0
- 1
cirrus,ldpm-group2-vmon-select:
type: boolean
description:
When in a valid group 2 level dependent power management (LDPM) state
the voltage monitor (VMON) circuit is put into a low power operational
state.
cirrus,ldpm-group2-imon-select:
type: boolean
description:
When in a valid group 2 level dependent power management (LDPM) state
the current monitor (IMON) circuit is put into a low power operational
state.
patternProperties:
"^cirrus,gpio-ctrl[1-3]$":
description:
@@ -121,6 +191,30 @@ patternProperties:
minimum: 0
maximum: 7
default: 0
"^cirrus,ldpm-group[1-2]-pcm-threshold-db$":
description:
Amplifier level dependent power management (LDPM) threshold. Input
referred threshold of the PCM audio signal in which the level is low
enough for the LDPM group to engage after entry delay. A value of dB
-2147483648 is assumed to mean true zero data with an LSB dither.
$ref: /schemas/types.yaml#/definitions/int32-array
minItems: 1
maxItems: 1
items:
enum: [-2147483648, -102, -96, -90, -84, -78, -72, -66]
"^cirrus,ldpm-group[1-2]-delay-ms$":
description:
Amplifier level dependent power management (LDPM) state entry delay.
Time that the incoming audio signal must be below the PCM threshold
before the LDPM group engages.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 1
items:
enum: [5, 10, 25, 50, 100, 250, 500, 1000]
required:
- compatible
- reg
@@ -135,25 +229,37 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
cs35l45: cs35l45@2 {
#sound-dai-cells = <1>;
compatible = "cirrus,cs35l45";
reg = <2>;
spi-max-frequency = <5000000>;
vdd-a-supply = <&dummy_vreg>;
vdd-batt-supply = <&dummy_vreg>;
reset-gpios = <&gpio 110 0>;
cirrus,asp-sdout-hiz-ctrl = <(CS35L45_ASP_TX_HIZ_UNUSED |
CS35L45_ASP_TX_HIZ_DISABLED)>;
cirrus,gpio-ctrl1 {
gpio-ctrl = <0x2>;
};
cirrus,gpio-ctrl2 {
gpio-ctrl = <0x2>;
};
cirrus,gpio-ctrl3 {
gpio-ctrl = <0x1>;
gpio-dir = <0x1>;
};
cs35l45: audio-codec@2 {
#sound-dai-cells = <1>;
compatible = "cirrus,cs35l45";
reg = <2>;
spi-max-frequency = <5000000>;
vdd-a-supply = <&dummy_vreg>;
vdd-batt-supply = <&dummy_vreg>;
reset-gpios = <&gpio 110 0>;
cirrus,asp-sdout-hiz-ctrl = <(CS35L45_ASP_TX_HIZ_UNUSED |
CS35L45_ASP_TX_HIZ_DISABLED)>;
cirrus,sync-lsw-txid = <0x1>;
cirrus,sync-sw-txid = <0x1>;
cirrus,ldpm-group1-pcm-threshold-db = <(-66)>;
cirrus,ldpm-group1-delay-ms = <500>;
cirrus,ldpm-group1-boost-select;
cirrus,boost-low-power-mode = <CS35L45_BST_LPMODE_DCM_MODE>;
cirrus,ldpm-group1-amp-select;
cirrus,amplifier-low-power-mode = <CS35L45_AMP_LPMODE_NFR_MODE>;
cirrus,ldpm-group2-pcm-threshold-db = <(-102)>;
cirrus,ldpm-group2-delay-ms = <1000>;
cirrus,ldpm-group2-vmon-select;
cirrus,ldpm-group2-imon-select;
cirrus,gpio-ctrl1 {
gpio-ctrl = <0x2>;
};
cirrus,gpio-ctrl2 {
gpio-ctrl = <0x2>;
};
cirrus,gpio-ctrl3 {
gpio-ctrl = <0x1>;
gpio-dir = <0x1>;
};
};
};
@@ -49,11 +49,11 @@ unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
codec@48 {
compatible = "cirrus,cs4270";
reg = <0x48>;
};
codec@48 {
compatible = "cirrus,cs4270";
reg = <0x48>;
};
};
@@ -199,28 +199,28 @@ examples:
- |
#include <dt-bindings/sound/cs42l42.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
#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>;
audio-codec@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>;
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>;
};
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>;
};
};
@@ -43,14 +43,14 @@ examples:
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
jack_codec: codec@4b {
compatible = "cirrus,cs42l84";
reg = <0x4b>;
reset-gpios = <&pinctrl_nub 4 GPIO_ACTIVE_LOW>;
interrupts-extended = <&pinctrl_ap 180 IRQ_TYPE_LEVEL_LOW>;
#sound-dai-cells = <0>;
};
jack_codec: codec@4b {
compatible = "cirrus,cs42l84";
reg = <0x4b>;
reset-gpios = <&pinctrl_nub 4 GPIO_ACTIVE_LOW>;
interrupts-extended = <&pinctrl_ap 180 IRQ_TYPE_LEVEL_LOW>;
#sound-dai-cells = <0>;
};
};
@@ -75,37 +75,37 @@ unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
codec@48 {
compatible = "cirrus,cs42888";
reg = <0x48>;
clocks = <&codec_mclk 0>;
clock-names = "mclk";
VA-supply = <&reg_audio>;
VD-supply = <&reg_audio>;
VLS-supply = <&reg_audio>;
VLC-supply = <&reg_audio>;
reset-gpios = <&gpio 1>;
};
codec@48 {
compatible = "cirrus,cs42888";
reg = <0x48>;
clocks = <&codec_mclk 0>;
clock-names = "mclk";
VA-supply = <&reg_audio>;
VD-supply = <&reg_audio>;
VLS-supply = <&reg_audio>;
VLC-supply = <&reg_audio>;
reset-gpios = <&gpio 1>;
};
};
spi {
#address-cells = <1>;
#size-cells = <0>;
cs-gpios = <&gpio 8 0>;
#address-cells = <1>;
#size-cells = <0>;
cs-gpios = <&gpio 8 0>;
codec@0 {
compatible = "cirrus,cs42888";
reg = <0>;
spi-max-frequency = <6000000>;
clocks = <&codec_mclk 0>;
clock-names = "mclk";
VA-supply = <&reg_audio>;
VD-supply = <&reg_audio>;
VLS-supply = <&reg_audio>;
VLC-supply = <&reg_audio>;
reset-gpios = <&gpio 1>;
};
codec@0 {
compatible = "cirrus,cs42888";
reg = <0>;
spi-max-frequency = <6000000>;
clocks = <&codec_mclk 0>;
clock-names = "mclk";
VA-supply = <&reg_audio>;
VD-supply = <&reg_audio>;
VLS-supply = <&reg_audio>;
VLC-supply = <&reg_audio>;
reset-gpios = <&gpio 1>;
};
};
@@ -1,49 +0,0 @@
* Texas Instruments SoC audio setups with TLV320AIC3X Codec
Required properties:
- compatible : "ti,da830-evm-audio" : forDM365/DA8xx/OMAPL1x/AM33xx
- ti,model : The user-visible name of this sound complex.
- ti,audio-codec : The phandle of the TLV320AIC3x audio codec
- ti,mcasp-controller : The phandle of the McASP controller
- ti,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 codec's pins, and the jacks on the board:
Optional properties:
- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec.
- clocks : Reference to the master clock
- clock-names : The clock should be named "mclk"
- Either codec-clock-rate or the codec-clock reference has to be defined. If
the both are defined the driver attempts to set referenced clock to the
defined rate and takes the rate from the clock reference.
Board connectors:
* Headphone Jack
* Line Out
* Mic Jack
* Line In
Example:
sound {
compatible = "ti,da830-evm-audio";
ti,model = "DA830 EVM";
ti,audio-codec = <&tlv320aic3x>;
ti,mcasp-controller = <&mcasp1>;
ti,codec-clock-rate = <12000000>;
ti,audio-routing =
"Headphone Jack", "HPLOUT",
"Headphone Jack", "HPROUT",
"Line Out", "LLOUT",
"Line Out", "RLOUT",
"MIC3L", "Mic Bias 2V",
"MIC3R", "Mic Bias 2V",
"Mic Bias 2V", "Mic Jack",
"LINE1L", "Line In",
"LINE2L", "Line In",
"LINE1R", "Line In",
"LINE2R", "Line In";
};
@@ -195,44 +195,44 @@ examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
codec: da7219@1a {
compatible = "dlg,da7219";
reg = <0x1a>;
codec: audio-codec@1a {
compatible = "dlg,da7219";
reg = <0x1a>;
interrupt-parent = <&gpio6>;
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
interrupt-parent = <&gpio6>;
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
VDD-supply = <&vdd_reg>;
VDDMIC-supply = <&vddmic_reg>;
VDDIO-supply = <&vddio_reg>;
VDD-supply = <&vdd_reg>;
VDDMIC-supply = <&vddmic_reg>;
VDDIO-supply = <&vddio_reg>;
#clock-cells = <1>;
clock-output-names = "da7219-dai-wclk", "da7219-dai-bclk";
#clock-cells = <1>;
clock-output-names = "da7219-dai-wclk", "da7219-dai-bclk";
clocks = <&clks 201>;
clock-names = "mclk";
clocks = <&clks 201>;
clock-names = "mclk";
dlg,micbias-lvl = <2600>;
dlg,mic-amp-in-sel = "diff";
dlg,micbias-lvl = <2600>;
dlg,mic-amp-in-sel = "diff";
da7219_aad {
dlg,btn-cfg = <50>;
dlg,mic-det-thr = <500>;
dlg,jack-ins-deb = <20>;
dlg,jack-ins-det-pty = "low";
dlg,jack-det-rate = "32_64";
dlg,jack-rem-deb = <1>;
da7219_aad {
dlg,btn-cfg = <50>;
dlg,mic-det-thr = <500>;
dlg,jack-ins-deb = <20>;
dlg,jack-ins-det-pty = "low";
dlg,jack-det-rate = "32_64";
dlg,jack-rem-deb = <1>;
dlg,a-d-btn-thr = <0xa>;
dlg,d-b-btn-thr = <0x16>;
dlg,b-c-btn-thr = <0x21>;
dlg,c-mic-btn-thr = <0x3E>;
dlg,a-d-btn-thr = <0xa>;
dlg,d-b-btn-thr = <0x16>;
dlg,b-c-btn-thr = <0x21>;
dlg,c-mic-btn-thr = <0x3E>;
dlg,btn-avg = <4>;
dlg,adc-1bit-rpt = <1>;
};
};
dlg,btn-avg = <4>;
dlg,adc-1bit-rpt = <1>;
};
};
};
@@ -0,0 +1,94 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/esstech,es9039q2m.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ESS Technology ES9039Q2M audio DAC
maintainers:
- Karl Asseily <karl@asseily.com>
description:
The ES9039Q2M is a 32-bit two-channel audio DAC supporting PCM to 768 kHz,
DSD64 to DSD1024, DoP and S/PDIF. It is controlled over I2C or SPI when the
MODE pin selects software mode; this binding covers the I2C interface. The
part contains an asynchronous sample rate converter, so the system clock need
not be synchronous with the audio bit or frame clocks.
The four supplies are all nominally 3.3V and the datasheet requires a set
order - AVDD first, then VCCA about 200us later, then AVCC_DAC1 and
AVCC_DAC2, and the reverse on the way down. DVDD, the part's 1.2V rail, is
on-chip and needs only its decoupling capacitor - it is not a supply input
and has no property here.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: esstech,es9039q2m
reg:
description:
I2C address, selected by the ADDR0 and ADDR1 pins - 0x48, 0x49, 0x4a or
0x4b for GND/GND, GND/AVDD, AVDD/GND and AVDD/AVDD respectively.
enum: [ 0x48, 0x49, 0x4a, 0x4b ]
clocks:
maxItems: 1
clock-names:
const: mclk
avdd-supply:
description:
3.3V supply for the part's internal digital regulator, pin AVDD. It is
the first rail up and the last down, per the ordering described above.
vcca-supply:
description: 3.3V analogue supply, pin VCCA.
avcc-dac1-supply:
description:
3.3V reference supply for the channel 1 analogue output stage, pin
AVCC_DAC1. The datasheet allows this rail to move by up to 15% where a
calibrating regulator tracks the DAC's output impedance.
avcc-dac2-supply:
description:
3.3V reference supply for the channel 2 analogue output stage, pin
AVCC_DAC2, with the same 15% allowance as channel 1.
"#sound-dai-cells":
const: 0
required:
- compatible
- reg
- avdd-supply
- vcca-supply
- avcc-dac1-supply
- avcc-dac2-supply
- "#sound-dai-cells"
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@48 {
compatible = "esstech,es9039q2m";
reg = <0x48>;
#sound-dai-cells = <0>;
clocks = <&dac_mclk>;
clock-names = "mclk";
avdd-supply = <&dac_3v3>;
vcca-supply = <&dac_3v3>;
avcc-dac1-supply = <&dac_avcc1>;
avcc-dac2-supply = <&dac_avcc2>;
};
};
@@ -84,6 +84,11 @@ properties:
"#sound-dai-cells":
const: 0
everest,jack-detect-inverted:
$ref: /schemas/types.yaml#/definitions/flag
description:
Defined to invert the jack detection.
required:
- compatible
- reg
@@ -63,7 +63,7 @@ properties:
a. Register initialization settings
b. DSP effect parameters
c. Multi-scene sound effect configurations(optional)
It's gernerated by FourSemi's tuning tool.
It's generated by FourSemi's tuning tool.
required:
- compatible
@@ -55,6 +55,14 @@ properties:
- const: imx/easrc/easrc-imx8mn.bin
description: The coefficient table for the filters
ports:
$ref: /schemas/graph.yaml#/properties/ports
patternProperties:
"^port@[0-3]$":
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: port for an independent conversion path
fsl,asrc-rate:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 8000
@@ -106,4 +114,41 @@ examples:
firmware-name = "imx/easrc/easrc-imx8mn.bin";
fsl,asrc-rate = <8000>;
fsl,asrc-format = <2>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
playback-only;
endpoint {
remote-endpoint = <&fe00_ep>;
};
};
port@1 {
reg = <1>;
playback-only;
endpoint {
remote-endpoint = <&fe01_ep>;
};
};
port@2 {
reg = <2>;
capture-only;
endpoint {
remote-endpoint = <&fe02_ep>;
};
};
port@3 {
reg = <3>;
capture-only;
endpoint {
remote-endpoint = <&fe03_ep>;
};
};
};
};
@@ -78,9 +78,19 @@ properties:
power-domains:
maxItems: 1
ports:
$ref: /schemas/graph.yaml#/properties/ports
patternProperties:
"^port@[0-2]$":
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: port for an independent conversion path
port:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
deprecated: true
description: deprecated, use ports instead
fsl,asrc-rate:
$ref: /schemas/types.yaml#/definitions/uint32
@@ -125,6 +135,10 @@ required:
- fsl,asrc-width
allOf:
- not:
required:
- port
- ports
- $ref: dai-common.yaml#
- if:
properties:
@@ -180,11 +194,32 @@ examples:
fsl,asrc-rate = <48000>;
fsl,asrc-width = <16>;
port {
playback-only;
ports {
#address-cells = <1>;
#size-cells = <0>;
asrc_endpoint: endpoint {
remote-endpoint = <&fe00_ep>;
port@0 {
reg = <0>;
playback-only;
endpoint {
remote-endpoint = <&fe00_ep>;
};
};
};
port@1 {
reg = <1>;
capture-only;
endpoint {
remote-endpoint = <&fe01_ep>;
};
};
port@2 {
reg = <2>;
capture-only;
endpoint {
remote-endpoint = <&fe02_ep>;
};
};
};
};
@@ -260,13 +260,13 @@ examples:
playback-only;
sai1_endpoint0: endpoint {
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
dai-tdm-slot-width-map = <32 8 32>;
dai-format = "dsp_a";
bitclock-master;
frame-master;
remote-endpoint = <&mcodec01_ep>;
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
dai-tdm-slot-width-map = <32 8 32>;
dai-format = "dsp_a";
bitclock-master;
frame-master;
remote-endpoint = <&mcodec01_ep>;
};
};
@@ -48,6 +48,10 @@ properties:
The dai cell indexes reference the following interfaces:
0: S2 interface
ports:
$ref: audio-graph-port.yaml#/definitions/ports
unevaluatedProperties: false
required:
- compatible
- reg
@@ -105,10 +105,10 @@ examples:
format = "i2s";
fsl,mclk-equal-bclk;
cpu {
sound-dai = <&sai1>;
sound-dai = <&sai1>;
};
codec {
sound-dai = <&ak4458_1>, <&ak4458_2>;
sound-dai = <&ak4458_1>, <&ak4458_2>;
};
};
fe-dai-link {
@@ -101,10 +101,10 @@ examples:
mux-ssi1 {
fsl,audmux-port = <0>;
fsl,port-config = <
IMX_AUDMUX_V2_PTCR_SYN 0
IMX_AUDMUX_V2_PTCR_TFSEL(2) 0
IMX_AUDMUX_V2_PTCR_TCSEL(2) 0
IMX_AUDMUX_V2_PTCR_TFSDIR 0
IMX_AUDMUX_V2_PTCR_SYN 0
IMX_AUDMUX_V2_PTCR_TFSEL(2) 0
IMX_AUDMUX_V2_PTCR_TCSEL(2) 0
IMX_AUDMUX_V2_PTCR_TFSDIR 0
IMX_AUDMUX_V2_PTCR_TCLKDIR IMX_AUDMUX_V2_PDCR_RXDSEL(2)
>;
};
@@ -42,10 +42,10 @@ examples:
compatible = "invensense,ics43432";
port {
endpoint {
remote-endpoint = <&i2s1_endpoint>;
dai-format = "i2s";
};
endpoint {
remote-endpoint = <&i2s1_endpoint>;
dai-format = "i2s";
};
};
};
@@ -79,7 +79,7 @@ examples:
sound-dai = <&i2s>;
};
codec {
sound-dai = <&es8323>;
sound-dai = <&es8323>;
};
};
@@ -104,6 +104,6 @@ examples:
};
codec {
sound-dai = <&es8388>;
sound-dai = <&es8388>;
};
};
@@ -32,7 +32,7 @@ properties:
maxItems: 1
clocks:
minItems: 34
minItems: 33
items:
- description: audio infra sys clock
- description: top audio mux 1
@@ -74,7 +74,7 @@ properties:
- description: audio APLL root pd
clock-names:
minItems: 34
minItems: 33
items:
- const: infra_sys_audio_clk
- const: top_audio_mux1_sel
@@ -132,8 +132,10 @@ allOf:
then:
properties:
clocks:
maxItems: 34
minItems: 33
maxItems: 33
clock-names:
maxItems: 34
minItems: 33
maxItems: 33
additionalProperties: false
@@ -84,15 +84,15 @@ examples:
<&topckgen CLK_TOP_I2S2_M_SEL>,
<&topckgen CLK_TOP_I2S3_M_SEL>,
<&topckgen CLK_TOP_I2S3_B_SEL>;
clock-names = "infra_sys_audio_clk",
"top_pdn_audio",
"top_pdn_aud_intbus",
"bck0",
"bck1",
"i2s0_m",
"i2s1_m",
"i2s2_m",
"i2s3_m",
"i2s3_b";
memory-region = <&afe_dma_mem>;
clock-names = "infra_sys_audio_clk",
"top_pdn_audio",
"top_pdn_aud_intbus",
"bck0",
"bck1",
"i2s0_m",
"i2s1_m",
"i2s2_m",
"i2s3_m",
"i2s3_b";
memory-region = <&afe_dma_mem>;
};
@@ -182,47 +182,47 @@ examples:
<&topckgen CLK_TOP_APLL12_DIV4>,
<&topckgen CLK_TOP_APLL12_DIVB>,
<&clk26m>;
clock-names = "aud_afe_clk",
"aud_dac_clk",
"aud_dac_predis_clk",
"aud_adc_clk",
"aud_adc_adda6_clk",
"aud_apll22m_clk",
"aud_apll24m_clk",
"aud_apll1_tuner_clk",
"aud_apll2_tuner_clk",
"aud_i2s1_bclk_sw",
"aud_i2s2_bclk_sw",
"aud_i2s3_bclk_sw",
"aud_i2s4_bclk_sw",
"aud_tdm_clk",
"aud_tml_clk",
"aud_infra_clk",
"mtkaif_26m_clk",
"top_mux_audio",
"top_mux_aud_intbus",
"top_syspll_d2_d4",
"top_mux_aud_1",
"top_apll1_ck",
"top_mux_aud_2",
"top_apll2_ck",
"top_mux_aud_eng1",
"top_apll1_d8",
"top_mux_aud_eng2",
"top_apll2_d8",
"top_i2s0_m_sel",
"top_i2s1_m_sel",
"top_i2s2_m_sel",
"top_i2s3_m_sel",
"top_i2s4_m_sel",
"top_i2s5_m_sel",
"top_apll12_div0",
"top_apll12_div1",
"top_apll12_div2",
"top_apll12_div3",
"top_apll12_div4",
"top_apll12_divb",
"top_clk26m_clk";
clock-names = "aud_afe_clk",
"aud_dac_clk",
"aud_dac_predis_clk",
"aud_adc_clk",
"aud_adc_adda6_clk",
"aud_apll22m_clk",
"aud_apll24m_clk",
"aud_apll1_tuner_clk",
"aud_apll2_tuner_clk",
"aud_i2s1_bclk_sw",
"aud_i2s2_bclk_sw",
"aud_i2s3_bclk_sw",
"aud_i2s4_bclk_sw",
"aud_tdm_clk",
"aud_tml_clk",
"aud_infra_clk",
"mtkaif_26m_clk",
"top_mux_audio",
"top_mux_aud_intbus",
"top_syspll_d2_d4",
"top_mux_aud_1",
"top_apll1_ck",
"top_mux_aud_2",
"top_apll2_ck",
"top_mux_aud_eng1",
"top_apll1_d8",
"top_mux_aud_eng2",
"top_apll2_d8",
"top_i2s0_m_sel",
"top_i2s1_m_sel",
"top_i2s2_m_sel",
"top_i2s3_m_sel",
"top_i2s4_m_sel",
"top_i2s5_m_sel",
"top_apll12_div0",
"top_apll12_div1",
"top_apll12_div2",
"top_apll12_div3",
"top_apll12_div4",
"top_apll12_divb",
"top_clk26m_clk";
};
...
@@ -167,30 +167,30 @@ examples:
"HDMI1", "TX";
hs-playback-dai-link {
link-name = "I2S0";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&da7219>;
};
link-name = "I2S0";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&da7219>;
};
};
hs-capture-dai-link {
link-name = "I2S1";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&da7219>;
};
link-name = "I2S1";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&da7219>;
};
};
spk-dp-playback-dai-link {
link-name = "I2S3";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&anx_bridge_dp>, <&max98357a>;
};
link-name = "I2S3";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&anx_bridge_dp>, <&max98357a>;
};
};
};
@@ -171,30 +171,30 @@ examples:
"HDMI1", "TX";
hs-playback-dai-link {
link-name = "I2S0";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682s 0>;
};
link-name = "I2S0";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682s 0>;
};
};
hs-capture-dai-link {
link-name = "I2S1";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682s 0>;
};
link-name = "I2S1";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682s 0>;
};
};
spk-hdmi-playback-dai-link {
link-name = "I2S3";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&it6505dptx>, <&rt1019p>;
};
link-name = "I2S3";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&it6505dptx>, <&rt1019p>;
};
};
};
@@ -165,38 +165,38 @@ examples:
"Speakers", "Speaker";
spk-playback-dai-link {
link-name = "I2S3";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt1015p>;
};
link-name = "I2S3";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt1015p>;
};
};
hs-playback-dai-link {
link-name = "I2S8";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682 0>;
};
link-name = "I2S8";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682 0>;
};
};
hs-capture-dai-link {
link-name = "I2S9";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682 0>;
};
link-name = "I2S9";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682 0>;
};
};
displayport-dai-link {
link-name = "TDM";
dai-format = "dsp_a";
codec {
sound-dai = <&anx_bridge_dp>;
};
link-name = "TDM";
dai-format = "dsp_a";
codec {
sound-dai = <&anx_bridge_dp>;
};
};
};
@@ -156,46 +156,46 @@ examples:
"Ext Spk", "Speaker";
mm-dai-link {
link-name = "ETDM1_IN_BE";
mediatek,clk-provider = "cpu";
link-name = "ETDM1_IN_BE";
mediatek,clk-provider = "cpu";
};
hs-playback-dai-link {
link-name = "ETDM1_OUT_BE";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&headset_codec>;
};
link-name = "ETDM1_OUT_BE";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&headset_codec>;
};
};
hs-capture-dai-link {
link-name = "ETDM2_IN_BE";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&headset_codec>;
};
link-name = "ETDM2_IN_BE";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&headset_codec>;
};
};
spk-playback-dai-link {
link-name = "ETDM2_OUT_BE";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&spk_amplifier>;
};
link-name = "ETDM2_OUT_BE";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&spk_amplifier>;
};
};
hdmi-dai-link {
link-name = "ETDM3_OUT_BE";
codec {
sound-dai = <&hdmi_tx>;
};
link-name = "ETDM3_OUT_BE";
codec {
sound-dai = <&hdmi_tx>;
};
};
displayport-dai-link {
link-name = "DPTX_BE";
codec {
sound-dai = <&dp_tx>;
};
link-name = "DPTX_BE";
codec {
sound-dai = <&dp_tx>;
};
};
};
@@ -0,0 +1,115 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nuvoton,nau8360.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Nuvoton NAU83G60 Stereo Class-D Amplifier with DSP
description:
Stereo Class-D Amplifier with DSP and I/V-sense.
This device supports I2C.
maintainers:
- Neo Chang <YLCHANG2@nuvoton.com>
properties:
compatible:
enum:
- nuvoton,nau8360
reg:
description: The I2C address is determined by the hardware pins.
enum: [0x1a, 0x1b, 0x4a, 0x4b]
"#sound-dai-cells":
const: 0
clocks:
maxItems: 1
clock-names:
const: mclk
firmware-name:
description:
List of DSP core firmware filenames. Both Left and Right DSP firmware
must be provided and loaded. In PBTL mode, the Left DSP must use the
same binary file as the Right DSP.
items:
- description: Left DSP core firmware filename.
- description: Right DSP core firmware filename.
nuvoton,pbtl-enable:
type: boolean
description: NAU83G60 supports PBTL mode for mono output.
nuvoton,dac-cur-enable:
type: boolean
description:
Adjust DAC output current to match speaker impedance and prevent
hardware damage. +3.2dB when present, 0dB by default.
nuvoton,dsp-rx-slot-mapping:
description:
Configures the TDM slot routing for DSP RX functions.
Each integer assigns a specific DSP internal function to a TDM slot.
The indices of the array correspond to the following hardware functions
(0) DACL
(1) DACR
(2) ANCL
(3) ANCR
Assigned slots must be unique, except 255 which disables the function.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 4
maxItems: 4
items:
enum: [ 0, 1, 2, 3, 4, 5, 6, 7, 255 ]
nuvoton,dsp-tx-slot-mapping:
description:
Configures the TDM slot routing for DSP TX functions.
Each integer assigns a specific DSP internal function to a TDM slot.
The indices of the array correspond to the following hardware functions
(0) AECL (Acoustic echo cancellation left)
(1) AECR (Acoustic echo cancellation right)
(2) ISNSL (Current sense left)
(3) ISNSR (Current sense right)
(4) VSNSL (Voltage sense left)
(5) VSNSR (Voltage sense right)
(6) TJ (Junction temperature)
(7) VBAT (Battery voltage)
Assigned slots must be unique, except 255 which disables the function.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 8
maxItems: 8
items:
enum: [ 0, 1, 2, 3, 4, 5, 6, 7, 255 ]
required:
- compatible
- reg
- firmware-name
allOf:
- $ref: dai-common.yaml#
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
codec@1a {
compatible = "nuvoton,nau8360";
reg = <0x1a>;
#sound-dai-cells = <0>;
firmware-name = "NAU83G60.kcs.bin.l", "NAU83G60.kcs.bin.r";
nuvoton,dac-cur-enable;
nuvoton,pbtl-enable;
nuvoton,dsp-rx-slot-mapping = <0 1 2 3>;
nuvoton,dsp-tx-slot-mapping = <0 1 2 3 4 5 6 7>;
};
};
@@ -48,6 +48,11 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of audio codec
nvidia,aux-devs:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: List of phandles pointing to auxiliary devices,
such as amplifiers or dsp, to be added to the sound card.
nvidia,spkr-en-gpios:
maxItems: 1
description: The GPIO that enables the speakers
@@ -0,0 +1,110 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-wm8994.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra audio complex with WM8994 CODEC
maintainers:
- Svyatoslav Ryhel <clamor95@gmail.com>
allOf:
- $ref: nvidia,tegra-audio-common.yaml#
properties:
compatible:
items:
- pattern: '^[a-z0-9]+,tegra-audio-wm8994(-[a-z0-9]+)+$'
- const: nvidia,tegra-audio-wm8994
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
- Earpiece
- Line Out
- Mic Jack
- Int Mic
- Internal Mic 1
- Internal Mic 2
- FM Radio
# CODEC Pins
- SPKOUTLP
- SPKOUTLN
- SPKOUTRP
- SPKOUTRN
- HPOUT1L
- HPOUT1R
- HPOUT2P
- HPOUT2N
- LINEOUT1P
- LINEOUT1N
- LINEOUT2P
- LINEOUT2N
- IN1LN
- IN1LP
- IN2LN
- IN2LP:VXRN
- IN1RN
- IN1RP
- IN2RN
- IN2RP:VXRP
- DMIC1DAT
- DMIC2DAT
- MICBIAS1
- MICBIAS2
required:
- nvidia,i2s-controller
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/tegra20-car.h>
#include <dt-bindings/gpio/gpio.h>
sound {
compatible = "lg,tegra-audio-wm8994-star",
"nvidia,tegra-audio-wm8994";
nvidia,model = "LG Optimus 2X WM8994";
nvidia,audio-routing =
"Headphone Jack", "HPOUT1L",
"Headphone Jack", "HPOUT1R",
"Int Spk", "SPKOUTLN",
"Int Spk", "SPKOUTLP",
"Earpiece", "HPOUT2N",
"Earpiece", "HPOUT2P",
"IN2RN", "MICBIAS2",
"IN2RN", "Mic Jack",
"IN1LN", "MICBIAS1",
"IN1LN", "Internal Mic 1",
"IN1RN", "MICBIAS1",
"IN1RN", "Internal Mic 2";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&wm8994>;
nvidia,hp-det-gpios = <&gpio 51 GPIO_ACTIVE_HIGH>;
nvidia,mic-det-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;
nvidia,ext-mic-en-gpios = <&gpio 57 GPIO_ACTIVE_HIGH>;
nvidia,coupled-mic-hp-det;
clocks = <&tegra_car TEGRA20_CLK_PLL_A>,
<&tegra_car TEGRA20_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA20_CLK_CDEV1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
@@ -1,88 +0,0 @@
NVIDIA Tegra30 AHUB (Audio Hub)
Required properties:
- compatible : For Tegra30, must contain "nvidia,tegra30-ahub". For Tegra114,
must contain "nvidia,tegra114-ahub". For Tegra124, must contain
"nvidia,tegra124-ahub". Otherwise, must contain "nvidia,<chip>-ahub",
plus at least one of the above, where <chip> is tegra132.
- reg : Should contain the register physical address and length for each of
the AHUB's register blocks.
- Tegra30 requires 2 entries, for the APBIF and AHUB/AUDIO register blocks.
- Tegra114 requires an additional entry, for the APBIF2 register block.
- interrupts : Should contain AHUB interrupt
- 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:
- d_audio
- apbif
- resets : Must contain an entry for each entry in reset-names.
See ../reset/reset.txt for details.
- reset-names : Must include the following entries:
Tegra30 and later:
- d_audio
- apbif
- i2s0
- i2s1
- i2s2
- i2s3
- i2s4
- dam0
- dam1
- dam2
- spdif
Tegra114 and later additionally require:
- amx
- adx
Tegra124 and later additionally require:
- amx1
- adx1
- afc0
- afc1
- afc2
- afc3
- afc4
- afc5
- ranges : The bus address mapping for the configlink register bus.
Can be empty since the mapping is 1:1.
- dmas : Must contain an entry for each entry in clock-names.
See ../dma/dma.txt for details.
- dma-names : Must include the following entries:
- rx0 .. rx<n>
- tx0 .. tx<n>
... where n is:
Tegra30: 3
Tegra114, Tegra124: 9
- #address-cells : For the configlink bus. Should be <1>;
- #size-cells : For the configlink bus. Should be <1>.
AHUB client modules need to specify the IDs of their CIFs (Client InterFaces).
For RX CIFs, the numbers indicate the register number within AHUB routing
register space (APBIF 0..3 RX, I2S 0..5 RX, DAM 0..2 RX 0..1, SPDIF RX 0..1).
For TX CIFs, the numbers indicate the bit position within the AHUB routing
registers (APBIF 0..3 TX, I2S 0..5 TX, DAM 0..2 TX, SPDIF TX 0..1).
Example:
ahub@70080000 {
compatible = "nvidia,tegra30-ahub";
reg = <0x70080000 0x200 0x70080200 0x100>;
interrupts = < 0 103 0x04 >;
nvidia,dma-request-selector = <&apbdma 1>;
clocks = <&tegra_car 106>, <&tegra_car 107>;
clock-names = "d_audio", "apbif";
resets = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
<&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>,
<&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>,
<&tegra_car 110>, <&tegra_car 10>;
reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
"i2s3", "i2s4", "dam0", "dam1", "dam2",
"spdif";
dmas = <&apbdma 1>, <&apbdma 1>;
<&apbdma 2>, <&apbdma 2>;
<&apbdma 3>, <&apbdma 3>;
<&apbdma 4>, <&apbdma 4>;
dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2", "rx3", "tx3";
ranges;
#address-cells = <1>;
#size-cells = <1>;
};
@@ -0,0 +1,289 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra30-ahub.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra30 AHUB (Audio Hub)
maintainers:
- Thierry Reding <thierry.reding@gmail.com>
- Jon Hunter <jonathanh@nvidia.com>
description:
AHUB client modules need to specify the IDs of their CIFs (Client
InterFaces). For RX CIFs, the numbers indicate the register number within
AHUB routing register space (APBIF 0..3 RX, I2S 0..5 RX, DAM 0..2 RX 0..1,
SPDIF RX 0..1). For TX CIFs, the numbers indicate the bit position within
the AHUB routing registers (APBIF 0..3 TX, I2S 0..5 TX, DAM 0..2 TX, SPDIF
TX 0..1).
properties:
compatible:
oneOf:
- const: nvidia,tegra30-ahub
- const: nvidia,tegra114-ahub
- const: nvidia,tegra124-ahub
- items:
- const: nvidia,tegra132-ahub
- const: nvidia,tegra124-ahub
reg:
minItems: 2
maxItems: 3
interrupts:
maxItems: 1
clocks:
items:
- description: digital audio clock
- description: module clock
clock-names:
items:
- const: d_audio
- const: apbif
resets:
minItems: 11
maxItems: 21
reset-names:
minItems: 11
maxItems: 21
ranges: true
dmas:
minItems: 8
maxItems: 20
dma-names:
minItems: 8
maxItems: 20
"#address-cells":
enum: [1, 2]
"#size-cells":
enum: [1, 2]
patternProperties:
"^i2s@[0-9a-f]+$":
type: object
required:
- compatible
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
- reset-names
- ranges
- dmas
- dma-names
- "#address-cells"
- "#size-cells"
allOf:
- if:
properties:
compatible:
const: nvidia,tegra30-ahub
then:
properties:
reg:
items:
- description: APBIF registers
- description: AHUB/AUDIO registers
resets:
maxItems: 11
reset-names:
items:
- const: d_audio
- const: apbif
- const: i2s0
- const: i2s1
- const: i2s2
- const: i2s3
- const: i2s4
- const: dam0
- const: dam1
- const: dam2
- const: spdif
dmas:
maxItems: 8
dma-names:
items:
- const: rx0
- const: tx0
- const: rx1
- const: tx1
- const: rx2
- const: tx2
- const: rx3
- const: tx3
- if:
properties:
compatible:
const: nvidia,tegra114-ahub
then:
properties:
reg:
items:
- description: APBIF registers
- description: AHUB/AUDIO registers
- description: APBIF2 registers
resets:
minItems: 13
maxItems: 13
reset-names:
items:
- const: d_audio
- const: apbif
- const: i2s0
- const: i2s1
- const: i2s2
- const: i2s3
- const: i2s4
- const: dam0
- const: dam1
- const: dam2
- const: spdif
- const: amx
- const: adx
dmas:
minItems: 20
dma-names:
items:
- const: rx0
- const: tx0
- const: rx1
- const: tx1
- const: rx2
- const: tx2
- const: rx3
- const: tx3
- const: rx4
- const: tx4
- const: rx5
- const: tx5
- const: rx6
- const: tx6
- const: rx7
- const: tx7
- const: rx8
- const: tx8
- const: rx9
- const: tx9
- if:
properties:
compatible:
contains:
const: nvidia,tegra124-ahub
then:
properties:
reg:
items:
- description: APBIF registers
- description: AHUB/AUDIO registers
- description: APBIF2 registers
resets:
minItems: 21
reset-names:
items:
- const: d_audio
- const: apbif
- const: i2s0
- const: i2s1
- const: i2s2
- const: i2s3
- const: i2s4
- const: dam0
- const: dam1
- const: dam2
- const: spdif
- const: amx
- const: amx1
- const: adx
- const: adx1
- const: afc0
- const: afc1
- const: afc2
- const: afc3
- const: afc4
- const: afc5
dmas:
minItems: 20
dma-names:
items:
- const: rx0
- const: tx0
- const: rx1
- const: tx1
- const: rx2
- const: tx2
- const: rx3
- const: tx3
- const: rx4
- const: tx4
- const: rx5
- const: tx5
- const: rx6
- const: tx6
- const: rx7
- const: tx7
- const: rx8
- const: tx8
- const: rx9
- const: tx9
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/tegra30-car.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
ahub@70080000 {
compatible = "nvidia,tegra30-ahub";
reg = <0x70080000 0x200>,
<0x70080200 0x100>;
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA30_CLK_D_AUDIO>,
<&tegra_car TEGRA30_CLK_APBIF>;
clock-names = "d_audio", "apbif";
resets = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
<&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>,
<&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>,
<&tegra_car 110>, <&tegra_car 10>;
reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
"i2s3", "i2s4", "dam0", "dam1", "dam2",
"spdif";
dmas = <&apbdma 1>, <&apbdma 1>,
<&apbdma 2>, <&apbdma 2>,
<&apbdma 3>, <&apbdma 3>,
<&apbdma 4>, <&apbdma 4>;
dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2", "rx3", "tx3";
ranges;
#address-cells = <1>;
#size-cells = <1>;
};
@@ -18,6 +18,7 @@ properties:
- items:
- enum:
- qcom,sdm660-wcd-digital-codec
- qcom,sdm670-wcd-digital-codec
- const: qcom,msm8916-wcd-digital-codec
- const: qcom,msm8916-wcd-digital-codec
@@ -20,9 +20,24 @@ properties:
minItems: 1
maxItems: 2
memory-region:
minItems: 1
items:
- description:
Control-path buffer (audio_heap_mem) for platforms where the DSP
runs in a stage-2 protected context (e.g. modem-DSP).
- description:
Data-path buffer pool from which per-stream DMA buffers are
allocated.
required:
- compatible
- iommus
oneOf:
- required:
- iommus
- required:
- memory-region
additionalProperties: false
@@ -75,11 +75,11 @@ examples:
#size-cells = <0>;
dai@10 {
reg = <PRIMARY_MI2S_RX>;
clocks = <&q6prmcc LPASS_CLK_ID_PRI_MI2S_IBIT
LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6prmcc LPASS_CLK_ID_MCLK_1
LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
clock-names = "bclk", "mclk";
reg = <PRIMARY_MI2S_RX>;
clocks = <&q6prmcc LPASS_CLK_ID_PRI_MI2S_IBIT
LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6prmcc LPASS_CLK_ID_MCLK_1
LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
clock-names = "bclk", "mclk";
};
};
@@ -108,10 +108,15 @@ patternProperties:
properties:
reg:
contains:
# TDM DAI ID range from PRIMARY_TDM_RX_0 - QUINARY_TDM_TX_7
# TDM DAI ID range from PRIMARY_TDM_RX_0 - QUINARY_TDM_TX_7 and
# AIF_TDM_RX_0 - AIF_TDM_TX_12
items:
minimum: 24
maximum: 103
oneOf:
- minimum: 24
maximum: 103
- minimum: 179
maximum: 204
then:
required:
- qcom,tdm-sync-mode
@@ -127,7 +132,8 @@ patternProperties:
contains:
# MI2S DAI ID range PRIMARY_MI2S_RX - QUATERNARY_MI2S_TX and
# QUINARY_MI2S_RX - QUINARY_MI2S_TX and
# LPI_MI2S_RX_0 - LPI_MI2S_TX_6
# LPI_MI2S_RX_0 - LPI_MI2S_TX_6 and
# AIF_MI2S_RX_0 - AIF_MI2S_TX_12
items:
oneOf:
- minimum: 16
@@ -136,6 +142,8 @@ patternProperties:
maximum: 128
- minimum: 137
maximum: 152
- minimum: 153
maximum: 178
then:
required:
- qcom,sd-lines
@@ -0,0 +1,290 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,shikra-qaif-cpu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Audio Interface (QAIF) CPU DAI Controller
maintainers:
- Harendra Gautam <harendra.gautam@oss.qualcomm.com>
description: |
The Qualcomm Audio Interface (QAIF) is a fully configurable DMA-based
audio subsystem controller. It serialises and deserialises PCM audio
between system memory and external serial audio peripherals (PCM, TDM,
I2S, MI2S) through the AIF path, and transfers parallel audio between
memory and an internal WCD codec through the CIF path.
AIF (Audio Interface): up to 13 multi-lane Unified Audio Interfaces,
each supporting up to 8 independent data lanes. Each lane is individually
configurable as TX (output/speaker) or RX (input/mic). All lanes of an
interface share a single bit clock and frame sync. Supported modes are
PCM (short/long sync), TDM, and MI2S (stereo/mono). Per-interface
configuration includes sync source (master/slave), sync mode, sync delay,
sync inversion, slot width (8/16/24/32-bit), sample width, active slot
masks (up to 32 slots), bits-per-lane frame size, lane enable/direction
masks, loopback, output-enable control, and full-cycle path support for
long chip-to-chip connections.
CIF (Codec Interface): up to 10 RDDMA (playback) and 10 WRDMA (capture)
channels connecting to an internal codec over a parallel bus. Each channel
supports active-channel enable mask (up to 16 channels), frame-sync
selection, frame-sync delay, frame-sync output gating, dynamic clock
gating, and 16-bit packing/unpacking.
Note on RX/TX naming convention: in QAIF, TX refers to the output
(speaker/playback) direction and RX refers to the input (mic/capture)
direction. This applies to both AIF lane directions and CIF slot/mask
properties.
DMA engine: RDDMA fetches audio from DDR/TCM/LPM into a shared SRAM
latency buffer (SHRAM) and drains it to the interface. WRDMA collects
data from the interface into SHRAM and writes it to memory. Each DMA
owns a private SHRAM region defined by start address and length registers.
Burst sizes of 1/2/4/8/16 beats (64-bit) are supported with up to 4
outstanding transactions per DMA. Two QSB master ports (QXM0 for TCM,
QXM1 for DDR/LPM) provide the memory interface.
Resources are partitioned among up to 5 Execution Engines (EEs) via
EE map registers. Each EE owns a set of DMAs, audio interfaces, and
interface groups, and receives its own independent interrupt output.
The interrupt hierarchy has a two-level structure: a summary register
identifies the event class (DMA period, underflow/overflow, error
response, audio interface underflow/overflow, group done, rate detector,
VFR), and per-resource status registers identify the specific channel.
Interface grouping (bonding) allows up to 6 groups of audio and codec
interfaces to start synchronously and align their DMA period interrupts
within half a frame duration using the RDDMA padding feature.
Two rate detector blocks measure the frequency of incoming frame sync or
word select signals and generate interrupts on rate change, undetected
rate, or sync timeout.
Block diagram::
System Memory (DDR / LPM / TCM)
+---------------------------------+
| Circular Buffers (ping-pong) |
+----------+----------+-----------+
| ^
64-bit AXI 64-bit AXI
| |
+----------v----------+-----------+
| QSB Master Ports |
| +----------+ +----------+ |
| | QXM0 | | QXM1 | |
| +----+-----+ +-----+----+ |
+-------|--------------|----------+
| |
+-------v--------------v----------+
| Shared RAM (SHRAM) |
| +------------+ +------------+ |
| | QXM0 Read | | QXM0 Write | |
| | SHRAM | | SHRAM | |
| +------------+ +------------+ |
| +------------+ +------------+ |
| | QXM1 Read | | QXM1 Write | |
| | SHRAM | | SHRAM | |
| +------------+ +------------+ |
+---+--------+--------+-------+---+
| | | |
+---v--+ +--v---+ +--v---+ +-v----+
|RDDMA | |RDDMA | |WRDMA | |WRDMA |
| AIF | | CIF | | AIF | | CIF |
|[0..n]| |[0..n]| |[0..n]| |[0..n]|
+--+---+ +--+---+ +--+---+ +-+----+
| | ^ ^
| TX | TX | RX | RX
v v | |
+--+--------------------+ +----+----------+
| Unified Audio Intf | | Codec DMA |
| (AIF 0..12) | | Interface |
| | | (CIF) |
| AUD_INTFa block: | | |
| - Serializer (TX) | | RDDMA: DDR -> |
| - De-serializer (RX) | | internal |
| - Sync gen/detect | | codec |
| - Up to 8 data lanes | | WRDMA: codec |
| - PCM / TDM / MI2S | | -> DDR |
| - Near Pad Logic | | Up to 16 ch |
+--+--------------------+ +----+----------+
| Lane 0..7 (TX/RX) | Parallel bus
| Bit clk + Frame sync | + Frame sync
v v
+--+--------+ +------+------+
| External | | Internal |
| Serial | | Digital |
| Peripherals| | Codec |
| (PCM/TDM/ | | (Bolero/ |
| MI2S) | | WCD) |
+-----------+ +-------------+
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: qcom,shikra-qaif-cpu
reg:
maxItems: 1
interrupts:
maxItems: 1
description:
QAIF summary interrupt for this Execution Engine.
iommus:
maxItems: 1
dma-coherent: true
clocks:
maxItems: 9
clock-names:
description:
Core clocks for register access and DMA, followed by one bit
clock per AIF interface.
items:
- const: lpass_config
- const: lpass_core_axim
- const: aud_dma
- const: aud_dma_mem
- const: bus
- const: aif_if0_ibit
- const: aif_if1_ibit
- const: aif_if2_ibit
- const: aif_if3_ibit
'#sound-dai-cells':
const: 1
'#address-cells':
const: 1
'#size-cells':
const: 0
patternProperties:
'^aif@[0-9a-f]+$':
type: object
description:
QAIF AIF interface child node for PCM, TDM or MI2S configuration.
allOf:
- $ref: /schemas/sound/tdm-slot.yaml#
properties:
reg:
maxItems: 1
description:
DAI ID of the AIF interface (QAIF_MI2S_AIF* or QAIF_TDM_AIF*).
dai-format:
description: Serial audio interface format (MI2S, TDM or PCM).
enum: [i2s, dsp_a, dsp_b]
dai-tdm-slot-width:
enum: [8, 16, 24, 32]
dai-tdm-slot-num:
minimum: 1
maximum: 32
dai-tdm-slot-rx-mask:
minItems: 1
maxItems: 32
dai-tdm-slot-tx-mask:
minItems: 1
maxItems: 32
qcom,qaif-aif-lane-map:
$ref: /schemas/types.yaml#/definitions/uint32-array
description:
Per-lane direction map, one entry per lane starting from lane 0.
Use 0 for TX (output/speaker) and 1 for RX (input/mic).
minItems: 1
maxItems: 8
items:
enum: [0, 1]
required:
- reg
- dai-format
- qcom,qaif-aif-lane-map
if:
properties:
dai-format:
enum: [dsp_a, dsp_b]
then:
required:
- dai-tdm-slot-width
- dai-tdm-slot-num
- dai-tdm-slot-rx-mask
- dai-tdm-slot-tx-mask
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
- iommus
- clocks
- clock-names
- '#sound-dai-cells'
- '#address-cells'
- '#size-cells'
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
qaif_cpu: audio-controller@a000000 {
compatible = "qcom,shikra-qaif-cpu";
reg = <0x0 0x0a000000 0x0 0x20000>;
interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>;
iommus = <&apps_smmu 0x1c0 0x0>;
clocks = <&gcc 213>,
<&gcc 214>,
<&audiocorecc 15>,
<&audiocorecc 17>,
<&audiocorecc 18>,
<&audiocorecc 5>,
<&audiocorecc 8>,
<&audiocorecc 11>,
<&audiocorecc 14>;
clock-names = "lpass_config",
"lpass_core_axim",
"aud_dma",
"aud_dma_mem",
"bus",
"aif_if0_ibit",
"aif_if1_ibit",
"aif_if2_ibit",
"aif_if3_ibit";
#sound-dai-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
aif@b5 {
reg = <181>;
dai-format = "dsp_a";
dai-tdm-slot-width = <32>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-rx-mask = <1 1>;
dai-tdm-slot-tx-mask = <1 1>;
qcom,qaif-aif-lane-map = <1 0>;
};
};
};
@@ -36,8 +36,10 @@ properties:
- ayaneo,pocket-s2-sndcard
- fairphone,fp4-sndcard
- fairphone,fp5-sndcard
- motorola,dubai-sndcard
- qcom,apq8096-sndcard
- qcom,glymur-sndcard
- qcom,nord-sndcard
- qcom,qcm6490-idp-sndcard
- qcom,qcs615-sndcard
- qcom,qcs6490-rb3gen2-sndcard
@@ -54,6 +56,7 @@ properties:
- qcom,sm8250-sndcard
- qcom,sm8450-sndcard
- qcom,x1e80100-sndcard
- thundercomm,qcs6490-rubikpi3-sndcard
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
@@ -0,0 +1,105 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,wcd9378-sdw.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm WCD9378 (Tambora) SoundWire codec
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
description:
Qualcomm WCD9378 (Tambora) SoundWire codec. The same silicon can be
fused for a mobile (non-SDCA) mode or an SDCA-compliant mode; the
qcom,sdca-compliant property selects the latter and is required by
this driver.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: sdw20217011000
reg:
maxItems: 1
qcom,sdca-compliant:
description:
Present when the codec is fused as SDCA-compliant. The mobile
(non-SDCA) variant carries the same class-ID compatible and is
handled by a different driver.
type: boolean
qcom,port-mapping:
description:
Each entry maps a slave data port to a master data port.
Entries are in order starting from slave port 1; slave port 0
is reserved and not represented. SDCA-compliant mode uses 8
entries covering DP1..DP8.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 8
maxItems: 8
reset-gpios:
description: GPIO used to release the codec from reset.
maxItems: 1
vdd-buck-supply:
description: 1.8 V analog buck supply.
vdd-rxtx-supply:
description: 1.8 V RX/TX supply.
vdd-io-supply:
description: Digital I/O supply.
vdd-mic-bias-supply:
description: Mic bias supply.
'#sound-dai-cells':
const: 1
required:
- compatible
- reg
- qcom,sdca-compliant
- qcom,port-mapping
- reset-gpios
- vdd-buck-supply
- vdd-rxtx-supply
- vdd-io-supply
- vdd-mic-bias-supply
- '#sound-dai-cells'
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
soundwire@7630000 {
reg = <0x07630000 0x10000>;
#address-cells = <2>;
#size-cells = <0>;
wcd9378c_sdw: audio-codec@0,3 {
compatible = "sdw20217011000";
reg = <0 3>;
qcom,sdca-compliant;
qcom,port-mapping = <2 2 3 4 5 6 7 8>;
reset-gpios = <&tlmm 191 GPIO_ACTIVE_LOW>;
vdd-buck-supply = <&vreg_l15b_1p8>;
vdd-rxtx-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l18b_1p2>;
vdd-mic-bias-supply = <&vreg_bob1>;
#sound-dai-cells = <1>;
};
};
...
@@ -44,6 +44,14 @@ properties:
'#gpio-cells':
const: 2
clocks:
items:
- description: phandle and clock specifier for the codec MCLK1 input.
clock-names:
items:
- const: mclk1
realtek,pow-ldo2-gpio:
maxItems: 1
description: CODEC's POW_LDO2 pin.
@@ -127,6 +135,8 @@ examples:
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
clocks = <&osc>;
clock-names = "mclk1";
realtek,pow-ldo2-gpio = <&gpio 3 GPIO_ACTIVE_HIGH>;
realtek,reset-gpio = <&gpio 3 GPIO_ACTIVE_LOW>;
realtek,in1-differential;
@@ -432,14 +432,14 @@ examples:
"ssi.1", "ssi.0";
rcar_sound,dvc {
dvc0: dvc-0 {
dmas = <&audma0 0xbc>;
dma-names = "tx";
};
dvc1: dvc-1 {
dmas = <&audma0 0xbe>;
dma-names = "tx";
};
dvc0: dvc-0 {
dmas = <&audma0 0xbc>;
dma-names = "tx";
};
dvc1: dvc-1 {
dmas = <&audma0 0xbe>;
dma-names = "tx";
};
};
rcar_sound,mix {
@@ -95,20 +95,20 @@ examples:
ssi0: ssi@10049c00 {
compatible = "renesas,r9a07g044-ssi",
"renesas,rz-ssi";
reg = <0x10049c00 0x400>;
interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 328 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "int_req", "dma_rx", "dma_tx";
clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>,
<&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>,
<&audio_clk1>,
<&audio_clk2>;
clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
power-domains = <&cpg>;
resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
dmas = <&dmac 0x2655>,
<&dmac 0x2656>;
dma-names = "tx", "rx";
#sound-dai-cells = <0>;
reg = <0x10049c00 0x400>;
interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 328 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "int_req", "dma_rx", "dma_tx";
clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>,
<&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>,
<&audio_clk1>,
<&audio_clk2>;
clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
power-domains = <&cpg>;
resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
dmas = <&dmac 0x2655>,
<&dmac 0x2656>;
dma-names = "tx", "rx";
#sound-dai-cells = <0>;
};
@@ -0,0 +1,96 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/stericsson,ux500-msp-i2s.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ST-Ericsson Ux500 Multichannel Serial Port
maintainers:
- Linus Walleij <linusw@kernel.org>
description:
The Ux500 Multichannel Serial Port (MSP) is a synchronous serial audio
interface supporting I2S and PCM/TDM protocols. Data is transferred to and
from memory using the Ux500 DMA controller.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: stericsson,ux500-msp-i2s
reg:
maxItems: 1
interrupts:
maxItems: 1
v-ape-supply:
description: Analog power engine supply
dmas:
minItems: 1
maxItems: 2
dma-names:
minItems: 1
maxItems: 2
items:
enum: [ rx, tx ]
clocks:
items:
- description: MSP functional clock
- description: MSP APB bus clock
clock-names:
items:
- const: msp
- const: apb_pclk
resets:
maxItems: 1
'#sound-dai-cells':
const: 0
port:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
- v-ape-supply
- dmas
- dma-names
- clocks
- clock-names
- resets
- '#sound-dai-cells'
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/reset/stericsson,db8500-prcc-reset.h>
msp@80123000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80123000 0x1000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
v-ape-supply = <&db8500_vape_reg>;
dmas = <&dma 31 0 0x12>, <&dma 31 0 0x10>;
dma-names = "rx", "tx";
clocks = <&prcc_kclk 1 3>, <&prcc_pclk 1 3>;
clock-names = "msp", "apb_pclk";
resets = <&prcc_reset DB8500_PRCC_1 DB8500_PRCC_1_RESET_MSP0>;
#sound-dai-cells = <0>;
};
...
@@ -0,0 +1,83 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,da830-evm-audio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments SoC audio setups with TLV320AIC3X Codec
maintainers:
- Eduard Bostina <egbostina@gmail.com>
properties:
compatible:
const: ti,da830-evm-audio
ti,model:
$ref: /schemas/types.yaml#/definitions/string
description: The user-visible name of this sound complex.
ti,audio-codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of the TLV320AIC3x audio codec
ti,mcasp-controller:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of the McASP controller
ti,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 codec's pins, and the jacks on the board (Headphone Jack,
Line Out, Mic Jack, Line In).
ti,codec-clock-rate:
$ref: /schemas/types.yaml#/definitions/uint32
description: The Codec Clock rate (in Hz) applied to the Codec.
clocks:
maxItems: 1
description: Reference to the master clock
clock-names:
const: mclk
required:
- compatible
- ti,model
- ti,audio-codec
- ti,mcasp-controller
- ti,audio-routing
anyOf:
- required:
- ti,codec-clock-rate
- required:
- clocks
additionalProperties: false
examples:
- |
sound {
compatible = "ti,da830-evm-audio";
ti,model = "DA830 EVM";
ti,audio-codec = <&tlv320aic3x>;
ti,mcasp-controller = <&mcasp1>;
ti,codec-clock-rate = <12000000>;
ti,audio-routing =
"Headphone Jack", "HPLOUT",
"Headphone Jack", "HPROUT",
"Line Out", "LLOUT",
"Line Out", "RLOUT",
"MIC3L", "Mic Bias 2V",
"MIC3R", "Mic Bias 2V",
"Mic Bias 2V", "Mic Jack",
"LINE1L", "Line In",
"LINE2L", "Line In",
"LINE1R", "Line In",
"LINE2R", "Line In";
};
@@ -21,6 +21,22 @@ properties:
reg:
maxItems: 1
clocks:
maxItems: 1
description: System clock (SCK)
clock-names:
const: sck
VCC1-supply:
description: 5V analog power supply
VCC2-supply:
description: 5V analog power supply
VDD-supply:
description: 3.3V digital power supply
"#sound-dai-cells":
const: 0
@@ -219,9 +219,7 @@ allOf:
- if:
properties:
compatible:
contains:
enum:
- ti,tas2781
const: ti,tas2781
then:
properties:
reg:
@@ -45,13 +45,13 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
tas5805m: tas5805m@2c {
reg = <0x2c>;
compatible = "ti,tas5805m";
reg = <0x2c>;
compatible = "ti,tas5805m";
pvdd-supply = <&audiopwr>;
pdn-gpios = <&tlmm 160 0>;
pvdd-supply = <&audiopwr>;
pdn-gpios = <&tlmm 160 0>;
ti,dsp-config-name = "mono_pbtl_48khz";
ti,dsp-config-name = "mono_pbtl_48khz";
};
};
...
@@ -121,6 +121,6 @@ examples:
AVDD-supply = <&regulator>;
IOVDD-supply = <&regulator>;
DVDD-supply = <&regulator>;
};
};
};
@@ -50,6 +50,6 @@ examples:
reg = <0x60>;
Vdd-supply = <&vmmc2>;
power-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
};
};
};
@@ -1,39 +0,0 @@
* MOP500 Audio Machine Driver
This node is responsible for linking together all ux500 Audio Driver components.
Required properties:
- compatible : "stericsson,snd-soc-mop500"
Non-standard properties:
- stericsson,cpu-dai : Phandle to the CPU-side DAI
- stericsson,audio-codec : Phandle to the Audio CODEC
- stericsson,card-name : Over-ride default card name
Example:
sound {
compatible = "stericsson,snd-soc-mop500";
stericsson,cpu-dai = <&msp1 &msp3>;
stericsson,audio-codec = <&codec>;
};
msp1: msp@80124000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80124000 0x1000>;
interrupts = <0 62 0x4>;
v-ape-supply = <&db8500_vape_reg>;
};
msp3: msp@80125000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80125000 0x1000>;
interrupts = <0 62 0x4>;
v-ape-supply = <&db8500_vape_reg>;
};
codec: ab8500-codec {
compatible = "stericsson,ab8500-codec";
stericsson,earpeice-cmv = <950>; /* Units in mV. */
};
@@ -1,42 +0,0 @@
* ux500 MSP (CPU-side Digital Audio Interface)
Required properties:
- compatible :"stericsson,ux500-msp-i2s"
- reg : Physical base address and length of the device's registers.
Optional properties:
- interrupts : The interrupt output from the device.
- <name>-supply : Phandle to the regulator <name> supply
Example:
sound {
compatible = "stericsson,snd-soc-mop500";
stericsson,platform-pcm-dma = <&pcm>;
stericsson,cpu-dai = <&msp1 &msp3>;
stericsson,audio-codec = <&codec>;
};
pcm: ux500-pcm {
compatible = "stericsson,ux500-pcm";
};
msp1: msp@80124000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80124000 0x1000>;
interrupts = <0 62 0x4>;
v-ape-supply = <&db8500_vape_reg>;
};
msp3: msp@80125000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80125000 0x1000>;
interrupts = <0 62 0x4>;
v-ape-supply = <&db8500_vape_reg>;
};
codec: ab8500-codec {
compatible = "stericsson,ab8500-codec";
stericsson,earpeice-cmv = <950>; /* Units in mV. */
};
@@ -561,6 +561,8 @@ patternProperties:
description: Seiko Epson Corp.
"^esp,.*":
description: Espressif Systems Co. Ltd.
"^esstech,.*":
description: ESS Technology, Inc.
"^est,.*":
description: ESTeem Wireless Modems
"^eswin,.*":
@@ -2407,6 +2407,12 @@ quirk_flags
the requested rate. A device advertising a single rate is otherwise
never sent the request at all, and some require it before streaming
will start.
* bit 33: ``swap_rates``
The clock source applies a requested rate to the other base-rate
family, i.e. asking for 44100 makes the device run at 48000 and vice
versa (same for 88200 <-> 96000 and 176400 <-> 192000). The driver
sends the partner rate in SET_CUR so the device ends up running at the
requested one.
This module supports multiple devices, autoprobe and hotplugging.
+40 -69
View File
@@ -6,9 +6,11 @@ Software Interface ALSA-DSP MADI Driver
2004 - winfried ritsch
driver name - snd-hdspm
Full functionality has been added to the driver. Since some of
the Controls and startup-options are ALSA-Standard and only the
the Controls and startup options are ALSA-Standard, only the
special Controls are described and discussed below.
@@ -18,7 +20,7 @@ Hardware functionality
Audio transmission
------------------
* number of channels -- depends on transmission mode
* number of channels -- depends on transmission mode
The number of channels chosen is from 1..Nmax. The reason to
use for a lower number of channels is only resource allocation,
@@ -29,29 +31,29 @@ Audio transmission
* Single Speed -- 1..64 channels
.. note::
(Note: Choosing the 56channel mode for transmission or as
Choosing the 56-channel mode for transmission or as
receiver, only 56 are transmitted/received over the MADI, but
all 64 channels are available for the mixer, so channel count
for the driver)
for the driver.
* Double Speed -- 1..32 channels
.. note::
Note: Choosing the 56-channel mode for
transmission/receive-mode , only 28 are transmitted/received
Choosing the 56-channel mode for
transmission/receive-mode, only 28 are transmitted/received
over the MADI, but all 32 channels are available for the mixer,
so channel count for the driver
so channel count for the driver.
* Quad Speed -- 1..16 channels
.. note::
Choosing the 56-channel mode for
transmission/receive-mode , only 14 are transmitted/received
transmission/receive-mode, only 14 are transmitted/received
over the MADI, but all 16 channels are available for the mixer,
so channel count for the driver
so channel count for the driver.
* Format -- signed 32 Bit Little Endian (SNDRV_PCM_FMTBIT_S32_LE)
* Format -- signed 32-bit Little Endian (SNDRV_PCM_FMTBIT_S32_LE)
* Sample Rates --
@@ -67,30 +69,6 @@ Audio transmission
* fragments -- 2
* Hardware-pointer -- 2 Modi
The Card supports the readout of the actual Buffer-pointer,
where DMA reads/writes. Since of the bulk mode of PCI it is only
64 Byte accurate. SO it is not really usable for the
ALSA-mid-level functions (here the buffer-ID gives a better
result), but if MMAP is used by the application. Therefore it
can be configured at load-time with the parameter
precise-pointer.
.. hint::
(Hint: Experimenting I found that the pointer is maximum 64 to
large never to small. So if you subtract 64 you always have a
safe pointer for writing, which is used on this mode inside
ALSA. In theory now you can get now a latency as low as 16
Samples, which is a quarter of the interrupt possibilities.)
* Precise Pointer -- off
interrupt used for pointer-calculation
* Precise Pointer -- on
hardware pointer used.
Controller
----------
@@ -104,7 +82,7 @@ hwdep-interface.
Also all 128+256 Peak and RMS-Meter can be accessed via the
hwdep-interface. Since it could be a performance problem always
copying and converting Peak and RMS-Levels even if you just need
one, I decided to export the hardware structure, so that of
one, I decided to export the hardware structure, so that if
needed some driver-guru can implement a memory-mapping of mixer
or peak-meters over ioctl, or also to do only copying and no
conversion. A test-application shows the usage of the controller.
@@ -112,9 +90,9 @@ conversion. A test-application shows the usage of the controller.
* Latency Controls --- not implemented !!!
.. note::
Note: Within the windows-driver the latency is accessible of a
control-panel, but buffer-sizes are controlled with ALSA from
hwparams-calls and should not be changed in run-state, I did not
Within the Windows driver the latency is accessible via
Control Panel, but buffer sizes are controlled with ALSA from
hwparams calls and should not be changed in run-state. I did not
implement it here.
@@ -127,12 +105,12 @@ conversion. A test-application shows the usage of the controller.
* Values -- "Master" "Slave"
.. note::
!!!! This is a hardware-function but is in conflict with the
Clock-source controller, which is a kind of ALSA-standard. I
!!!! This is a hardware function but is in conflict with the
Clock-source controller, which is a kind of ALSA-standard. It
makes sense to set the card to a special mode (master at some
frequency or slave), since even not using an Audio-application
frequency or slave), since even not using an Audio application
a studio should have working synchronisations setup. So use
Clock-source-controller instead !!!!
Clock-source controller instead !!!!
* Clock Source
@@ -145,11 +123,11 @@ conversion. A test-application shows the usage of the controller.
"Internal 96.0 kHz"
Choose between Master at a specific Frequency and so also the
Speed-mode or Slave (Autosync). Also see "Preferred Sync Ref"
Speed-mode or Slave (Autosync). Also see "Preferred Sync Ref".
.. warning::
!!!! This is no pure hardware function but was implemented by
ALSA by some ALSA-drivers before, so I use it also. !!!
!!!! This is not a pure hardware function but was implemented by
ALSA by some ALSA drivers before, so I use it also. !!!
* Preferred Sync Ref
@@ -165,7 +143,7 @@ conversion. A test-application shows the usage of the controller.
chosen. If it is not available another is used if possible.
.. note::
Note: Since MADI has a much higher bit-rate than word-clock, the
Since MADI has a much higher bit-rate than word-clock, the
card should synchronise better in MADI Mode. But since the
RME-PLL is very good, there are almost no problems with
word-clock too. I never found a difference.
@@ -179,12 +157,12 @@ conversion. A test-application shows the usage of the controller.
* Values -- 0 1
Using 64-channel-modus (1) or 56-channel-modus for
Using 64-channel mode (1) or 56-channel mode for
MADI-transmission (0).
.. note::
Note: This control is for output only. Input-mode is detected
This control is for output only. Input mode is detected
automatically from hardware sending MADI.
@@ -200,7 +178,7 @@ conversion. A test-application shows the usage of the controller.
Don't use to lower 5 Audio-bits on AES as additional Bits.
* Safe Mode oder Auto Input
* Safe Mode or Auto Input
* Name -- "Safe Mode"
@@ -222,7 +200,7 @@ conversion. A test-application shows the usage of the controller.
* Values -- optical coaxial
Choosing the Input, optical or coaxial. If Safe-mode is active,
Choosing the Input, optical or coaxial. If Safe mode is active,
this is the preferred Input.
Mixer
@@ -240,7 +218,7 @@ Mixer
Here as a first value the channel-index is taken to get/set the
corresponding mixer channel, where 0-63 are the input to output
fader and 64-127 the playback to outputs fader. Value 0
is channel muted 0 and 32768 an amplification of 1.
is channel muted 0 and 32768 an amplification of 1.
* Chn 1-64
@@ -250,14 +228,14 @@ Mixer
* Line Out
* Name -- "Line Out"
* Name -- "Line Out"
* Access -- Read Write
* Values -- 0 1
Switching on and off the analog out, which has nothing to do
with mixing or routing. the analog outs reflects channel 63,64.
with mixing or routing. The analog outs reflects channel 63,64.
Information (only read access)
@@ -280,7 +258,7 @@ Information (only read access)
Should be "Autosync Rate", but Name used is
ALSA-Scheme. External Sample frequency liked used on Autosync is
ALSA-Scheme. External Sample frequency like used on Autosync is
reported.
@@ -315,19 +293,19 @@ Information (only read access)
Sync-Reference is either "WordClock", "MADI" or none.
* RX 64ch --- noch nicht implementiert
* RX 64ch --- not yet implemented
MADI-Receiver is in 64 channel mode oder 56 channel mode.
MADI-Receiver is in 64-channel mode or 56-channel mode.
* AB_inp --- not tested
* AB_inp --- not tested
Used input for Auto-Input.
* actual Buffer Position --- not implemented
!!! this is a ALSA internal function, so no control is used !!!
!!! This is an ALSA internal function, so no control is used !!!
@@ -352,22 +330,15 @@ Calling Parameter
note: ALSA-standard
* precise_ptr int array (min = 1, max = 8)
Enable precise pointer, or disable.
.. note::
note: Use only when the application supports this (which is a special case).
* line_outs_monitor int array (min = 1, max = 8)
Send playback streams to analog outs by default.
.. note::
note: each playback channel is mixed to the same numbered output
Each playback channel is mixed to the same numbered output
channel (routed). This is against the ALSA-convention, where all
channels have to be muted on after loading the driver, but was
used before on other cards, so i historically use it again)
used before on other cards, so I historically use it again.
@@ -375,5 +346,5 @@ Calling Parameter
Enable Analog Out on Channel 63/64 by default.
.. note ::
note: here the analog output is enabled (but not routed).
.. note::
Here the analog output is enabled (but not routed).
+40
View File
@@ -779,6 +779,14 @@ F: Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.yaml
F: drivers/phy/phy-airoha-pcie-regs.h
F: drivers/phy/phy-airoha-pcie.c
AIROHA SOUND DRIVER
M: Christian Marangi <ansuelsmth@gmail.com>
L: linux-sound@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/sound/airoha,an7581-afe.yaml
F: Documentation/devicetree/bindings/sound/airoha,an7581-wm8960.yaml
F: sound/soc/mediatek/an7581/*
AIROHA SPI SNFI DRIVER
M: Lorenzo Bianconi <lorenzo@kernel.org>
M: Ray Liu <ray.liu@airoha.com>
@@ -4399,6 +4407,13 @@ F: drivers/net/ieee802154/at86rf230.h
F: drivers/net/ieee802154/atusb.c
F: drivers/net/ieee802154/atusb.h
AUDIENT EVO MIXER DRIVER
M: Christian Ruppert <arc@gmx.li>
L: linux-sound@vger.kernel.org
S: Maintained
F: sound/usb/mixer_evo.c
F: sound/usb/mixer_evo.h
AUDIT SUBSYSTEM
M: Paul Moore <paul@paul-moore.com>
M: Eric Paris <eparis@redhat.com>
@@ -4472,6 +4487,12 @@ L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/pci/hws/
AWINIC AW88399 HDA SIDE CODEC DRIVER
M: Marco Giunta <marco_giunta@outlook.it>
L: linux-sound@vger.kernel.org
S: Maintained
F: sound/hda/codecs/side-codecs/aw88399*
AWINIC AW99706 WLED BACKLIGHT DRIVER
M: Junjie Cao <junjie.cao@linux.dev>
S: Maintained
@@ -9874,6 +9895,13 @@ S: Maintained
F: include/linux/errseq.h
F: lib/errseq.c
ES9039Q2M AUDIO CODEC DRIVER
M: Karl Asseily <karl@asseily.com>
L: linux-sound@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/sound/esstech,es9039q2m.yaml
F: sound/soc/codecs/es9039q2m.c
ESD CAN NETWORK DRIVERS
M: Stefan Mätje <stefan.maetje@esd.eu>
R: socketcan@esd.eu
@@ -22395,6 +22423,15 @@ F: sound/soc/codecs/wcd93*.*
F: sound/soc/codecs/wsa88*.*
F: sound/soc/qcom/
QCOM AUDIO INTERFACE (QAIF) DRIVER
M: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
M: Srinivas Kandagatla <srini@kernel.org>
L: linux-sound@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/sound/qcom,shikra-qaif-cpu.yaml
F: sound/soc/qcom/qaif*
QCOM EMBEDDED USB DEBUGGER (EUD)
M: Souradeep Chowdhury <quic_schowdhu@quicinc.com>
L: linux-arm-msm@vger.kernel.org
@@ -30630,9 +30667,12 @@ F: tools/testing/selftests/cgroup/test_zswap.c
SENARYTECH AUDIO CODEC DRIVER
M: bo liu <bo.liu@senarytech.com>
M: qianghua.wang <qianghua.wang@senarytech.com>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
F: sound/hda/codecs/senarytech.c
F: sound/soc/codecs/sn624x*
F: sound/soc/sdw_utils/soc_sdw_senary*
ZTE DINGHAI ETHERNET DRIVER
M: Junyang Han <han.junyang@zte.com.cn>
+1
View File
@@ -1763,6 +1763,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
/* Non-conforming _HID for Cirrus Logic already released */
{"CLSA0100", },
{"CLSA0101", },
{"CLSA0102", },
/*
* Some ACPI devs contain SerialBus resources even though they are not
* attached to a serial bus at all.
+3 -1
View File
@@ -2960,6 +2960,8 @@ int cs_dsp_run(struct cs_dsp *dsp)
return 0;
err:
dsp->running = false;
if (dsp->ops->stop_core)
dsp->ops->stop_core(dsp);
if (dsp->ops->disable_core)
@@ -3505,7 +3507,7 @@ EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_write, "FW_CS_DSP");
*
* As cs_dsp_chunk_write only writes data when a whole DSP word is ready to
* be written out it is possible that some data will remain in the cache, this
* function will pad that data with zeros upto a whole DSP word and write out.
* function will pad that data with zeros up to a whole DSP word and write out.
*
* Return: Zero for success, a negative number on error.
*/
@@ -36,6 +36,8 @@ struct cs_dsp_test_local {
int num_post_stop;
int num_watchdog_expired;
bool fail_post_run;
struct cs_dsp_coeff_ctl *passed_ctl[16];
struct cs_dsp *passed_dsp;
};
@@ -106,6 +108,9 @@ static int cs_dsp_test_post_run_callback(struct cs_dsp *dsp)
local->passed_dsp = dsp;
local->num_post_run++;
if (local->fail_post_run)
return -EIO;
return 0;
}
@@ -198,6 +203,33 @@ static void cs_dsp_test_run_stop_callbacks(struct kunit *test)
local->passed_dsp = NULL;
}
static void cs_dsp_test_run_error_clears_running(struct kunit *test)
{
struct cs_dsp_test *priv = test->priv;
struct cs_dsp_test_local *local = priv->local;
struct firmware *wmfw;
wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
KUNIT_EXPECT_EQ(test,
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
0);
/*
* By the time the post_run hook runs, the core has been started. A
* failure there stops and disables the core again, so the DSP must not
* be left looking like it is running.
*/
local->fail_post_run = true;
KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), -EIO);
KUNIT_EXPECT_FALSE(test, priv->dsp->running);
/* and the next run must be able to start it again */
local->fail_post_run = false;
KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
KUNIT_EXPECT_TRUE(test, priv->dsp->running);
}
static void cs_dsp_test_ctl_v1_callbacks(struct kunit *test)
{
struct cs_dsp_test *priv = test->priv;
@@ -609,6 +641,7 @@ KUNIT_ARRAY_PARAM(cs_dsp_no_callbacks,
static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv1_test_cases[] = {
KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
KUNIT_CASE_PARAM(cs_dsp_test_run_error_clears_running, cs_dsp_callbacks_ops_gen_params),
KUNIT_CASE_PARAM(cs_dsp_test_ctl_v1_callbacks, cs_dsp_callbacks_ops_gen_params),
KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
@@ -617,6 +650,7 @@ static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv1_test_cases[] = {
static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv2_test_cases[] = {
KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
KUNIT_CASE_PARAM(cs_dsp_test_run_error_clears_running, cs_dsp_callbacks_ops_gen_params),
KUNIT_CASE_PARAM(cs_dsp_test_ctl_v2_callbacks, cs_dsp_callbacks_ops_gen_params),
KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
@@ -625,6 +659,7 @@ static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv2_test_cases[] = {
static struct kunit_case cs_dsp_callbacks_halo_test_cases[] = {
KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
KUNIT_CASE_PARAM(cs_dsp_test_run_error_clears_running, cs_dsp_callbacks_ops_gen_params),
KUNIT_CASE_PARAM(cs_dsp_test_ctl_v2_callbacks, cs_dsp_callbacks_ops_gen_params),
KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
+7 -3
View File
@@ -1458,11 +1458,15 @@ static int fmh_gpib_attach_impl(struct gpib_board *board, const struct gpib_boar
e_priv->irq = irq;
if (acquire_dma) {
e_priv->dma_channel = dma_request_slave_channel(board->dev, "rxtx");
if (!e_priv->dma_channel) {
struct dma_chan *tmp_chan;
tmp_chan = dma_request_chan(board->dev, "rxtx");
retval = PTR_ERR_OR_ZERO(tmp_chan);
if (retval) {
dev_err(board->dev, "failed to acquire dma channel \"rxtx\".\n");
return -EIO;
return retval;
}
e_priv->dma_channel = tmp_chan;
}
/*
* in the future we might want to know the half-fifo size
@@ -426,6 +426,7 @@ static const struct acpi_device_id smi_acpi_ids[] = {
/* Non-conforming _HID for Cirrus Logic already released */
{ "CLSA0100", (unsigned long)&cs35l41_hda },
{ "CLSA0101", (unsigned long)&cs35l41_hda },
{ "CLSA0102", (unsigned long)&cs35l41_hda },
{ }
};
MODULE_DEVICE_TABLE(acpi, smi_acpi_ids);
+27
View File
@@ -17,6 +17,33 @@
#define CS35L45_ASP_TX_HIZ_UNUSED 0x1
#define CS35L45_ASP_TX_HIZ_DISABLED 0x2
/*
* cirrus,boost-low-power-mode
*
* BST_LPMODE_NO_REACTION: No reaction
* BST_LPMODE_DCM_MODE: Force boost DCM low power mode
* BST_LPMODE_STATIC_BYPASS: Force boost static bypass
*/
#define CS35L45_BST_LPMODE_NO_REACTION 0x0
#define CS35L45_BST_LPMODE_DCM_MODE 0x1
#define CS35L45_BST_LPMODE_STATIC_BYPASS 0x2
/*
* cirrus,amplifier-low-power-mode
*
* AMP_LPMODE_NG_MODE: Noise gate mode
* AMP_LPMODE_NFR_MODE: Noise floor reduction mode
*/
#define CS35L45_AMP_LPMODE_NG_MODE 0x0
#define CS35L45_AMP_LPMODE_NFR_MODE 0x1
/*
* cirrus,ldpm-groupX-pcm-threshold-db
*
* LDPM_PCM_THLD_TRUE_ZERO:
*/
#define CS35L45_LDPM_PCM_THLD_TRUE_ZERO -2147483648
/*
* Optional GPIOX Sub-nodes:
* The cs35l45 node can have up to three "cirrus,gpio-ctrlX" ('X' = [1,2,3])
@@ -156,6 +156,58 @@
#define LPI_MI2S_TX_5 150
#define LPI_MI2S_RX_6 151
#define LPI_MI2S_TX_6 152
#define AIF_MI2S_RX_0 153
#define AIF_MI2S_TX_0 154
#define AIF_MI2S_RX_1 155
#define AIF_MI2S_TX_1 156
#define AIF_MI2S_RX_2 157
#define AIF_MI2S_TX_2 158
#define AIF_MI2S_RX_3 159
#define AIF_MI2S_TX_3 160
#define AIF_MI2S_RX_4 161
#define AIF_MI2S_TX_4 162
#define AIF_MI2S_RX_5 163
#define AIF_MI2S_TX_5 164
#define AIF_MI2S_RX_6 165
#define AIF_MI2S_TX_6 166
#define AIF_MI2S_RX_7 167
#define AIF_MI2S_TX_7 168
#define AIF_MI2S_RX_8 169
#define AIF_MI2S_TX_8 170
#define AIF_MI2S_RX_9 171
#define AIF_MI2S_TX_9 172
#define AIF_MI2S_RX_10 173
#define AIF_MI2S_TX_10 174
#define AIF_MI2S_RX_11 175
#define AIF_MI2S_TX_11 176
#define AIF_MI2S_RX_12 177
#define AIF_MI2S_TX_12 178
#define AIF_TDM_RX_0 179
#define AIF_TDM_TX_0 180
#define AIF_TDM_RX_1 181
#define AIF_TDM_TX_1 182
#define AIF_TDM_RX_2 183
#define AIF_TDM_TX_2 184
#define AIF_TDM_RX_3 185
#define AIF_TDM_TX_3 186
#define AIF_TDM_RX_4 187
#define AIF_TDM_TX_4 188
#define AIF_TDM_RX_5 189
#define AIF_TDM_TX_5 190
#define AIF_TDM_RX_6 191
#define AIF_TDM_TX_6 192
#define AIF_TDM_RX_7 193
#define AIF_TDM_TX_7 194
#define AIF_TDM_RX_8 195
#define AIF_TDM_TX_8 196
#define AIF_TDM_RX_9 197
#define AIF_TDM_TX_9 198
#define AIF_TDM_RX_10 199
#define AIF_TDM_TX_10 200
#define AIF_TDM_RX_11 201
#define AIF_TDM_TX_11 202
#define AIF_TDM_RX_12 203
#define AIF_TDM_TX_12 204
#define LPASS_CLK_ID_PRI_MI2S_IBIT 1
#define LPASS_CLK_ID_PRI_MI2S_EBIT 2
-9
View File
@@ -1760,15 +1760,6 @@ void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
#define dma_request_channel(mask, x, y) \
__dma_request_channel(&(mask), x, y, NULL)
/* Deprecated, please use dma_request_chan() directly */
static inline struct dma_chan * __deprecated
dma_request_slave_channel(struct device *dev, const char *name)
{
struct dma_chan *ch = dma_request_chan(dev, name);
return IS_ERR(ch) ? NULL : ch;
}
static inline struct dma_chan
*dma_request_slave_channel_compat(const dma_cap_mask_t mask,
dma_filter_fn fn, void *fn_param,
+1 -1
View File
@@ -96,7 +96,7 @@ struct cs_dsp_alg_region {
struct cs_dsp_coeff_ctl {
struct list_head list;
struct cs_dsp *dsp;
void *cache;
void *cache __counted_by_ptr(len);
const char *fw_name;
/* Subname is needed to match with firmware */
const char *subname;
+6 -2
View File
@@ -449,6 +449,11 @@
#define AW88399_NOISE_GATE_EN_MASK \
(~(((1<<AW88399_NOISE_GATE_EN_BITS_LEN)-1) << AW88399_NOISE_GATE_EN_START_BIT))
#define AW88399_EPS_EN_START_BIT (2)
#define AW88399_EPS_EN_BITS_LEN (1)
#define AW88399_EPS_EN_MASK \
(~(((1 << AW88399_EPS_EN_BITS_LEN) - 1) << AW88399_EPS_EN_START_BIT))
#define AW88399_WDT_CNT_START_BIT (0)
#define AW88399_WDT_CNT_BITS_LEN (8)
#define AW88399_WDT_CNT_MASK \
@@ -598,7 +603,6 @@ struct aw88399 {
unsigned int crc_init_val;
unsigned int vcalb_init_val;
unsigned int dither_st;
bool bsts_unreliable;
bool fw_needs_reload;
};
@@ -613,7 +617,7 @@ void aw88399_dev_set_channel(struct aw88399 *aw88399, int channel);
void aw88399_hw_reset(struct aw88399 *aw88399);
int aw88399_init(struct aw88399 *aw88399, struct i2c_client *i2c, struct regmap *regmap);
extern const struct regmap_config aw88399_remap_config;
int aw88399_request_firmware_file(struct aw88399 *aw88399);
int aw88399_request_firmware_file(struct aw88399 *aw88399, const char *fw_name);
void aw88399_start(struct aw88399 *aw88399, bool sync_start);
void aw88399_startup_work(struct work_struct *work);
int aw88399_stop(struct aw_device *aw_dev);
+2
View File
@@ -188,6 +188,7 @@ struct snd_compr_ops {
* @card: sound card pointer
* @direction: Playback or capture direction
* @lock: device lock
* @open_list: list of open compress files
* @device: device id
* @use_pause_in_draining: allow pause in draining, true when set
*/
@@ -199,6 +200,7 @@ struct snd_compr {
struct snd_card *card;
unsigned int direction;
struct mutex lock;
struct list_head open_list;
int device;
bool use_pause_in_draining;
#ifdef CONFIG_SND_VERBOSE_PROCFS
+2 -2
View File
@@ -244,7 +244,7 @@ int _snd_ctl_add_follower(struct snd_kcontrol *master,
* @follower: follower element to add
*
* Add a virtual follower control to the given master element created via
* snd_ctl_create_virtual_master() beforehand.
* snd_ctl_make_virtual_master() beforehand.
*
* All followers must be the same type (returning the same information
* via info callback). The function doesn't check it, so it's your
@@ -289,7 +289,7 @@ snd_ctl_add_follower_uncached(struct snd_kcontrol *master,
return _snd_ctl_add_follower(master, follower, SND_CTL_FOLLOWER_NEED_UPDATE);
}
int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
int snd_ctl_add_vmaster_hook(struct snd_card *card, struct snd_kcontrol *kctl,
void (*hook)(void *private_data, int),
void *private_data);
void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only);
+3 -2
View File
@@ -84,6 +84,7 @@ struct snd_device {
struct snd_refcount {
atomic_t count;
wait_queue_head_t waiter;
spinlock_t lock;
};
void snd_refcount_init(struct snd_refcount *ref);
@@ -300,7 +301,8 @@ int snd_card_locked(int card);
#define SND_MIXER_OSS_NOTIFY_REGISTER 0
#define SND_MIXER_OSS_NOTIFY_DISCONNECT 1
#define SND_MIXER_OSS_NOTIFY_FREE 2
extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
void snd_mixer_oss_set_notify(int (*callback)(struct snd_card *card, int cmd));
void snd_mixer_oss_notify(struct snd_card *card, int cmd);
#endif
int snd_card_new(struct device *parent, int idx, const char *xid,
@@ -314,7 +316,6 @@ void snd_card_disconnect(struct snd_card *card);
void snd_card_disconnect_sync(struct snd_card *card);
void snd_card_free(struct snd_card *card);
void snd_card_free_when_closed(struct snd_card *card);
int snd_card_free_on_error(struct device *dev, int ret);
void snd_card_set_id(struct snd_card *card, const char *id);
int snd_card_register(struct snd_card *card);
int snd_card_info_init(void);
+2 -2
View File
@@ -633,8 +633,8 @@ SUB_REG(PEFE, FILTERAMOUNT, 0x000000ff) /* Filter envlope amount */
#define A_ADCCR_RCHANENABLE 0x00000020
#define A_ADCCR_LCHANENABLE 0x00000010
#define A_ADCCR_SAMPLERATE_MASK 0x0000000F /* Audigy sample rate convertor output rate */
#define ADCCR_SAMPLERATE_MASK 0x00000007 /* Sample rate convertor output rate */
#define A_ADCCR_SAMPLERATE_MASK 0x0000000F /* Audigy sample rate converter output rate */
#define ADCCR_SAMPLERATE_MASK 0x00000007 /* Sample rate converter output rate */
#define ADCCR_SAMPLERATE_48 0x00000000 /* 48kHz sample rate */
#define ADCCR_SAMPLERATE_44 0x00000001 /* 44.1kHz sample rate */
#define ADCCR_SAMPLERATE_32 0x00000002 /* 32kHz sample rate */
+1 -1
View File
@@ -5,7 +5,7 @@
/*
* Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
*
* Definitions of OSS compatible headers for Emu8000 device informations
* Definitions of OSS compatible headers for Emu8000 device information
*/
#include <sound/seq_oss_legacy.h>
+4 -2
View File
@@ -28,6 +28,7 @@ struct hda_codec;
struct hda_pcm;
struct hda_pcm_stream;
struct hda_codec_ops;
struct hda_jack_tbl;
/*
* codec bus
@@ -274,7 +275,8 @@ struct hda_codec {
struct hda_codec *codec, hda_nid_t nid);
/* jack detection */
struct snd_array jacktbl;
struct hda_jack_tbl *jacktbl, *jacktbl_last; /* linked list head/tail */
int jacktbl_used; /* number of jacktbl elements */
unsigned long jackpoll_interval; /* In jiffies. Zero means no poll, rely on unsol events */
struct delayed_work jackpoll_work;
@@ -519,7 +521,7 @@ void snd_hda_update_power_acct(struct hda_codec *codec);
static inline bool hda_codec_need_resume(struct hda_codec *codec)
{
return !codec->relaxed_resume && codec->jacktbl.used;
return !codec->relaxed_resume && codec->jacktbl_used;
}
/*
+7 -5
View File
@@ -96,7 +96,8 @@ struct hdac_device {
bool lazy_cache:1; /* don't wake up for writes */
bool caps_overwriting:1; /* caps overwrite being in process */
bool cache_coef:1; /* cache COEF read/write too */
unsigned int registered:1; /* codec was registered */
bool registered; /* codec was registered */
bool unsol_disabled; /* unsol events blocked; protected by bus->reg_lock */
};
/* device/driver type used for matching */
@@ -123,6 +124,7 @@ int snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus,
const char *name, unsigned int addr);
void snd_hdac_device_exit(struct hdac_device *dev);
int snd_hdac_device_register(struct hdac_device *codec);
void snd_hdac_device_disable_unsol(struct hdac_device *codec);
void snd_hdac_device_unregister(struct hdac_device *codec);
int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name);
int snd_hdac_codec_modalias(const struct hdac_device *hdac, char *buf, size_t size);
@@ -179,9 +181,9 @@ static inline int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid,
#ifdef CONFIG_PM
int snd_hdac_power_up(struct hdac_device *codec);
int snd_hdac_power_down(struct hdac_device *codec);
void snd_hdac_power_down(struct hdac_device *codec);
int snd_hdac_power_up_pm(struct hdac_device *codec);
int snd_hdac_power_down_pm(struct hdac_device *codec);
void snd_hdac_power_down_pm(struct hdac_device *codec);
int snd_hdac_keep_power_up(struct hdac_device *codec);
/* call this at entering into suspend/resume callbacks in codec driver */
@@ -207,9 +209,9 @@ static inline bool snd_hdac_is_power_on(struct hdac_device *codec)
}
#else
static inline int snd_hdac_power_up(struct hdac_device *codec) { return 0; }
static inline int snd_hdac_power_down(struct hdac_device *codec) { return 0; }
static inline void snd_hdac_power_down(struct hdac_device *codec) {}
static inline int snd_hdac_power_up_pm(struct hdac_device *codec) { return 0; }
static inline int snd_hdac_power_down_pm(struct hdac_device *codec) { return 0; }
static inline void snd_hdac_power_down_pm(struct hdac_device *codec) {}
static inline int snd_hdac_keep_power_up(struct hdac_device *codec) { return 0; }
static inline void snd_hdac_enter_pm(struct hdac_device *codec) {}
static inline void snd_hdac_leave_pm(struct hdac_device *codec) {}
+1 -1
View File
@@ -62,10 +62,10 @@ struct snd_jack {
struct list_head kctl_list;
struct snd_card *card;
const char *id;
bool registered;
#ifdef CONFIG_SND_JACK_INPUT_DEV
struct input_dev *input_dev;
struct mutex input_dev_lock;
int registered;
int type;
char name[100];
unsigned int key[6]; /* Keep in sync with definitions above */
+2
View File
@@ -8,6 +8,7 @@
* Abramo Bagnara <abramo@alsa-project.org>
*/
#include <sound/core.h>
#include <sound/asound.h>
#include <sound/memalloc.h>
#include <sound/minors.h>
@@ -414,6 +415,7 @@ struct snd_pcm_runtime {
snd_pcm_uframes_t twake; /* do transfer (!poll) wakeup if non-zero */
wait_queue_head_t sleep; /* poll sleep */
wait_queue_head_t tsleep; /* transfer sleep */
struct snd_refcount refcnt; /* refcount for draining, etc */
struct snd_fasync *fasync;
bool stop_operating; /* sync_stop will be called */
struct mutex buffer_mutex; /* protect for buffer changes */
+1
View File
@@ -70,6 +70,7 @@ struct snd_pcm_oss_stream {
struct snd_pcm_oss {
int reg;
unsigned int reg_mask;
bool registered;
};
#endif /* __SOUND_PCM_OSS_H */
+1
View File
@@ -86,6 +86,7 @@ struct snd_rawmidi_substream {
bool opened; /* open flag */
bool append; /* append flag (merge more streams) */
bool active_sensing; /* send active sensing when close */
bool disconnected; /* already disconnected */
unsigned int framing; /* whether to frame input data */
unsigned int clock_type; /* clock source to use for input framing */
int use_count; /* use counter (for output) */
+18 -5
View File
@@ -60,20 +60,16 @@ enum sdca_quirk {
SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING,
};
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA)
#if IS_ENABLED(CONFIG_SND_SOC_SDCA)
void sdca_lookup_functions(struct sdw_slave *slave);
void sdca_lookup_swft(struct sdw_slave *slave);
void sdca_lookup_interface_revision(struct sdw_slave *slave);
bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk);
int sdca_dev_register_functions(struct sdw_slave *slave);
void sdca_dev_unregister_functions(struct sdw_slave *slave);
#else
static inline void sdca_lookup_functions(struct sdw_slave *slave) {}
static inline void sdca_lookup_swft(struct sdw_slave *slave) {}
static inline void sdca_lookup_interface_revision(struct sdw_slave *slave) {}
static inline bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk)
{
return false;
@@ -88,4 +84,21 @@ static inline void sdca_dev_unregister_functions(struct sdw_slave *slave) {}
#endif
/*
* Called from the SoundWire bus during peripheral enumeration; gated on
* ACPI to avoid a soundwire_bus <-> snd_soc_sdca module cycle on DT builds
* (where the bodies are stubs anyway).
*/
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA)
void sdca_lookup_functions(struct sdw_slave *slave);
void sdca_lookup_interface_revision(struct sdw_slave *slave);
#else
static inline void sdca_lookup_functions(struct sdw_slave *slave) {}
static inline void sdca_lookup_interface_revision(struct sdw_slave *slave) {}
#endif
#endif
+70
View File
@@ -0,0 +1,70 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* The MIPI SDCA specification is available for public downloads at
* https://www.mipi.org/mipi-sdca-v1-0-download
*
* Copyright (C) 2025 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*/
#ifndef __SDCA_CLASS_H__
#define __SDCA_CLASS_H__
#include <linux/completion.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
struct device;
struct regmap;
struct sdw_slave;
struct sdca_function_data;
/**
* struct sdca_class_ops - optional codec-provided class callbacks
* @populate_function: fill @function (entities, clusters, init_table, ...)
* from static tables in place of sdca_parse_function() on
* DT/non-DisCo platforms. Called once per SDCA function with
* @dev pointing at that function's device. Pure data source;
* performs no bus I/O. Return 0 on success or a negative errno.
*/
struct sdca_class_ops {
int (*populate_function)(struct device *dev,
struct sdca_function_data *function);
};
struct sdca_class_drv {
struct device *dev;
struct regmap *dev_regmap;
struct sdw_slave *sdw;
struct sdca_interrupt_info *irq_info;
const struct sdca_class_ops *ops;
struct mutex regmap_lock;
/* Serialise function initialisations */
struct mutex init_lock;
struct work_struct boot_work;
};
/* Library helpers used by codec-specific SDCA SoundWire drivers. */
int sdca_class_probe(struct sdw_slave *sdw,
struct sdca_class_drv *drv,
const struct sdca_class_ops *ops);
void sdca_class_remove(struct sdca_class_drv *drv);
/*
* PM helpers. Codec drivers embed sdca_class_drv in their own priv,
* own dev_set_drvdata(), and compose these into their own dev_pm_ops:
*
* static int wcd_runtime_suspend(struct device *dev) {
* struct wcd_priv *priv = dev_get_drvdata(dev);
* return sdca_class_runtime_suspend(&priv->class);
* }
*/
int sdca_class_runtime_suspend(struct sdca_class_drv *drv);
int sdca_class_runtime_resume(struct sdca_class_drv *drv);
int sdca_class_system_suspend(struct sdca_class_drv *drv);
int sdca_class_system_resume(struct sdca_class_drv *drv);
#endif /* __SDCA_CLASS_H__ */
+2
View File
@@ -219,12 +219,14 @@ static inline int simple_util_parse_aux_devs(struct simple_util_priv *priv, char
int simple_util_init_jack(struct snd_soc_card *card,
struct simple_util_jack *sjack,
int is_hp, char *prefix, char *pin);
void simple_util_remove_jack(struct simple_util_jack *sjack);
int simple_util_init_aux_jacks(struct snd_soc_card *card, char *prefix);
int simple_util_init_priv(struct simple_util_priv *priv,
struct link_info *li);
void simple_util_remove(struct platform_device *pdev);
int graph_util_card_probe(struct snd_soc_card *card);
int graph_util_card_remove(struct snd_soc_card *card);
int graph_util_is_ports0(struct device_node *port);
int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep,
struct snd_soc_dai_link_component *dlc, int *is_single_link);
+41 -41
View File
@@ -154,6 +154,8 @@ struct snd_soc_component_driver {
struct snd_pcm_substream *substream);
snd_pcm_sframes_t (*delay)(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
const struct snd_compress_ops *compress_ops;
@@ -194,12 +196,13 @@ struct snd_soc_component_driver {
unsigned int endianness:1;
unsigned int legacy_dai_naming:1;
/* use DAI link PCM ID as PCM device number */
unsigned int use_dai_pcm_id:1;
/* this component uses topology and ignore machine driver FEs */
const char *ignore_machine;
const char *topology_name_prefix;
int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
bool use_dai_pcm_id; /* use DAI link PCM ID as PCM device number */
int be_pcm_base; /* base device ID for all BE PCMs */
const char *debugfs_prefix;
@@ -258,37 +261,24 @@ struct snd_soc_component {
void *priv;
};
#define for_each_component_dais(component, dai)\
list_for_each_entry(dai, &(component)->dai_list, list)
#define for_each_component_dais_safe(component, dai, _dai)\
list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list)
#define for_each_component_dais(component, dai) \
for (dai = snd_soc_dai_from_list((component)->dai_list.next); \
snd_soc_dai_to_list(dai) != &(component)->dai_list; \
dai = snd_soc_dai_from_list(snd_soc_dai_to_list(dai)->next))
/**
* snd_soc_component_to_dapm() - Returns the DAPM context associated with a
* component
* @component: The component for which to get the DAPM context
*/
static inline struct snd_soc_dapm_context *snd_soc_component_to_dapm(
struct snd_soc_component *component)
{
return component->dapm;
}
#define for_each_component_dais_safe(component, dai, _dai) \
for (dai = snd_soc_dai_from_list((component)->dai_list.next), \
_dai = snd_soc_dai_from_list(snd_soc_dai_to_list(dai)->next); \
snd_soc_dai_to_list(dai) != &(component)->dai_list; \
dai = _dai, _dai = snd_soc_dai_from_list(snd_soc_dai_to_list(_dai)->next))
/**
* snd_soc_component_cache_sync() - Sync the register cache with the hardware
* @component: COMPONENT to sync
*
* Note: This function will call regcache_sync()
*/
static inline int snd_soc_component_cache_sync(
struct snd_soc_component *component)
{
return regcache_sync(component->regmap);
}
struct snd_soc_dapm_context *snd_soc_component_to_dapm(struct snd_soc_component *component);
struct snd_soc_component *snd_soc_component_new(struct device *dev, const char *name,
const struct snd_soc_component_driver *driver);
int snd_soc_component_register(struct snd_soc_component *component,
struct snd_soc_dai_driver *dai_drv,
int num_dai);
struct snd_soc_component *snd_soc_component_alloc(struct device *dev);
void snd_soc_component_set_name(struct snd_soc_component *component, const char *name);
const char *snd_soc_component_name(struct snd_soc_component *component);
void snd_soc_component_set_priv(struct snd_soc_component *component, void *priv);
@@ -299,6 +289,11 @@ void snd_soc_component_set_aux(struct snd_soc_component *component,
int snd_soc_component_init(struct snd_soc_component *component);
int snd_soc_component_is_dummy(struct snd_soc_component *component);
struct snd_soc_component *snd_soc_component_lookup_nolock(struct device *dev,
const char *driver_name);
struct snd_soc_component *snd_soc_component_lookup(struct device *dev, const char *driver_name);
struct snd_soc_component *snd_soc_component_lookup_by_name(const char *component_name);
/* component IO */
unsigned int snd_soc_component_read(struct snd_soc_component *component,
unsigned int reg);
@@ -310,7 +305,6 @@ int snd_soc_component_update_bits(struct snd_soc_component *component,
int snd_soc_component_update_bits_async(struct snd_soc_component *component,
unsigned int reg, unsigned int mask,
unsigned int val);
void snd_soc_component_async_complete(struct snd_soc_component *component);
int snd_soc_component_test_bits(struct snd_soc_component *component,
unsigned int reg, unsigned int mask,
unsigned int value);
@@ -340,12 +334,18 @@ int snd_soc_component_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level);
int snd_soc_component_regmap_val_bytes(struct snd_soc_component *component);
int snd_soc_component_regmap_cache_sync(struct snd_soc_component *component);
void snd_soc_component_regmap_async_complete(struct snd_soc_component *component);
#ifdef CONFIG_REGMAP
void snd_soc_component_init_regmap(struct snd_soc_component *component,
struct regmap *regmap);
void snd_soc_component_exit_regmap(struct snd_soc_component *component);
#endif
int snd_soc_component_fixup_controls(struct snd_soc_component *component);
int snd_soc_component_add_controls(struct snd_soc_component *component,
const struct snd_kcontrol_new *controls, unsigned int num_controls);
#define snd_soc_component_module_get_when_probe(component)\
snd_soc_component_module_get(component, NULL, 0)
#define snd_soc_component_module_get_when_open(component, substream) \
@@ -370,11 +370,7 @@ static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c)
return dev_get_drvdata(c->dev);
}
static inline unsigned int
snd_soc_component_active(struct snd_soc_component *component)
{
return component->active;
}
unsigned int snd_soc_component_active(struct snd_soc_component *component);
/* component controls */
struct snd_kcontrol *snd_soc_component_get_kcontrol(struct snd_soc_component *component,
@@ -391,9 +387,6 @@ int snd_soc_component_close(struct snd_soc_component *component,
void snd_soc_component_suspend(struct snd_soc_component *component);
void snd_soc_component_resume(struct snd_soc_component *component);
int snd_soc_component_is_suspended(struct snd_soc_component *component);
int snd_soc_component_probe(struct snd_soc_component *component);
int snd_soc_component_fixup_controls(struct snd_soc_component *component);
void snd_soc_component_remove(struct snd_soc_component *component);
int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
struct device_node *ep);
int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
@@ -423,7 +416,7 @@ int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream,
int snd_soc_component_compr_get_metadata(struct snd_compr_stream *cstream,
struct snd_compr_metadata *metadata);
int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream);
snd_pcm_uframes_t snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream);
int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg);
int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream);
@@ -451,4 +444,11 @@ int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream);
void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream,
snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay);
/* REMOVE ME */
#define snd_soc_component_cache_sync snd_soc_component_regmap_cache_sync
#define snd_soc_component_async_complete snd_soc_component_regmap_async_complete
#define snd_soc_lookup_component_nolocked snd_soc_component_lookup_nolock
#define snd_soc_lookup_component snd_soc_component_lookup
#define snd_soc_lookup_component_by_name snd_soc_component_lookup_by_name
#endif /* __SOC_COMPONENT_H */
+78 -101
View File
@@ -212,8 +212,11 @@ int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai,
unsigned int *tx_num, unsigned int *tx_slot,
unsigned int *rx_num, unsigned int *rx_slot);
struct snd_soc_component *snd_soc_dai_to_component(const struct snd_soc_dai *dai);
struct snd_soc_dai_driver *snd_soc_dai_to_driver(const struct snd_soc_dai *dai);
int snd_soc_dai_is_dummy(const struct snd_soc_dai *dai);
int snd_soc_dai_add_controls(struct snd_soc_dai *dai,
const struct snd_kcontrol_new *controls, int num_controls);
int snd_soc_dai_hw_params(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
@@ -228,18 +231,7 @@ void snd_soc_dai_suspend(struct snd_soc_dai *dai);
void snd_soc_dai_resume(struct snd_soc_dai *dai);
int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd);
bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int stream);
void snd_soc_dai_action(struct snd_soc_dai *dai,
int stream, int action);
static inline void snd_soc_dai_activate(struct snd_soc_dai *dai,
int stream)
{
snd_soc_dai_action(dai, stream, 1);
}
static inline void snd_soc_dai_deactivate(struct snd_soc_dai *dai,
int stream)
{
snd_soc_dai_action(dai, stream, -1);
}
int snd_soc_dai_active(const struct snd_soc_dai *dai);
int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order);
@@ -277,7 +269,12 @@ int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream,
struct snd_compr_metadata *metadata);
const char *snd_soc_dai_name_get(const struct snd_soc_dai *dai);
int snd_soc_dai_matches_args(const struct snd_soc_dai *dai,
const struct of_phandle_args *args2);
int snd_soc_dai_matches_dlc(struct snd_soc_dai *dai,
const struct snd_soc_dai_link_component *dlc);
const char *snd_soc_dai_name(const struct snd_soc_dai *dai);
int snd_soc_dai_id(const struct snd_soc_dai *dai);
struct snd_soc_dai_ops {
/* DAI driver callbacks */
@@ -489,69 +486,51 @@ struct snd_soc_dai {
void *priv;
};
const struct snd_soc_pcm_stream *
snd_soc_dai_pcm_stream_get_i(const struct snd_soc_dai *dai, int stream);
static inline const struct snd_soc_pcm_stream *
snd_soc_dai_get_pcm_stream(const struct snd_soc_dai *dai, int stream)
snd_soc_dai_pcm_stream_get_s(const struct snd_soc_dai *dai, struct snd_pcm_substream *substream)
{
return (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
&dai->driver->playback : &dai->driver->capture;
return snd_soc_dai_pcm_stream_get_i(dai, substream->stream);
}
#define snd_soc_dai_pcm_stream_get(dai, x) _Generic((x), \
int : snd_soc_dai_pcm_stream_get_i, \
struct snd_pcm_substream * : snd_soc_dai_pcm_stream_get_s)(dai, x)
#define snd_soc_dai_get_widget_playback(dai) snd_soc_dai_get_widget(dai, SNDRV_PCM_STREAM_PLAYBACK)
#define snd_soc_dai_get_widget_capture(dai) snd_soc_dai_get_widget(dai, SNDRV_PCM_STREAM_CAPTURE)
static inline
struct snd_soc_dapm_widget *snd_soc_dai_get_widget(struct snd_soc_dai *dai, int stream)
{
return dai->stream[stream].widget;
}
#define snd_soc_dai_stream_widget_get_playback(dai) snd_soc_dai_stream_widget_get(dai, SNDRV_PCM_STREAM_PLAYBACK)
#define snd_soc_dai_stream_widget_get_capture(dai) snd_soc_dai_stream_widget_get(dai, SNDRV_PCM_STREAM_CAPTURE)
struct snd_soc_dapm_widget *snd_soc_dai_stream_widget_get(struct snd_soc_dai *dai, int stream);
#define snd_soc_dai_set_widget_playback(dai, widget) snd_soc_dai_set_widget(dai, SNDRV_PCM_STREAM_PLAYBACK, widget)
#define snd_soc_dai_set_widget_capture(dai, widget) snd_soc_dai_set_widget(dai, SNDRV_PCM_STREAM_CAPTURE, widget)
static inline
void snd_soc_dai_set_widget(struct snd_soc_dai *dai, int stream, struct snd_soc_dapm_widget *widget)
{
dai->stream[stream].widget = widget;
}
#define snd_soc_dai_stream_widget_set_playback(dai, widget) snd_soc_dai_stream_widget_set(dai, SNDRV_PCM_STREAM_PLAYBACK, widget)
#define snd_soc_dai_stream_widget_set_capture(dai, widget) snd_soc_dai_stream_widget_set(dai, SNDRV_PCM_STREAM_CAPTURE, widget)
void snd_soc_dai_stream_widget_set(struct snd_soc_dai *dai, int stream, struct snd_soc_dapm_widget *widget);
#define snd_soc_dai_dma_data_get_playback(dai) snd_soc_dai_dma_data_get(dai, SNDRV_PCM_STREAM_PLAYBACK)
#define snd_soc_dai_dma_data_get_capture(dai) snd_soc_dai_dma_data_get(dai, SNDRV_PCM_STREAM_CAPTURE)
#define snd_soc_dai_get_dma_data(dai, ss) snd_soc_dai_dma_data_get(dai, ss->stream)
static inline void *snd_soc_dai_dma_data_get(const struct snd_soc_dai *dai, int stream)
#define snd_soc_dai_stream_dma_data_get_playback(dai) snd_soc_dai_stream_dma_data_get(dai, SNDRV_PCM_STREAM_PLAYBACK)
#define snd_soc_dai_stream_dma_data_get_capture(dai) snd_soc_dai_stream_dma_data_get(dai, SNDRV_PCM_STREAM_CAPTURE)
void *snd_soc_dai_stream_dma_data_get_i(const struct snd_soc_dai *dai, int stream);
static inline void *snd_soc_dai_stream_dma_data_get_s(const struct snd_soc_dai *dai, struct snd_pcm_substream *substream)
{
return dai->stream[stream].dma_data;
return snd_soc_dai_stream_dma_data_get_i(dai, substream->stream);
}
#define snd_soc_dai_stream_dma_data_get(dai, x) _Generic((x), \
int : snd_soc_dai_stream_dma_data_get_i, \
struct snd_pcm_substream * : snd_soc_dai_stream_dma_data_get_s)(dai, x)
#define snd_soc_dai_dma_data_set_playback(dai, data) snd_soc_dai_dma_data_set(dai, SNDRV_PCM_STREAM_PLAYBACK, data)
#define snd_soc_dai_dma_data_set_capture(dai, data) snd_soc_dai_dma_data_set(dai, SNDRV_PCM_STREAM_CAPTURE, data)
#define snd_soc_dai_set_dma_data(dai, ss, data) snd_soc_dai_dma_data_set(dai, ss->stream, data)
static inline void snd_soc_dai_dma_data_set(struct snd_soc_dai *dai, int stream, void *data)
#define snd_soc_dai_stream_dma_data_set_playback(dai, data) snd_soc_dai_stream_dma_data_set(dai, SNDRV_PCM_STREAM_PLAYBACK, data)
#define snd_soc_dai_stream_dma_data_set_capture(dai, data) snd_soc_dai_stream_dma_data_set(dai, SNDRV_PCM_STREAM_CAPTURE, data)
void snd_soc_dai_stream_dma_data_set_i(struct snd_soc_dai *dai, int stream, void *data);
static inline void snd_soc_dai_stream_dma_data_set_s(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, void *data)
{
dai->stream[stream].dma_data = data;
snd_soc_dai_stream_dma_data_set_i(dai, substream->stream, data);
}
#define snd_soc_dai_stream_dma_data_set(dai, x, data) _Generic((x), \
int : snd_soc_dai_stream_dma_data_set_i, \
struct snd_pcm_substream * : snd_soc_dai_stream_dma_data_set_s)(dai, x, data)
static inline void snd_soc_dai_init_dma_data(struct snd_soc_dai *dai, void *playback, void *capture)
{
snd_soc_dai_dma_data_set_playback(dai, playback);
snd_soc_dai_dma_data_set_capture(dai, capture);
}
unsigned int snd_soc_dai_stream_tdm_mask_get(const struct snd_soc_dai *dai, int stream);
void snd_soc_dai_stream_tdm_mask_set(struct snd_soc_dai *dai, int stream, unsigned int tdm_mask);
static inline unsigned int snd_soc_dai_tdm_mask_get(const struct snd_soc_dai *dai,
int stream)
{
return dai->stream[stream].tdm_mask;
}
static inline void snd_soc_dai_tdm_mask_set(struct snd_soc_dai *dai, int stream,
unsigned int tdm_mask)
{
dai->stream[stream].tdm_mask = tdm_mask;
}
static inline unsigned int snd_soc_dai_stream_active(const struct snd_soc_dai *dai,
int stream)
{
/* see snd_soc_dai_action() for setup */
return dai->stream[stream].active;
}
unsigned int snd_soc_dai_stream_active(const struct snd_soc_dai *dai, int stream);
static inline void snd_soc_dai_set_drvdata(struct snd_soc_dai *dai,
void *data)
@@ -564,45 +543,43 @@ static inline void *snd_soc_dai_get_drvdata(struct snd_soc_dai *dai)
return dev_get_drvdata(dai->dev);
}
/**
* snd_soc_dai_set_stream() - Configures a DAI for stream operation
* @dai: DAI
* @stream: STREAM (opaque structure depending on DAI type)
* @direction: Stream direction(Playback/Capture)
* Some subsystems, such as SoundWire, don't have a notion of direction and we reuse
* the ASoC stream direction to configure sink/source ports.
* Playback maps to source ports and Capture for sink ports.
*
* This should be invoked with NULL to clear the stream set previously.
* Returns 0 on success, a negative error code otherwise.
*/
static inline int snd_soc_dai_set_stream(struct snd_soc_dai *dai,
void *stream, int direction)
{
if (dai->driver->ops->set_stream)
return dai->driver->ops->set_stream(dai, stream, direction);
else
return -ENOTSUPP;
}
int snd_soc_dai_set_stream(struct snd_soc_dai *dai, void *stream, int direction);
void *snd_soc_dai_get_stream(struct snd_soc_dai *dai, int direction);
/**
* snd_soc_dai_get_stream() - Retrieves stream from DAI
* @dai: DAI
* @direction: Stream direction(Playback/Capture)
*
* This routine only retrieves that was previously configured
* with snd_soc_dai_get_stream()
*
* Returns pointer to stream or an ERR_PTR value, e.g.
* ERR_PTR(-ENOTSUPP) if callback is not supported;
*/
static inline void *snd_soc_dai_get_stream(struct snd_soc_dai *dai,
int direction)
struct snd_soc_dai *snd_soc_dai_register(struct snd_soc_component *component,
struct snd_soc_dai_driver *dai_drv,
bool legacy_dai_naming);
void snd_soc_dai_unregister(struct snd_soc_dai *dai);
struct snd_soc_dai *snd_soc_dai_from_list(struct list_head *list);
struct list_head *snd_soc_dai_to_list(struct snd_soc_dai *dai);
unsigned int snd_soc_dai_get_symmetric_rate(struct snd_soc_dai *dai);
unsigned int snd_soc_dai_get_symmetric_channels(struct snd_soc_dai *dai);
unsigned int snd_soc_dai_get_symmetric_sample_bits(struct snd_soc_dai *dai);
void snd_soc_dai_set_priv(struct snd_soc_dai *dai, void *priv);
void *snd_soc_dai_to_priv(struct snd_soc_dai *dai);
/* REMOVE ME */
#define snd_soc_dai_get_pcm_stream snd_soc_dai_pcm_stream_get
#define snd_soc_dai_get_widget_playback(dai) snd_soc_dai_stream_widget_get(dai, SNDRV_PCM_STREAM_PLAYBACK)
#define snd_soc_dai_get_widget_capture(dai) snd_soc_dai_stream_widget_get(dai, SNDRV_PCM_STREAM_CAPTURE)
#define snd_soc_dai_get_widget snd_soc_dai_stream_widget_get
#define snd_soc_dai_set_widget_playback(dai, widget) snd_soc_dai_stream_widget_set(dai, SNDRV_PCM_STREAM_PLAYBACK, widget)
#define snd_soc_dai_set_widget_capture(dai, widget) snd_soc_dai_stream_widget_set(dai, SNDRV_PCM_STREAM_CAPTURE, widget)
#define snd_soc_dai_set_widget snd_soc_dai_stream_widget_set
#define snd_soc_dai_dma_data_get_playback(dai) snd_soc_dai_stream_dma_data_get(dai, SNDRV_PCM_STREAM_PLAYBACK)
#define snd_soc_dai_dma_data_get_capture(dai) snd_soc_dai_stream_dma_data_get(dai, SNDRV_PCM_STREAM_CAPTURE)
#define snd_soc_dai_get_dma_data snd_soc_dai_stream_dma_data_get
#define snd_soc_dai_dma_data_get snd_soc_dai_stream_dma_data_get
#define snd_soc_dai_dma_data_set_playback(dai, data) snd_soc_dai_stream_dma_data_set(dai, SNDRV_PCM_STREAM_PLAYBACK, data)
#define snd_soc_dai_dma_data_set_capture(dai, data) snd_soc_dai_stream_dma_data_set(dai, SNDRV_PCM_STREAM_CAPTURE, data)
#define snd_soc_dai_set_dma_data snd_soc_dai_stream_dma_data_set
#define snd_soc_dai_dma_data_set snd_soc_dai_stream_dma_data_set
#define snd_soc_dai_tdm_mask_get snd_soc_dai_stream_tdm_mask_get
#define snd_soc_dai_tdm_mask_set snd_soc_dai_stream_tdm_mask_set
static inline void snd_soc_dai_init_dma_data(struct snd_soc_dai *dai, void *playback, void *capture)
{
if (dai->driver->ops->get_stream)
return dai->driver->ops->get_stream(dai, direction);
else
return ERR_PTR(-ENOTSUPP);
snd_soc_dai_stream_dma_data_set_playback(dai, playback);
snd_soc_dai_stream_dma_data_set_capture(dai, capture);
}
#endif
+12 -23
View File
@@ -447,15 +447,9 @@ static inline int snd_soc_resume(struct device *dev)
}
#endif
int snd_soc_poweroff(struct device *dev);
int snd_soc_register_component_c(struct snd_soc_component *component,
const struct snd_soc_component_driver *component_driver,
struct snd_soc_dai_driver *dai_drv, int num_dai);
int snd_soc_register_component_d(struct device *dev,
int snd_soc_register_component(struct device *dev,
const struct snd_soc_component_driver *component_driver,
struct snd_soc_dai_driver *dai_drv, int num_dai);
#define snd_soc_register_component(x, ...) _Generic((x), \
struct device * : snd_soc_register_component_d, \
struct snd_soc_component * : snd_soc_register_component_c)(x, __VA_ARGS__)
int devm_snd_soc_register_component(struct device *dev,
const struct snd_soc_component_driver *component_driver,
@@ -463,11 +457,6 @@ int devm_snd_soc_register_component(struct device *dev,
#define snd_soc_unregister_component(dev) snd_soc_unregister_component_by_driver(dev, NULL)
void snd_soc_unregister_component_by_driver(struct device *dev,
const struct snd_soc_component_driver *component_driver);
struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev,
const char *driver_name);
struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
const char *driver_name);
struct snd_soc_component *snd_soc_lookup_component_by_name(const char *component_name);
int soc_new_pcm(struct snd_soc_pcm_runtime *rtd);
#ifdef CONFIG_SND_SOC_COMPRESS
@@ -551,12 +540,8 @@ static inline int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops)
struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
void *data, const char *long_name,
const char *prefix);
int snd_soc_add_component_controls(struct snd_soc_component *component,
const struct snd_kcontrol_new *controls, unsigned int num_controls);
int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
const struct snd_kcontrol_new *controls, int num_controls);
int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
const struct snd_kcontrol_new *controls, int num_controls);
int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
@@ -1331,6 +1316,9 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np,
unsigned int *rx_mask,
unsigned int *slots,
unsigned int *slot_width);
int snd_soc_of_xlate_dai_name(struct snd_soc_component *component,
const struct of_phandle_args *args,
const char **dai_name);
void snd_soc_of_parse_node_prefix(struct device_node *np,
struct snd_soc_codec_conf *codec_conf,
struct device_node *of_node,
@@ -1389,19 +1377,12 @@ void snd_soc_dlc_use_cpu_as_platform(struct snd_soc_dai_link_component *platform
struct of_phandle_args *snd_soc_copy_dai_args(struct device *dev,
const struct of_phandle_args *args);
struct snd_soc_dai *snd_soc_get_dai_via_args(const struct of_phandle_args *dai_args);
struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component,
struct snd_soc_dai_driver *dai_drv,
bool legacy_dai_naming);
void snd_soc_unregister_dai(struct snd_soc_dai *dai);
struct snd_soc_dai *snd_soc_find_dai(
const struct snd_soc_dai_link_component *dlc);
struct snd_soc_dai *snd_soc_find_dai_with_mutex(
const struct snd_soc_dai_link_component *dlc);
void soc_pcm_set_dai_params(struct snd_soc_dai *dai,
struct snd_pcm_hw_params *params);
#include <sound/soc-dai.h>
static inline
@@ -1551,4 +1532,12 @@ static inline void _snd_soc_dpcm_mutex_assert_held_r(struct snd_soc_pcm_runtime
#include <sound/soc-card.h>
#include <sound/soc-jack.h>
/*
* REMOVE ME
*/
#define snd_soc_add_dai_controls snd_soc_dai_add_controls
#define snd_soc_register_dai snd_soc_dai_register
#define snd_soc_unregister_dai snd_soc_dai_unregister
#define snd_soc_add_component_controls snd_soc_component_add_controls
#endif
+20
View File
@@ -292,4 +292,24 @@ int asoc_sdw_es9356_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai
int asoc_sdw_es9356_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_es9356_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
/* Senary SN624x SDCA */
int asoc_sdw_senary_sdca_jack_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
struct asoc_sdw_codec_info *info,
bool playback);
int asoc_sdw_senary_sdca_jack_exit(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link);
int asoc_sdw_senary_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_dai *dai);
int asoc_sdw_senary_amp_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
struct asoc_sdw_codec_info *info,
bool playback);
int asoc_sdw_senary_amp_exit(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link);
int asoc_sdw_senary_sdca_spk_rtd_init(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_dai *dai);
int asoc_sdw_senary_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_dai *dai);
#endif
+16 -8
View File
@@ -436,12 +436,10 @@ enum sof_ipc4_fw_config_params {
SOF_IPC4_FW_CFG_RESERVED,
SOF_IPC4_FW_CFG_POWER_GATING_POLICY,
SOF_IPC4_FW_CFG_ASSERT_MODE,
SOF_IPC4_FW_RESERVED1,
SOF_IPC4_FW_RESERVED2,
SOF_IPC4_FW_RESERVED3,
SOF_IPC4_FW_RESERVED4,
SOF_IPC4_FW_RESERVED5,
SOF_IPC4_FW_CONTEXT_SAVE
/* Reserved: 24 - 28 */
SOF_IPC4_FW_CONTEXT_SAVE = 29,
/* Reserved: 30 - 34 */
SOF_IPC4_FW_CFG_SOF_INFO = 35,
};
struct sof_ipc4_fw_version {
@@ -451,6 +449,14 @@ struct sof_ipc4_fw_version {
uint16_t build;
} __packed;
/*
* tuple based array for SOF specific information under SOF_IPC4_FW_CFG_SOF_INFO
* tuple of fw_config
*/
enum ipc4_fw_sof_info_params {
SOF_IPC4_SOF_CODEC_INFO,
};
/* Payload data for SOF_IPC4_MOD_SET_DX */
struct sof_ipc4_dx_state_info {
/* core(s) to apply the change */
@@ -641,9 +647,10 @@ struct sof_ipc4_notify_module_data {
* The event_data contains the struct sof_ipc4_control_msg_payload of the control
* which sent the notification.
*/
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_MASK GENMASK(31, 16)
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_SOF_MAGIC_MASK GENMASK(31, 16)
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL 0xA15A0000
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_PARAMID_MASK GENMASK(15, 0)
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_COMPR_MAGIC_VAL 0xC0C00000
/*
* Macros for creating struct sof_ipc4_module_init_ext_init payload
@@ -706,7 +713,8 @@ struct sof_ipc4_module_init_ext_object {
enum sof_ipc4_mod_init_ext_obj_id {
SOF_IPC4_MOD_INIT_DATA_ID_INVALID = 0,
SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA,
SOF_IPC4_MOD_INIT_DATA_ID_MAX = SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA,
SOF_IPC4_MOD_INIT_DATA_ID_MODULE_DATA,
SOF_IPC4_MOD_INIT_DATA_ID_MAX = SOF_IPC4_MOD_INIT_DATA_ID_MODULE_DATA,
};
/* DP module memory configuration data object for object array */
+13
View File
@@ -56,6 +56,10 @@ enum tasdevice_dsp_dev_idx {
TASDEVICE_DSP_TAS_2781_QUAD,
TASDEVICE_DSP_TAS_5825_MONO,
TASDEVICE_DSP_TAS_5825_DUAL,
TASDEVICE_DSP_TAS_2573_MONO,
TASDEVICE_DSP_TAS_2573_DUAL,
TASDEVICE_DSP_TAS_2573_21,
TASDEVICE_DSP_TAS_2573_QUAD,
TASDEVICE_DSP_TAS_MAX_DEVICE
};
@@ -142,6 +146,7 @@ struct tasdevice_fw {
struct tasdevice_calibration *calibrations;
struct fct_param_address fct_par_addr;
struct device *dev;
int calibration_config_id;
};
enum tasdevice_fw_state {
@@ -206,6 +211,14 @@ struct tasdevice_rca {
* capture.
*/
int capture_profile_id;
/*
* Primarily designed for speaker calibration scenarios with special
* requirements. For regular use cases, when the default value -1 is
* set, calibration will directly reuse the current playback
* configuration; non-negative values can be customized for special
* calibration demands.
*/
int calibration_profile_id;
/*
* Since version 0x105, the keyword 'init' was introduced into the
* profile, which is used for chip initialization, particularly to
+31
View File
@@ -49,6 +49,13 @@
#define TASDEVICE_REG(book, page, reg) (((book * 256 * 128) + \
(page * 128)) + reg)
#define TAS_REG_ERR_LOG(dev, chn, reg, ret) \
dev_err((dev), "%s, C%uBx%02xPx%02xRx%02x E=%d\n", \
__func__, chn, TASDEVICE_BOOK_ID(reg), \
TASDEVICE_PAGE_ID(reg), \
TASDEVICE_PAGE_REG(reg), \
(ret))
/* Software Reset, compatble with new device (TAS5825). */
#define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0x0, 0x01)
#define TASDEVICE_REG_SWRESET_RESET BIT(0)
@@ -91,6 +98,30 @@
/* prm_TE_1_Beta1 */
#define TAS2563_TE_DT_REG TASDEVICE_REG(0x00, 0x0f, 0x70)
#define TAS2573_FCT_INT_LATCH TASDEVICE_REG(0x00, 0x00, 0x67)
/* YM57 */
#define TAS2573_FCT_OUTPUT_R0 TASDEVICE_REG(0x00, 0x65, 0x74)
/* YM58 */
#define TAS2573_FCT_OUTPUT_R0_LOW TASDEVICE_REG(0x00, 0x65, 0x78)
/* YM59 */
#define TAS2573_FCT_OUTPUT_INV_R0 TASDEVICE_REG(0x00, 0x65, 0x7C)
/* YM61 */
#define TAS2573_FCT_OUTPUT_POWERTOT TASDEVICE_REG(0x00, 0x66, 0x0C)
/* YM64 */
#define TAS2573_FCT_OUTPUT_F0 TASDEVICE_REG(0x00, 0x65, 0x18)
/* YM147 */
#define TAS2573_FCT_STATUS_CTRL TASDEVICE_REG(0x00, 0x68, 0x74)
/* YM148 */
#define TAS2573_FCT_STATUS_BINNING TASDEVICE_REG(0x00, 0x68, 0x78)
/* YM664 */
#define TAS2573_RE_OUT TASDEVICE_REG(0x00, 0x7A, 0x18)
/* YM952 */
#define TAS2573_SILENCE_DETECTED TASDEVICE_REG(0x00, 0x83, 0x60)
/* YM954 */
#define TAS2573_OPEN_CIRCUIT TASDEVICE_REG(0x00, 0x83, 0x68)
/* YM955 */
#define TAS2573_SHORTCKT TASDEVICE_REG(0x00, 0x83, 0x6C)
#define TAS2781_PRM_INT_MASK_REG TASDEVICE_REG(0x00, 0x00, 0x3b)
#define TAS2781_PRM_CLK_CFG_REG TASDEVICE_REG(0x00, 0x00, 0x5c)
#define TAS2781_PRM_RSVD_REG TASDEVICE_REG(0x00, 0x01, 0x19)
+2 -1
View File
@@ -99,9 +99,10 @@ enum {
SNDRV_HWDEP_IFACE_LINE6, /* Line6 USB processors */
SNDRV_HWDEP_IFACE_FW_MOTU, /* MOTU FireWire series */
SNDRV_HWDEP_IFACE_FW_FIREFACE, /* RME Fireface series */
SNDRV_HWDEP_IFACE_CAIAQ, /* Native Instruments caiaq USB devices */
/* Don't forget to change the following: */
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_FIREFACE
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_CAIAQ
};
struct snd_hwdep_info {
+117 -25
View File
@@ -42,6 +42,7 @@
#endif
struct snd_compr_file {
struct list_head list;
unsigned long caps;
struct snd_compr_stream stream;
};
@@ -75,11 +76,11 @@ static inline void snd_compr_task_free_all(struct snd_compr_stream *stream) { }
static int snd_compr_open(struct inode *inode, struct file *f)
{
struct snd_compr *compr;
struct snd_compr_file *data;
struct snd_compr_runtime *runtime;
struct snd_compr_file *data = NULL;
struct snd_compr_runtime *runtime = NULL;
enum snd_compr_direction dirn;
int maj = imajor(inode);
int ret;
int ret = 0;
if ((f->f_flags & O_ACCMODE) == O_WRONLY)
dirn = SND_COMPRESS_PLAYBACK;
@@ -101,17 +102,30 @@ static int snd_compr_open(struct inode *inode, struct file *f)
return -ENODEV;
}
ret = snd_card_file_add(compr->card, f);
if (ret < 0) {
snd_card_unref(compr->card);
return ret;
}
if (!try_module_get(compr->card->module)) {
snd_card_file_remove(compr->card, f);
snd_card_unref(compr->card);
return -EFAULT;
}
if (dirn != compr->direction) {
pr_err("this device doesn't support this direction\n");
snd_card_unref(compr->card);
return -EINVAL;
ret = -EINVAL;
goto __error;
}
data = kzalloc_obj(*data);
if (!data) {
snd_card_unref(compr->card);
return -ENOMEM;
ret = -ENOMEM;
goto __error;
}
INIT_LIST_HEAD(&data->list);
INIT_DELAYED_WORK(&data->stream.error_work, error_delayed_work);
@@ -121,9 +135,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)
data->stream.device = compr;
runtime = kzalloc_obj(*runtime);
if (!runtime) {
kfree(data);
snd_card_unref(compr->card);
return -ENOMEM;
ret = -ENOMEM;
goto __error;
}
runtime->state = SNDRV_PCM_STATE_OPEN;
init_waitqueue_head(&runtime->sleep);
@@ -132,11 +145,18 @@ static int snd_compr_open(struct inode *inode, struct file *f)
#endif
data->stream.runtime = runtime;
f->private_data = (void *)data;
scoped_guard(mutex, &compr->lock)
scoped_guard(mutex, &compr->lock) {
ret = compr->ops->open(&data->stream);
if (!ret)
list_add_tail(&data->list, &compr->open_list);
}
__error:
if (ret) {
kfree(runtime);
kfree(data);
module_put(compr->card->module);
snd_card_file_remove(compr->card, f);
}
snd_card_unref(compr->card);
return ret;
@@ -146,17 +166,23 @@ static int snd_compr_free(struct inode *inode, struct file *f)
{
struct snd_compr_file *data = f->private_data;
struct snd_compr_runtime *runtime = data->stream.runtime;
struct snd_compr *compr = data->stream.device;
cancel_delayed_work_sync(&data->stream.error_work);
switch (runtime->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_PAUSED:
data->stream.ops->trigger(&data->stream, SNDRV_PCM_TRIGGER_STOP);
break;
default:
break;
scoped_guard(mutex, &compr->lock) {
if (!list_empty(&data->list))
list_del_init(&data->list);
switch (runtime->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_PAUSED:
data->stream.ops->trigger(&data->stream, SNDRV_PCM_TRIGGER_STOP);
break;
default:
break;
}
}
snd_compr_task_free_all(&data->stream);
@@ -164,8 +190,10 @@ static int snd_compr_free(struct inode *inode, struct file *f)
data->stream.ops->free(&data->stream);
if (!data->stream.runtime->dma_buffer_p)
kfree(data->stream.runtime->buffer);
module_put(data->stream.device->card->module);
kfree(data->stream.runtime);
kfree(data);
snd_card_file_remove(compr->card, f);
return 0;
}
@@ -669,13 +697,30 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
if (retval)
return retval;
retval = snd_compr_allocate_buffer(stream, params);
if (retval)
return -ENOMEM;
if (stream->next_track) {
/*
* total_bytes_available/transferred still refer to the
* current buffer; its geometry must not change.
*/
if (params->buffer.fragment_size != stream->runtime->fragment_size ||
params->buffer.fragments != stream->runtime->fragments)
return -EINVAL;
} else {
retval = snd_compr_allocate_buffer(stream, params);
if (retval)
return retval;
}
retval = stream->ops->set_params(stream, params);
if (retval)
if (retval) {
/* the stream stays OPEN: drop the buffer of the rejected setup */
if (stream->runtime->state == SNDRV_PCM_STATE_OPEN &&
!stream->runtime->dma_buffer_p) {
kfree(stream->runtime->buffer);
stream->runtime->buffer = NULL;
}
return retval;
}
if (stream->next_track)
return retval;
@@ -744,6 +789,9 @@ snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg)
* we should allow parameter change only when stream has been
* opened not in other cases
*/
if (stream->runtime->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (copy_from_user(&metadata, (void __user *)arg, sizeof(metadata)))
return -EFAULT;
@@ -919,8 +967,10 @@ static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
* It is expected that driver will notify the drain completion and then
* stream will be moved to SETUP state, even if draining resulted in an
* error. We can trigger next track after this.
*
* The state has been set to SNDRV_PCM_STATE_DRAINING by the caller,
* before the drain trigger was issued.
*/
stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
mutex_unlock(&stream->device->lock);
/* we wait for drain to complete here, drain can return when
@@ -945,6 +995,7 @@ static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
static int snd_compr_drain(struct snd_compr_stream *stream)
{
snd_pcm_state_t state;
int retval;
switch (stream->runtime->state) {
@@ -959,9 +1010,20 @@ static int snd_compr_drain(struct snd_compr_stream *stream)
break;
}
/*
* The state must be set to draining before the trigger is issued as the
* drain can be completed by the driver either from the trigger callback
* itself or from a different context as soon as the trigger is called.
* A snd_compr_drain_notify() arriving before the state is updated would
* be lost and the wait for the drain to finish would never be woken up.
*/
state = stream->runtime->state;
stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
if (retval) {
pr_debug("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval);
stream->runtime->state = state;
wake_up(&stream->runtime->sleep);
return retval;
}
@@ -997,6 +1059,7 @@ static int snd_compr_next_track(struct snd_compr_stream *stream)
static int snd_compr_partial_drain(struct snd_compr_stream *stream)
{
snd_pcm_state_t state;
int retval;
switch (stream->runtime->state) {
@@ -1020,9 +1083,16 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream)
return -EPERM;
stream->partial_drain = true;
/* See the comment in snd_compr_drain() on the state handling */
state = stream->runtime->state;
stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN);
if (retval) {
pr_debug("Partial drain returned failure\n");
stream->partial_drain = false;
stream->runtime->state = state;
wake_up(&stream->runtime->sleep);
return retval;
}
@@ -1136,7 +1206,9 @@ static int snd_compr_task_start_prepare(struct snd_compr_task_runtime *task,
{
if (task == NULL)
return -EINVAL;
if (task->state >= SND_COMPRESS_TASK_STATE_FINISHED)
/* only an unqueued or already finished task may be (re)started */
if (task->state != SND_COMPRESS_TASK_STATE_IDLE &&
task->state != SND_COMPRESS_TASK_STATE_FINISHED)
return -EBUSY;
if (utask->input_size > task->input->size)
return -EINVAL;
@@ -1432,8 +1504,27 @@ static int snd_compress_dev_register(struct snd_device *device)
static int snd_compress_dev_disconnect(struct snd_device *device)
{
struct snd_compr *compr;
struct snd_compr_file *data;
compr = device->device_data;
scoped_guard(mutex, &compr->lock) {
list_for_each_entry(data, &compr->open_list, list) {
switch (data->stream.runtime->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_PAUSED:
data->stream.ops->trigger(&data->stream,
SNDRV_PCM_TRIGGER_STOP);
break;
default:
break;
}
data->stream.runtime->state = SNDRV_PCM_STATE_DISCONNECTED;
wake_up(&data->stream.runtime->sleep);
}
}
snd_unregister_device(compr->dev);
return 0;
}
@@ -1541,6 +1632,7 @@ int snd_compress_new(struct snd_card *card, int device,
compr->device = device;
compr->direction = dirn;
mutex_init(&compr->lock);
INIT_LIST_HEAD(&compr->open_list);
snd_compress_set_id(compr, id);
+2
View File
@@ -1802,6 +1802,8 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
alloc_size = compute_user_elem_size(private_size, count);
guard(rwsem_write)(&card->controls_rwsem);
if (card->shutdown)
return -ENODEV;
if (check_user_elem_overflow(card, alloc_size))
return -ENOMEM;
+57 -5
View File
@@ -563,12 +563,43 @@ static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, si
return count;
}
/*
* snd_ctl_led_disconnect() removes these files with card->controls_rwsem
* held. so don't let the removal wait for a callback that takes it.
*/
static struct kernfs_node *snd_ctl_led_sysfs_enter(struct device *dev,
struct device_attribute *attr)
{
struct kernfs_node *kn;
if (!try_module_get(THIS_MODULE))
return NULL;
kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
if (!kn)
module_put(THIS_MODULE);
return kn;
}
static void snd_ctl_led_sysfs_exit(struct kernfs_node *kn)
{
sysfs_unbreak_active_protection(kn);
module_put(THIS_MODULE);
}
static ssize_t attach_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
return set_led_id(led_card, buf, count, true);
struct kernfs_node *kn;
ssize_t ret;
kn = snd_ctl_led_sysfs_enter(dev, attr);
if (!kn)
return -ENODEV;
ret = set_led_id(led_card, buf, count, true);
snd_ctl_led_sysfs_exit(kn);
return ret;
}
static ssize_t detach_store(struct device *dev,
@@ -576,7 +607,15 @@ static ssize_t detach_store(struct device *dev,
const char *buf, size_t count)
{
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
return set_led_id(led_card, buf, count, false);
struct kernfs_node *kn;
ssize_t ret;
kn = snd_ctl_led_sysfs_enter(dev, attr);
if (!kn)
return -ENODEV;
ret = set_led_id(led_card, buf, count, false);
snd_ctl_led_sysfs_exit(kn);
return ret;
}
static ssize_t reset_store(struct device *dev,
@@ -594,10 +633,8 @@ static ssize_t reset_store(struct device *dev,
return count;
}
static ssize_t list_show(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t snd_ctl_led_list(struct snd_ctl_led_card *led_card, char *buf)
{
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
struct snd_ctl_led_ctl *lctl;
size_t l = 0;
struct snd_card *card __free(snd_card_unref) =
@@ -620,6 +657,21 @@ static ssize_t list_show(struct device *dev,
return l;
}
static ssize_t list_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
struct kernfs_node *kn;
ssize_t ret;
kn = snd_ctl_led_sysfs_enter(dev, attr);
if (!kn)
return -ENODEV;
ret = snd_ctl_led_list(led_card, buf);
snd_ctl_led_sysfs_exit(kn);
return ret;
}
static DEVICE_ATTR_WO(attach);
static DEVICE_ATTR_WO(detach);
static DEVICE_ATTR_WO(reset);
+1
View File
@@ -38,6 +38,7 @@ static int get_available_index(struct snd_card *card, const char *name)
sid.iface = SNDRV_CTL_ELEM_IFACE_CARD;
strscpy(sid.name, name, sizeof(sid.name));
guard(rwsem_read)(&card->controls_rwsem);
while (snd_ctl_find_id(card, &sid)) {
sid.index++;
/* reset numid; otherwise snd_ctl_find_id() hits this again */
+2 -1
View File
@@ -528,6 +528,8 @@ int snd_info_card_register(struct snd_card *card)
void snd_info_card_id_change(struct snd_card *card)
{
guard(mutex)(&info_mutex);
if (card->shutdown)
return;
if (card->proc_root_link) {
proc_remove(card->proc_root_link);
card->proc_root_link = NULL;
@@ -555,7 +557,6 @@ void snd_info_card_disconnect(struct snd_card *card)
if (card->proc_root)
snd_info_clear_entries(card->proc_root);
card->proc_root_link = NULL;
card->proc_root = NULL;
}
/*
+45 -50
View File
@@ -82,8 +82,24 @@ static int module_slot_match(struct module *module, int idx)
}
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
static DEFINE_MUTEX(mixer_oss_notify_mutex);
static int (*mixer_oss_notify_callback)(struct snd_card *card, int cmd);
void snd_mixer_oss_notify(struct snd_card *card, int cmd)
{
guard(mutex)(&mixer_oss_notify_mutex);
if (mixer_oss_notify_callback)
mixer_oss_notify_callback(card, cmd);
}
EXPORT_SYMBOL(snd_mixer_oss_notify);
void snd_mixer_oss_set_notify(int (*callback)(struct snd_card *, int))
{
/* Wait for callbacks, including a final module_put(), to return. */
guard(mutex)(&mixer_oss_notify_mutex);
mixer_oss_notify_callback = callback;
}
EXPORT_SYMBOL(snd_mixer_oss_set_notify);
#endif
static int check_empty_slot(struct module *module, int slot)
@@ -216,11 +232,13 @@ static void __snd_card_release(struct device *dev, void *data)
* is added automatically. In that way, the resource disconnection is assured
* at first, then released in the expected order.
*
* If an error happens at the probe before snd_card_register() is called and
* there have been other devres resources, you'd need to free the card manually
* via snd_card_free() call in the error; otherwise it may lead to UAF due to
* devres call orders. You can use snd_card_free_on_error() helper for
* handling it more easily.
* Caveat: if an error happens at the probe before snd_card_register() is
* called and there have been other devres resources that are referred at the
* card-level destructor call, you'd still need to free the card manually;
* otherwise it may lead to UAF due to devres call orders. Instead of a manual
* snd_card_free() call, you can use the automatic clean-up for the card
* pointer via __free(snd_card_free), too. In this case, don't forget to do
* NULL-clear the card pointer before the successful return!
*
* Return: zero if successful, or a negative error code
*/
@@ -250,30 +268,6 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid,
}
EXPORT_SYMBOL_GPL(snd_devm_card_new);
/**
* snd_card_free_on_error - a small helper for handling devm probe errors
* @dev: the managed device object
* @ret: the return code from the probe callback
*
* This function handles the explicit snd_card_free() call at the error from
* the probe callback. It's just a small helper for simplifying the error
* handling with the managed devices.
*
* Return: zero if successful, or a negative error code
*/
int snd_card_free_on_error(struct device *dev, int ret)
{
struct snd_card *card;
if (!ret)
return 0;
card = devres_find(dev, __snd_card_release, NULL, NULL);
if (card)
snd_card_free(card);
return ret;
}
EXPORT_SYMBOL_GPL(snd_card_free_on_error);
static int snd_card_init(struct snd_card *card, struct device *parent,
int idx, const char *xid, struct module *module,
size_t extra_size)
@@ -356,7 +350,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
err = snd_info_card_create(card);
if (err < 0) {
dev_err(parent, "unable to create card info\n");
goto __error_ctl;
goto __error;
}
#ifdef CONFIG_SND_DEBUG
@@ -365,16 +359,16 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
#endif
#ifdef CONFIG_SND_CTL_DEBUG
card->value_buf = kmalloc_obj(*card->value_buf);
if (!card->value_buf)
return -ENOMEM;
if (!card->value_buf) {
err = -ENOMEM;
goto __error;
}
#endif
return 0;
__error_ctl:
snd_device_free_all(card);
__error:
put_device(&card->card_dev);
return err;
snd_card_free(card);
return err;
}
/**
@@ -530,8 +524,7 @@ void snd_card_disconnect(struct snd_card *card)
/* at this point, they cannot respond to any calls except release() */
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT);
snd_mixer_oss_notify(card, SND_MIXER_OSS_NOTIFY_DISCONNECT);
#endif
/* notify all devices that we are disconnected */
@@ -557,6 +550,8 @@ void snd_card_disconnect(struct snd_card *card)
clear_bit(card->number, snd_cards_lock);
}
/* order card->shutdown store against power_ref read */
smp_mb();
snd_power_sync_ref(card);
}
EXPORT_SYMBOL(snd_card_disconnect);
@@ -587,8 +582,7 @@ static int snd_card_do_free(struct snd_card *card)
card->releasing = true;
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
snd_mixer_oss_notify(card, SND_MIXER_OSS_NOTIFY_FREE);
#endif
snd_device_free_all(card);
kfree(card->components);
@@ -932,8 +926,7 @@ int snd_card_register(struct snd_card *card)
return err;
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
snd_mixer_oss_notify(card, SND_MIXER_OSS_NOTIFY_REGISTER);
#endif
return 0;
}
@@ -1174,12 +1167,14 @@ EXPORT_SYMBOL(snd_card_file_remove);
int snd_power_ref_and_wait(struct snd_card *card)
{
snd_power_ref(card);
if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0)
return 0;
wait_event_cmd(card->power_sleep,
card->shutdown ||
snd_power_get_state(card) == SNDRV_CTL_POWER_D0,
snd_power_unref(card), snd_power_ref(card));
/* order power_ref increment against card->shutdown read */
smp_mb__after_atomic();
if (snd_power_get_state(card) != SNDRV_CTL_POWER_D0) {
wait_event_cmd(card->power_sleep,
card->shutdown ||
snd_power_get_state(card) == SNDRV_CTL_POWER_D0,
snd_power_unref(card), snd_power_ref(card));
}
if (card->shutdown) {
snd_power_unref(card);
return -ENODEV;
+54 -13
View File
@@ -38,6 +38,7 @@ static const int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
};
#endif /* CONFIG_SND_JACK_INPUT_DEV */
static void snd_jack_add_debugfs(struct snd_jack *jack);
static void snd_jack_remove_debugfs(struct snd_jack *jack);
static int snd_jack_dev_disconnect(struct snd_device *device)
@@ -68,6 +69,9 @@ static int snd_jack_dev_free(struct snd_device *device)
struct snd_card *card = device->card;
struct snd_jack_kctl *jack_kctl, *tmp_jack_kctl;
/* Remove debugfs while the controls are still linked. */
snd_jack_remove_debugfs(jack);
list_for_each_entry_safe(jack_kctl, tmp_jack_kctl, &jack->kctl_list, list) {
list_del_init(&jack_kctl->list);
snd_ctl_remove(card, jack_kctl->kctl);
@@ -85,11 +89,10 @@ static int snd_jack_dev_free(struct snd_device *device)
}
#ifdef CONFIG_SND_JACK_INPUT_DEV
static int snd_jack_dev_register(struct snd_device *device)
static int snd_jack_input_dev_register(struct snd_card *card,
struct snd_jack *jack)
{
struct snd_jack *jack = device->device_data;
struct snd_card *card = device->card;
int err, i;
int i;
snprintf(jack->name, sizeof(jack->name), "%s %s",
card->shortname, jack->id);
@@ -117,14 +120,32 @@ static int snd_jack_dev_register(struct snd_device *device)
input_set_capability(jack->input_dev, EV_KEY, jack->key[i]);
}
err = input_register_device(jack->input_dev);
if (err == 0)
jack->registered = 1;
return err;
return input_register_device(jack->input_dev);
}
#else
static inline int snd_jack_input_dev_register(struct snd_card *card,
struct snd_jack *jack)
{
return 0;
}
#endif /* CONFIG_SND_JACK_INPUT_DEV */
static int snd_jack_dev_register(struct snd_device *device)
{
struct snd_card *card = device->card;
struct snd_jack *jack = device->device_data;
int err;
err = snd_jack_input_dev_register(card, jack);
if (err < 0)
return err;
snd_jack_add_debugfs(jack);
jack->registered = true;
return 0;
}
#ifdef CONFIG_SND_JACK_INJECTION_DEBUG
static void snd_jack_inject_report(struct snd_jack_kctl *jack_kctl, int status)
{
@@ -303,6 +324,7 @@ static ssize_t jack_type_read(struct file *file,
}
static const struct file_operations jack_type_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = jack_type_read,
.llseek = default_llseek,
@@ -310,6 +332,7 @@ static const struct file_operations jack_type_fops = {
#endif
static const struct file_operations sw_inject_enable_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = sw_inject_enable_read,
.write = sw_inject_enable_write,
@@ -317,24 +340,28 @@ static const struct file_operations sw_inject_enable_fops = {
};
static const struct file_operations jackin_inject_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.write = jackin_inject_write,
.llseek = default_llseek,
};
static const struct file_operations jack_kctl_id_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = jack_kctl_id_read,
.llseek = default_llseek,
};
static const struct file_operations jack_kctl_mask_bits_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = jack_kctl_mask_bits_read,
.llseek = default_llseek,
};
static const struct file_operations jack_kctl_status_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = jack_kctl_status_read,
.llseek = default_llseek,
@@ -346,6 +373,9 @@ static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
char *tname;
int i;
if (jack_kctl->jack_debugfs_root)
return 0;
/* Don't create injection interface for Phantom jacks */
if (strstr(jack_kctl->kctl->id.name, "Phantom"))
return 0;
@@ -384,6 +414,14 @@ static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
return 0;
}
static void snd_jack_add_debugfs(struct snd_jack *jack)
{
struct snd_jack_kctl *jack_kctl;
list_for_each_entry(jack_kctl, &jack->kctl_list, list)
snd_jack_debugfs_add_inject_node(jack, jack_kctl);
}
static void snd_jack_remove_debugfs(struct snd_jack *jack)
{
struct snd_jack_kctl *jack_kctl;
@@ -400,6 +438,10 @@ static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
return 0;
}
static void snd_jack_add_debugfs(struct snd_jack *jack)
{
}
static void snd_jack_remove_debugfs(struct snd_jack *jack)
{
}
@@ -420,7 +462,8 @@ static void snd_jack_kctl_add(struct snd_jack *jack, struct snd_jack_kctl *jack_
{
jack_kctl->jack = jack;
list_add_tail(&jack_kctl->list, &jack->kctl_list);
snd_jack_debugfs_add_inject_node(jack, jack_kctl);
if (jack->registered)
snd_jack_debugfs_add_inject_node(jack, jack_kctl);
}
static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const char *name, unsigned int mask)
@@ -450,7 +493,7 @@ static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const cha
return jack_kctl;
error:
snd_ctl_free_one(kctl);
snd_ctl_remove(card, kctl);
return NULL;
}
@@ -501,9 +544,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
int err;
static const struct snd_device_ops ops = {
.dev_free = snd_jack_dev_free,
#ifdef CONFIG_SND_JACK_INPUT_DEV
.dev_register = snd_jack_dev_register,
#endif /* CONFIG_SND_JACK_INPUT_DEV */
.dev_disconnect = snd_jack_dev_disconnect,
};
+4 -1
View File
@@ -183,11 +183,13 @@ void snd_refcount_init(struct snd_refcount *ref)
{
atomic_set(&ref->count, 0);
init_waitqueue_head(&ref->waiter);
spin_lock_init(&ref->lock);
}
EXPORT_SYMBOL_GPL(snd_refcount_init);
void snd_refcount_put(struct snd_refcount *ref)
{
guard(spinlock_irqsave)(&ref->lock);
if (atomic_dec_and_test(&ref->count))
wake_up(&ref->waiter);
}
@@ -195,6 +197,7 @@ EXPORT_SYMBOL_GPL(snd_refcount_put);
void snd_refcount_sync(struct snd_refcount *ref)
{
wait_event(ref->waiter, !atomic_read(&ref->count));
guard(spinlock_irq)(&ref->lock);
wait_event_lock_irq(ref->waiter, !atomic_read(&ref->count), ref->lock);
}
EXPORT_SYMBOL_GPL(snd_refcount_sync);
Loaded 100 of 832 files, more files were not shown because too many files have changed in this diff. Show more