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

Pull sound updates from Takashi Iwai:
 "It's been relatively calm in this cycle from the feature POV, but
  there were lots of cleanup works in the wide-range of code for
  converting with the auto-cleanup macros like guard().

  The mostly user-visible changes are the support of a couple of new
  compress-offload API extensions, and the support of new ASoC codec /
  platform drivers as well as USB-audio quirks.

  Here we go with some highlights:

  Core:
   - Compress-offload API extension for 64bit timestamp support
   - Compress-offload API extension for OPUS codec support
   - Workaround for PCM locking issue with PREEMPT_RT and softirq
   - KCSAN warning fix for ALSA sequencer core

  ASoC:
   - Continued cleanup works for ASoC core APIs
   - Lots of cleanups and conversions of DT bindings
   - Substantial maintainance work on the Intel AVS drivers
   - Support for Qualcomm Glymur and PM4125, Realtek RT1321, Shanghai
     FourSemi FS2104/5S, Texas Instruments PCM1754 and TAS2783A
   - Remove support for TI WL1273 for old Nokia systems

  USB-audio:
   - Support for Tascam US-144mkII, Presonus S1824c support
   - More flexible quirk option handling
   - Fix for USB MIDI timer bug triggered by fuzzer

  Others:
   - A large series of cleanups with guard() & co macros over (non-ASoC)
     sound drivers (PCI, ISA, HD-audio, USB-audio, drivers, etc)
   - TAS5825 HD-audio side-codec support"

* tag 'sound-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (454 commits)
  ALSA: usb-audio: don't hardcode gain for output channel of Presonus Studio
  ALSA: usb-audio: add the initial mix for Presonus Studio 1824c
  ALSA: doc: improved docs about quirk_flags in snd-usb-audio
  ALSA: usb-audio: make param quirk_flags change-able in runtime
  ALSA: usb-audio: improve module param quirk_flags
  ALSA: usb-audio: add two-way convert between name and bit for QUIRK_FLAG_*
  ALSA: usb-audio: fix race condition to UAF in snd_usbmidi_free
  ALSA: usb-audio: add mono main switch to Presonus S1824c
  ALSA: compress: document 'chan_map' member in snd_dec_opus
  ASoC: cs35l56: Add support for CS35L56 B2 silicon
  ASoC: cs35l56: Set fw_regs table after getting REVID
  ALSA: hda/realtek: Add quirk for HP Spectre 14t-ea100
  ASoc: tas2783A: Fix an error code in probe()
  ASoC: tlv320aic3x: Fix class-D initialization for tlv320aic3007
  ASoC: qcom: sc8280xp: use sa8775p/ subdir for QCS9100 / QCS9075
  ASoC: stm32: sai: manage context in set_sysclk callback
  ASoC: renesas: msiof: ignore 1st FSERR
  ASoC: renesas: msiof: Add note for The possibility of R/L opposite Capture
  ASoC: renesas: msiof: setup both (Playback/Capture) in the same time
  ASoC: renesas: msiof: tidyup DMAC stop timing
  ...
This commit is contained in:
Linus Torvalds
2025-10-02 11:37:19 -07:00
602 changed files with 24383 additions and 16192 deletions

View File

@@ -1,46 +0,0 @@
Texas Instruments TWL family (twl4030) audio module
The audio module inside the TWL family consist of an audio codec and a vibra
driver.
Required properties:
- compatible : must be "ti,twl4030-audio"
Optional properties, nodes:
Audio functionality:
- codec { }: Need to be present if the audio functionality is used. Within this
section the following options can be used:
- ti,digimic_delay: Delay need after enabling the digimic to reduce artifacts
from the start of the recorded sample (in ms)
-ti,ramp_delay_value: HS ramp delay configuration to reduce pop noise
-ti,hs_extmute: Use external mute for HS pop reduction
-ti,hs_extmute_gpio: Use external GPIO to control the external mute
-ti,offset_cncl_path: Offset cancellation path selection, refer to TRM for the
valid values.
Vibra functionality
- ti,enable-vibra: Need to be set to <1> if the vibra functionality is used. if
missing or it is 0, the vibra functionality is disabled.
Example:
&i2c1 {
clock-frequency = <2600000>;
twl: twl@48 {
reg = <0x48>;
interrupts = <7>; /* SYS_NIRQ cascaded to intc */
interrupt-parent = <&intc>;
twl_audio: audio {
compatible = "ti,twl4030-audio";
ti,enable-vibra = <1>;
codec {
ti,ramp_delay_value = <3>;
};
};
};
};

View File

@@ -1,25 +0,0 @@
ALC5621/ALC5622/ALC5623 audio Codec
Required properties:
- compatible: "realtek,alc5623"
- reg: the I2C address of the device.
Optional properties:
- add-ctrl: Default register value for Reg-40h, Additional Control
Register. If absent or has the value of 0, the
register is untouched.
- jack-det-ctrl: Default register value for Reg-5Ah, Jack Detect
Control Register. If absent or has value 0, the
register is untouched.
Example:
alc5621: alc5621@1a {
compatible = "alc5621";
reg = <0x1a>;
add-ctrl = <0x3700>;
jack-det-ctrl = <0x4810>;
};

View File

@@ -15,6 +15,9 @@ properties:
- asahi-kasei,ak4458
- asahi-kasei,ak4497
"#sound-dai-cells":
const: 0
reg:
maxItems: 1
@@ -46,6 +49,7 @@ required:
- reg
allOf:
- $ref: dai-common.yaml#
- if:
properties:
compatible:

View File

@@ -1,24 +0,0 @@
* Broadcom BCM2835 SoC I2S/PCM module
Required properties:
- compatible: "brcm,bcm2835-i2s"
- reg: Should contain PCM registers location and length.
- clocks: the (PCM) clock to use
- dmas: List of DMA controller phandle and DMA request line ordered pairs.
- dma-names: Identifier string for each DMA request line in the dmas property.
These strings correspond 1:1 with the ordered pairs in dmas.
One of the DMA channels will be responsible for transmission (should be
named "tx") and one for reception (should be named "rx").
Example:
bcm2835_i2s: i2s@7e203000 {
compatible = "brcm,bcm2835-i2s";
reg = <0x7e203000 0x24>;
clocks = <&clocks BCM2835_CLOCK_PCM>;
dmas = <&dma 2>,
<&dma 3>;
dma-names = "tx", "rx";
};

View File

@@ -0,0 +1,51 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/brcm,bcm2835-i2s.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom BCM2835 SoC I2S/PCM module
maintainers:
- Florian Fainelli <florian.fainelli@broadcom.com>
properties:
compatible:
const: brcm,bcm2835-i2s
reg:
maxItems: 1
clocks:
maxItems: 1
dmas:
items:
- description: Transmission DMA controller phandle and request line.
- description: Reception DMA controller phandle and request line.
dma-names:
items:
- const: tx
- const: rx
required:
- compatible
- reg
- clocks
- dmas
- dma-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/bcm2835.h>
i2s@7e203000 {
compatible = "brcm,bcm2835-i2s";
reg = <0x7e203000 0x24>;
clocks = <&clocks BCM2835_CLOCK_PCM>;
dmas = <&dma 2>, <&dma 3>;
dma-names = "tx", "rx";
};

View File

@@ -151,6 +151,12 @@ properties:
minimum: 0
maximum: 5
cirrus,subsystem-id:
$ref: /schemas/types.yaml#/definitions/string
description:
Subsystem ID. If this property is present, it sets the system name,
used to identify the firmware and tuning to load.
required:
- compatible
- reg

View File

@@ -12,6 +12,22 @@ maintainers:
- Matteo Martelli <matteomartelli3@gmail.com>
- Binbin Zhou <zhoubinbin@loongson.cn>
description: |
Everest ES8311, ES8316 and ES8323 audio CODECs
Pins on the device (for linking into audio routes):
Outputs:
* LOUT: Left Analog Output
* ROUT: Right Analog Output
* MICBIAS: Microphone Bias
Inputs:
* MIC1P: Microphone 1 Positive Analog Input
* MIC1N: Microphone 1 Negative Analog Input
* MIC2P: Microphone 2 Positive Analog Input
* MIC2N: Microphone 2 Negative Analog Input
allOf:
- $ref: dai-common.yaml#

View File

@@ -0,0 +1,101 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/foursemi,fs2105s.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: FourSemi FS2104/5S Digital Audio Amplifier
maintainers:
- Nick Li <nick.li@foursemi.com>
description:
The FS2104 is a 15W Inductor-Less, Stereo, Closed-Loop,
Digital Input Class-D Power Amplifier with Enhanced Signal Processing.
The FS2105S is a 30W Inductor-Less, Stereo, Closed-Loop,
Digital Input Class-D Power Amplifier with Enhanced Signal Processing.
properties:
compatible:
oneOf:
- items:
- enum:
- foursemi,fs2104
- const: foursemi,fs2105s
- enum:
- foursemi,fs2105s
reg:
maxItems: 1
clocks:
items:
- description: The clock of I2S BCLK
clock-names:
items:
- const: bclk
interrupts:
maxItems: 1
'#sound-dai-cells':
const: 0
pvdd-supply:
description:
Regulator for power supply(PVDD in datasheet).
dvdd-supply:
description:
Regulator for digital supply(DVDD in datasheet).
reset-gpios:
maxItems: 1
description:
It's the SDZ pin in datasheet, the pin is active low,
it will power down and reset the chip to shut down state.
firmware-name:
maxItems: 1
description: |
The firmware(*.bin) contains:
a. Register initialization settings
b. DSP effect parameters
c. Multi-scene sound effect configurations(optional)
It's gernerated by FourSemi's tuning tool.
required:
- compatible
- reg
- '#sound-dai-cells'
- pvdd-supply
- dvdd-supply
- reset-gpios
- firmware-name
allOf:
- $ref: dai-common.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@68 {
compatible = "foursemi,fs2105s";
reg = <0x68>;
clocks = <&clocks 18>;
clock-names = "bclk";
#sound-dai-cells = <0>;
pvdd-supply = <&pvdd_supply>;
dvdd-supply = <&dvdd_supply>;
reset-gpios = <&gpio 18 GPIO_ACTIVE_LOW>;
firmware-name = "fs2105s-btl-2p0-0s.bin";
pinctrl-names = "default";
pinctrl-0 = <&fs210x_pins_default>;
};
};

View File

@@ -104,6 +104,6 @@ examples:
"ctx2_rx", "ctx2_tx",
"ctx3_rx", "ctx3_tx";
firmware-name = "imx/easrc/easrc-imx8mn.bin";
fsl,asrc-rate = <8000>;
fsl,asrc-rate = <8000>;
fsl,asrc-format = <2>;
};

View File

@@ -176,7 +176,7 @@ examples:
<&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
dma-names = "rxa", "rxb", "rxc",
"txa", "txb", "txc";
fsl,asrc-rate = <48000>;
fsl,asrc-rate = <48000>;
fsl,asrc-width = <16>;
port {

View File

@@ -1,56 +0,0 @@
Freescale i.MX audio complex with SGTL5000 codec
Required properties:
- compatible : "fsl,imx-audio-sgtl5000"
- model : The user-visible name of this sound complex
- ssi-controller : The phandle of the i.MX SSI controller
- audio-codec : The phandle of the SGTL5000 audio codec
- audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the
connection's sink, the second being the connection's
source. Valid names could be power supplies, SGTL5000
pins, and the jacks on the board:
Power supplies:
* Mic Bias
SGTL5000 pins:
* MIC_IN
* LINE_IN
* HP_OUT
* LINE_OUT
Board connectors:
* Mic Jack
* Line In Jack
* Headphone Jack
* Line Out Jack
* Ext Spk
- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)
- mux-ext-port : The external port of the i.MX audio muxer
Note: The AUDMUX port numbering should start at 1, which is consistent with
hardware manual.
Example:
sound {
compatible = "fsl,imx51-babbage-sgtl5000",
"fsl,imx-audio-sgtl5000";
model = "imx51-babbage-sgtl5000";
ssi-controller = <&ssi1>;
audio-codec = <&sgtl5000>;
audio-routing =
"MIC_IN", "Mic Jack",
"Mic Jack", "Mic Bias",
"Headphone Jack", "HP_OUT";
mux-int-port = <1>;
mux-ext-port = <3>;
};

View File

@@ -23,6 +23,9 @@ properties:
sound-name-prefix: true
port:
$ref: /schemas/graph.yaml#/properties/port
required:
- "#sound-dai-cells"
- compatible

View File

@@ -0,0 +1,228 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mediatek,mt8183-audio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mediatek AFE PCM controller for mt8183
maintainers:
- Julien Massot <jmassot@collabora.com>
properties:
compatible:
const: mediatek,mt8183-audio
interrupts:
maxItems: 1
resets:
maxItems: 1
reset-names:
const: audiosys
power-domains:
maxItems: 1
memory-region:
maxItems: 1
clocks:
items:
- description: AFE clock
- description: ADDA DAC clock
- description: ADDA DAC pre-distortion clock
- description: ADDA ADC clock
- description: ADDA6 ADC clock
- description: Audio low-jitter 22.5792m clock
- description: Audio low-jitter 24.576m clock
- description: Audio PLL1 tuner clock
- description: Audio PLL2 tuner clock
- description: I2S1 bit clock
- description: I2S2 bit clock
- description: I2S3 bit clock
- description: I2S4 bit clock
- description: Audio Time-Division Multiplexing interface clock
- description: Powerdown Audio test model clock
- description: Audio infra sys clock
- description: Audio infra 26M clock
- description: Mux for audio clock
- description: Mux for audio internal bus clock
- description: Mux main divider by 4
- description: Primary audio mux
- description: Primary audio PLL
- description: Secondary audio mux
- description: Secondary audio PLL
- description: Primary audio en-generator clock
- description: Primary PLL divider by 4 for IEC
- description: Secondary audio en-generator clock
- description: Secondary PLL divider by 8 for IEC
- description: Mux selector for I2S port 0
- description: Mux selector for I2S port 1
- description: Mux selector for I2S port 2
- description: Mux selector for I2S port 3
- description: Mux selector for I2S port 4
- description: Mux selector for I2S port 5
- description: APLL1 and APLL2 divider for I2S port 0
- description: APLL1 and APLL2 divider for I2S port 1
- description: APLL1 and APLL2 divider for I2S port 2
- description: APLL1 and APLL2 divider for I2S port 3
- description: APLL1 and APLL2 divider for I2S port 4
- description: APLL1 and APLL2 divider for IEC
- description: 26MHz clock for audio subsystem
clock-names:
items:
- const: aud_afe_clk
- const: aud_dac_clk
- const: aud_dac_predis_clk
- const: aud_adc_clk
- const: aud_adc_adda6_clk
- const: aud_apll22m_clk
- const: aud_apll24m_clk
- const: aud_apll1_tuner_clk
- const: aud_apll2_tuner_clk
- const: aud_i2s1_bclk_sw
- const: aud_i2s2_bclk_sw
- const: aud_i2s3_bclk_sw
- const: aud_i2s4_bclk_sw
- const: aud_tdm_clk
- const: aud_tml_clk
- const: aud_infra_clk
- const: mtkaif_26m_clk
- const: top_mux_audio
- const: top_mux_aud_intbus
- const: top_syspll_d2_d4
- const: top_mux_aud_1
- const: top_apll1_ck
- const: top_mux_aud_2
- const: top_apll2_ck
- const: top_mux_aud_eng1
- const: top_apll1_d8
- const: top_mux_aud_eng2
- const: top_apll2_d8
- const: top_i2s0_m_sel
- const: top_i2s1_m_sel
- const: top_i2s2_m_sel
- const: top_i2s3_m_sel
- const: top_i2s4_m_sel
- const: top_i2s5_m_sel
- const: top_apll12_div0
- const: top_apll12_div1
- const: top_apll12_div2
- const: top_apll12_div3
- const: top_apll12_div4
- const: top_apll12_divb
- const: top_clk26m_clk
required:
- compatible
- interrupts
- resets
- reset-names
- power-domains
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt8183-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/power/mt8183-power.h>
#include <dt-bindings/reset/mt8183-resets.h>
audio-controller {
compatible = "mediatek,mt8183-audio";
interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_LOW>;
resets = <&watchdog MT8183_TOPRGU_AUDIO_SW_RST>;
reset-names = "audiosys";
power-domains = <&spm MT8183_POWER_DOMAIN_AUDIO>;
clocks = <&audiosys CLK_AUDIO_AFE>,
<&audiosys CLK_AUDIO_DAC>,
<&audiosys CLK_AUDIO_DAC_PREDIS>,
<&audiosys CLK_AUDIO_ADC>,
<&audiosys CLK_AUDIO_PDN_ADDA6_ADC>,
<&audiosys CLK_AUDIO_22M>,
<&audiosys CLK_AUDIO_24M>,
<&audiosys CLK_AUDIO_APLL_TUNER>,
<&audiosys CLK_AUDIO_APLL2_TUNER>,
<&audiosys CLK_AUDIO_I2S1>,
<&audiosys CLK_AUDIO_I2S2>,
<&audiosys CLK_AUDIO_I2S3>,
<&audiosys CLK_AUDIO_I2S4>,
<&audiosys CLK_AUDIO_TDM>,
<&audiosys CLK_AUDIO_TML>,
<&infracfg CLK_INFRA_AUDIO>,
<&infracfg CLK_INFRA_AUDIO_26M_BCLK>,
<&topckgen CLK_TOP_MUX_AUDIO>,
<&topckgen CLK_TOP_MUX_AUD_INTBUS>,
<&topckgen CLK_TOP_SYSPLL_D2_D4>,
<&topckgen CLK_TOP_MUX_AUD_1>,
<&topckgen CLK_TOP_APLL1_CK>,
<&topckgen CLK_TOP_MUX_AUD_2>,
<&topckgen CLK_TOP_APLL2_CK>,
<&topckgen CLK_TOP_MUX_AUD_ENG1>,
<&topckgen CLK_TOP_APLL1_D8>,
<&topckgen CLK_TOP_MUX_AUD_ENG2>,
<&topckgen CLK_TOP_APLL2_D8>,
<&topckgen CLK_TOP_MUX_APLL_I2S0>,
<&topckgen CLK_TOP_MUX_APLL_I2S1>,
<&topckgen CLK_TOP_MUX_APLL_I2S2>,
<&topckgen CLK_TOP_MUX_APLL_I2S3>,
<&topckgen CLK_TOP_MUX_APLL_I2S4>,
<&topckgen CLK_TOP_MUX_APLL_I2S5>,
<&topckgen CLK_TOP_APLL12_DIV0>,
<&topckgen CLK_TOP_APLL12_DIV1>,
<&topckgen CLK_TOP_APLL12_DIV2>,
<&topckgen CLK_TOP_APLL12_DIV3>,
<&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";
};
...

View File

@@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mediatek,mt8183_da7219.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MT8183 sound card with external codecs
maintainers:
- Julien Massot <jmassot@collabora.com>
description:
MediaTek MT8183 SoC-based sound cards with DA7219 as headset codec,
and MAX98357A, RT1015 or RT1015P as speaker amplifiers. Optionally includes HDMI codec.
properties:
compatible:
enum:
- mediatek,mt8183_da7219_max98357
- mediatek,mt8183_da7219_rt1015
- mediatek,mt8183_da7219_rt1015p
mediatek,headset-codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: Phandle to the DA7219 headset codec.
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle
description: Phandle to the MT8183 ASoC platform (e.g., AFE node).
mediatek,hdmi-codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: Optional phandle to the HDMI codec (e.g., IT6505).
required:
- compatible
- mediatek,headset-codec
- mediatek,platform
additionalProperties: false
examples:
- |
sound {
compatible = "mediatek,mt8183_da7219_max98357";
mediatek,headset-codec = <&da7219>;
mediatek,hdmi-codec = <&it6505dptx>;
mediatek,platform = <&afe>;
};

View File

@@ -0,0 +1,59 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mediatek,mt8183_mt6358_ts3a227.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MT8183 sound card with MT6358, TS3A227, and MAX98357/RT1015 codecs
maintainers:
- Julien Massot <julien.massot@collabora.com>
description:
MediaTek MT8183 SoC-based sound cards using the MT6358 codec,
with optional TS3A227 headset codec, EC codec (via Chrome EC), and HDMI audio.
Speaker amplifier can be one of MAX98357A/B, RT1015, or RT1015P.
properties:
compatible:
enum:
- mediatek,mt8183_mt6358_ts3a227_max98357
- mediatek,mt8183_mt6358_ts3a227_max98357b
- mediatek,mt8183_mt6358_ts3a227_rt1015
- mediatek,mt8183_mt6358_ts3a227_rt1015p
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle
description: Phandle to the MT8183 ASoC platform node (e.g., AFE).
mediatek,headset-codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: Phandle to the TS3A227 headset codec.
mediatek,ec-codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: |
Optional phandle to a ChromeOS EC codec node.
See bindings in google,cros-ec-codec.yaml.
mediatek,hdmi-codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: Optional phandle to an HDMI audio codec node.
required:
- compatible
- mediatek,platform
additionalProperties: false
examples:
- |
sound {
compatible = "mediatek,mt8183_mt6358_ts3a227_max98357";
mediatek,headset-codec = <&ts3a227>;
mediatek,ec-codec = <&ec_codec>;
mediatek,hdmi-codec = <&it6505dptx>;
mediatek,platform = <&afe>;
};
...

View File

@@ -1,42 +0,0 @@
Mediatek AFE PCM controller for mt8183
Required properties:
- compatible = "mediatek,mt68183-audio";
- reg: register location and size
- interrupts: should contain AFE interrupt
- resets: Must contain an entry for each entry in reset-names
See ../reset/reset.txt for details.
- reset-names: should have these reset names:
"audiosys";
- power-domains: should define the power domain
- clocks: Must contain an entry for each entry in clock-names
- clock-names: should have these clock names:
"infra_sys_audio_clk",
"mtkaif_26m_clk",
"top_mux_audio",
"top_mux_aud_intbus",
"top_sys_pll3_d4",
"top_clk26m_clk";
Example:
afe: mt8183-afe-pcm@11220000 {
compatible = "mediatek,mt8183-audio";
reg = <0 0x11220000 0 0x1000>;
interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_LOW>;
resets = <&watchdog MT8183_TOPRGU_AUDIO_SW_RST>;
reset-names = "audiosys";
power-domains = <&scpsys MT8183_POWER_DOMAIN_AUDIO>;
clocks = <&infrasys CLK_INFRA_AUDIO>,
<&infrasys CLK_INFRA_AUDIO_26M_BCLK>,
<&topckgen CLK_TOP_MUX_AUDIO>,
<&topckgen CLK_TOP_MUX_AUD_INTBUS>,
<&topckgen CLK_TOP_SYSPLL_D2_D4>,
<&clk26m>;
clock-names = "infra_sys_audio_clk",
"mtkaif_26m_clk",
"top_mux_audio",
"top_mux_aud_intbus",
"top_sys_pll_d2_d4",
"top_clk26m_clk";
};

View File

@@ -1,21 +0,0 @@
MT8183 with MT6358, DA7219, MAX98357, and RT1015 CODECS
Required properties:
- compatible : "mediatek,mt8183_da7219_max98357" for MAX98357A codec
"mediatek,mt8183_da7219_rt1015" for RT1015 codec
"mediatek,mt8183_da7219_rt1015p" for RT1015P codec
- mediatek,headset-codec: the phandles of da7219 codecs
- mediatek,platform: the phandle of MT8183 ASoC platform
Optional properties:
- mediatek,hdmi-codec: the phandles of HDMI codec
Example:
sound {
compatible = "mediatek,mt8183_da7219_max98357";
mediatek,headset-codec = <&da7219>;
mediatek,hdmi-codec = <&it6505dptx>;
mediatek,platform = <&afe>;
};

View File

@@ -1,25 +0,0 @@
MT8183 with MT6358, TS3A227, MAX98357, and RT1015 CODECS
Required properties:
- compatible : "mediatek,mt8183_mt6358_ts3a227_max98357" for MAX98357A codec
"mediatek,mt8183_mt6358_ts3a227_max98357b" for MAX98357B codec
"mediatek,mt8183_mt6358_ts3a227_rt1015" for RT1015 codec
"mediatek,mt8183_mt6358_ts3a227_rt1015p" for RT1015P codec
- mediatek,platform: the phandle of MT8183 ASoC platform
Optional properties:
- mediatek,headset-codec: the phandles of ts3a227 codecs
- mediatek,ec-codec: the phandle of EC codecs.
See google,cros-ec-codec.txt for more details.
- mediatek,hdmi-codec: the phandles of HDMI codec
Example:
sound {
compatible = "mediatek,mt8183_mt6358_ts3a227_max98357";
mediatek,headset-codec = <&ts3a227>;
mediatek,ec-codec = <&ec_codec>;
mediatek,hdmi-codec = <&it6505dptx>;
mediatek,platform = <&afe>;
};

View File

@@ -9,6 +9,20 @@ title: NAU8825 audio CODEC
maintainers:
- John Hsu <KCHSU0@nuvoton.com>
description: |
NAU8825 audio CODEC
Pins on the device (for linking into audio routes):
Outputs:
* HPOL : Headphone Left Output
* HPOR : Headphone Right Output
* MICBIAS : Microphone Bias Output
Inputs:
* MICP : Analog Microphone Positive Input
* MICN : Analog Microphone Negative Input
allOf:
- $ref: dai-common.yaml#

View File

@@ -1,62 +0,0 @@
* Texas Instruments SoC with twl4030 based audio setups
Required properties:
- compatible: "ti,omap-twl4030"
- ti,model: Name of the sound card (for example "omap3beagle")
- ti,mcbsp: phandle for the McBSP node
Optional properties:
- ti,codec: phandle for the twl4030 audio node
- ti,mcbsp-voice: phandle for the McBSP node connected to the voice port of twl
- ti, jack-det-gpio: Jack detect GPIO
- ti,audio-routing: List of 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.
If the routing is not provided all possible connection will be available
Available audio endpoints for the audio-routing table:
Board connectors:
* Headset Stereophone
* Earpiece Spk
* Handsfree Spk
* Ext Spk
* Main Mic
* Sub Mic
* Headset Mic
* Carkit Mic
* Digital0 Mic
* Digital1 Mic
* Line In
twl4030 pins:
* HSOL
* HSOR
* EARPIECE
* HFL
* HFR
* PREDRIVEL
* PREDRIVER
* CARKITL
* CARKITR
* MAINMIC
* SUBMIC
* HSMIC
* DIGIMIC0
* DIGIMIC1
* CARKITMIC
* AUXL
* AUXR
* Headset Mic Bias
* Mic Bias 1 /* Used for Main Mic or Digimic0 */
* Mic Bias 2 /* Used for Sub Mic or Digimic1 */
Example:
sound {
compatible = "ti,omap-twl4030";
ti,model = "omap3beagle";
ti,mcbsp = <&mcbsp2>;
};

View File

@@ -20,6 +20,7 @@ properties:
- qcom,sc8280xp-lpass-va-macro
- items:
- enum:
- qcom,glymur-lpass-va-macro
- qcom,sm8650-lpass-va-macro
- qcom,sm8750-lpass-va-macro
- qcom,x1e80100-lpass-va-macro
@@ -79,12 +80,25 @@ allOf:
compatible:
contains:
const: qcom,sc7280-lpass-va-macro
then:
properties:
clocks:
maxItems: 1
clock-names:
maxItems: 1
if:
required:
- power-domains
then:
properties:
clocks:
maxItems: 1
clock-names:
maxItems: 1
else:
properties:
clocks:
minItems: 3
maxItems: 3
clock-names:
minItems: 3
maxItems: 3
- if:
properties:

View File

@@ -20,6 +20,7 @@ properties:
- qcom,sc8280xp-lpass-wsa-macro
- items:
- enum:
- qcom,glymur-lpass-wsa-macro
- qcom,sm8650-lpass-wsa-macro
- qcom,sm8750-lpass-wsa-macro
- qcom,x1e80100-lpass-wsa-macro

View File

@@ -0,0 +1,134 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,pm4125-codec.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm PM4125 Audio Codec
maintainers:
- Alexey Klimov <alexey.klimov@linaro.org>
description:
The audio codec IC found on Qualcomm PM4125/PM2250 PMIC.
It has RX and TX Soundwire slave devices.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: qcom,pm4125-codec
reg:
description:
Specifies the SPMI base address for the audio codec peripherals. The
address space contains reset register needed to power-on the codec.
maxItems: 1
reg-names:
maxItems: 1
vdd-io-supply:
description: A reference to the 1.8V I/O supply
vdd-cp-supply:
description: A reference to the charge pump I/O supply
vdd-mic-bias-supply:
description: A reference to the 3.3V mic bias supply
vdd-pa-vpos-supply:
description: A reference to the PA VPOS supply
qcom,tx-device:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: A reference to Soundwire tx device phandle
qcom,rx-device:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: A reference to Soundwire rx device phandle
qcom,micbias1-microvolt:
description: micbias1 voltage
minimum: 1800000
maximum: 2850000
qcom,micbias2-microvolt:
description: micbias2 voltage
minimum: 1800000
maximum: 2850000
qcom,micbias3-microvolt:
description: micbias3 voltage
minimum: 1800000
maximum: 2850000
qcom,mbhc-buttons-vthreshold-microvolt:
description:
Array of 8 Voltage threshold values corresponding to headset
button0 - button7
minItems: 8
maxItems: 8
'#sound-dai-cells':
const: 1
required:
- compatible
- reg
- vdd-io-supply
- vdd-cp-supply
- vdd-mic-bias-supply
- vdd-pa-vpos-supply
- qcom,tx-device
- qcom,rx-device
- qcom,micbias1-microvolt
- qcom,micbias2-microvolt
- qcom,micbias3-microvolt
- '#sound-dai-cells'
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/spmi/spmi.h>
spmi {
#address-cells = <2>;
#size-cells = <0>;
pmic {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@f000 {
compatible = "qcom,pm4125-codec";
reg = <0xf000>;
vdd-io-supply = <&pm4125_l15>;
vdd-cp-supply = <&pm4125_s4>;
vdd-pa-vpos-supply = <&pm4125_s4>;
vdd-mic-bias-supply = <&pm4125_l22>;
qcom,micbias1-microvolt = <1800000>;
qcom,micbias2-microvolt = <1800000>;
qcom,micbias3-microvolt = <1800000>;
qcom,rx-device = <&pm4125_rx>;
qcom,tx-device = <&pm4125_tx>;
#sound-dai-cells = <1>;
};
};
};
/* ... */
soundwire@a610000 {
reg = <0x0a610000 0x2000>;
#address-cells = <2>;
#size-cells = <0>;
pm4125_rx: audio-codec@0,4 {
compatible = "sdw20217010c00";
reg = <0 4>;
qcom,rx-port-mapping = <1 3>;
};
};
...

View File

@@ -0,0 +1,79 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,pm4125-sdw.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm SoundWire Slave devices on PM4125/PM2250 PMIC audio codec.
maintainers:
- Alexey Klimov <alexey.klimov@linaro.org>
description:
The audio codec IC found on Qualcomm PM4125/PM2250 PMICs.
It has RX and TX Soundwire slave devices.
properties:
compatible:
const: sdw20217010c00
reg:
maxItems: 1
qcom,tx-port-mapping:
description: |
Specifies static port mapping between device and host tx ports.
In the order of the device port index which are adc1_port, adc23_port,
dmic03_mbhc_port, dmic46_port.
Supports maximum 2 tx soundwire ports.
PM4125 TX Port 1 (ADC1,2 & DMIC0 & MBHC) <=> SWR0 Port 1
PM4125 TX Port 2 (ADC1 & DMIC0,1,2 & MBHC) <=> SWR0 Port 2
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 2
maxItems: 2
items:
enum: [1, 2, 3, 4]
qcom,rx-port-mapping:
description: |
Specifies static port mapping between device and host rx ports.
In the order of device port index which are hph_port, clsh_port,
comp_port, lo_port, dsd port.
Supports maximum 2 rx soundwire ports.
PM4125 RX Port 1 (HPH_L/R) <==> SWR1 Port 1 (HPH_L/R)
PM4125 RX Port 2 (COMP_L/R) <==> SWR1 Port 3 (COMP_L/R)
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 2
maxItems: 2
items:
enum: [1, 2, 3, 4, 5]
required:
- compatible
- reg
oneOf:
- required:
- qcom,tx-port-mapping
- required:
- qcom,rx-port-mapping
additionalProperties: false
examples:
- |
soundwire@a610000 {
reg = <0x0a610000 0x2000>;
#address-cells = <2>;
#size-cells = <0>;
pm4125_rx: codec@0,1 {
compatible = "sdw20217010c00";
reg = <0 1>;
qcom,rx-port-mapping = <1 3>;
};
};
...

View File

@@ -31,6 +31,7 @@ properties:
- fairphone,fp4-sndcard
- fairphone,fp5-sndcard
- qcom,apq8096-sndcard
- qcom,glymur-sndcard
- qcom,qcm6490-idp-sndcard
- qcom,qcs6490-rb3gen2-sndcard
- qcom,qcs8275-sndcard

View File

@@ -29,6 +29,10 @@ properties:
description: GPIO spec for Powerdown/Shutdown line to use (pin SD_N)
maxItems: 1
reset-gpios:
description: Powerdown/Shutdown line to use (pin SD_N)
maxItems: 1
vdd-supply:
description: VDD Supply for the Codec
@@ -50,10 +54,15 @@ required:
- compatible
- reg
- vdd-supply
- powerdown-gpios
- "#thermal-sensor-cells"
- "#sound-dai-cells"
oneOf:
- required:
- powerdown-gpios
- required:
- reset-gpios
unevaluatedProperties: false
examples:

View File

@@ -0,0 +1,54 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/realtek,alc5623.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ALC5621/ALC5623 Audio Codec
maintainers:
- Mahdi Khosravi <mmk1776@gmail.com>
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
enum:
- realtek,alc5621
- realtek,alc5623
reg:
maxItems: 1
add-ctrl:
description:
Default register value for Reg-40h, Additional Control Register.
If absent or zero, the register is left untouched.
$ref: /schemas/types.yaml#/definitions/uint32
jack-det-ctrl:
description:
Default register value for Reg-5Ah, Jack Detect Control Register.
If absent or zero, the register is left untouched.
$ref: /schemas/types.yaml#/definitions/uint32
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
codec@1a {
compatible = "realtek,alc5623";
reg = <0x1a>;
add-ctrl = <0x3700>;
jack-det-ctrl = <0x4810>;
};
};

View File

@@ -0,0 +1,98 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,omap-twl4030.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments SoC with twl4030 based audio setups
maintainers:
- Peter Ujfalusi <peter.ujfalusi@gmail.com>
description:
Audio setups on TI OMAP SoCs using TWL4030-family
audio codec connected via a McBSP port.
properties:
compatible:
const: ti,omap-twl4030
ti,model:
$ref: /schemas/types.yaml#/definitions/string
description: Name of the sound card (for example "omap3beagle").
ti,mcbsp:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle for the McBSP node.
ti,codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle for the twl4030 audio node.
ti,mcbsp-voice:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle to the McBSP node connected to the voice port.
ti,jack-det-gpio:
description: GPIO specifier for jack detection.
maxItems: 1
ti,audio-routing:
description: |
A list of audio routing connections. Each entry is a pair of strings,
with the first being the connection's sink and the second being the
source. If not provided, all possible connections are available.
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
items:
enum:
# Board Connectors
- Headset Stereophone
- Earpiece Spk
- Handsfree Spk
- Ext Spk
- Main Mic
- Sub Mic
- Headset Mic
- Carkit Mic
- Digital0 Mic
- Digital1 Mic
- Line In
# CODEC Pins
- HSOL
- HSOR
- EARPIECE
- HFL
- HFR
- PREDRIVEL
- PREDRIVER
- CARKITL
- CARKITR
- MAINMIC
- SUBMIC
- HSMIC
- DIGIMIC0
- DIGIMIC1
- CARKITMIC
- AUXL
- AUXR
# Headset Mic Bias
- Mic Bias 1 # Used for Main Mic or Digimic0
- Mic Bias 2 # Used for Sub Mic or Digimic1
required:
- compatible
- ti,model
- ti,mcbsp
additionalProperties: false
examples:
- |
sound {
compatible = "ti,omap-twl4030";
ti,model = "omap3beagle";
ti,mcbsp = <&mcbsp2>;
};

View File

@@ -0,0 +1,55 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,pcm1754.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments PCM1754 Stereo DAC
description:
The PCM1754 is a simple stereo DAC that is controlled via hardware gpios.
maintainers:
- Stefan Kerkmann <s.kerkmann@pengutronix.de>
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
enum:
- ti,pcm1754
vcc-supply: true
'#sound-dai-cells':
const: 0
format-gpios:
maxItems: 1
description:
GPIO used to select the PCM format
mute-gpios:
maxItems: 1
description:
GPIO used to mute all outputs
required:
- compatible
- '#sound-dai-cells'
- vcc-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
codec {
compatible = "ti,pcm1754";
#sound-dai-cells = <0>;
vcc-supply = <&vcc_reg>;
mute-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
format-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
};

View File

@@ -1,5 +1,5 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2022 - 2023 Texas Instruments Incorporated
# Copyright (C) 2022 - 2025 Texas Instruments Incorporated
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,tas2781.yaml#
@@ -11,30 +11,77 @@ maintainers:
- Shenghao Ding <shenghao-ding@ti.com>
description: |
The TAS2118/TAS2X20 is mono, digital input Class-D audio
amplifier optimized for efficiently driving high peak power into
small loudspeakers.
The TAS257x is mono, digital input Class-D audio amplifier optimized
for efficiently driving high peak power into small loudspeakers.
Integrated speaker voltage and current sense provides for real time
monitoring of loudspeaker behavior.
The TAS2563/TAS2781 is a mono, digital input Class-D audio
amplifier optimized for efficiently driving high peak power into
small loudspeakers. An integrated on-chip DSP supports Texas
Instruments Smart Amp speaker protection algorithm. The
integrated speaker voltage and current sense provides for real time
monitoring of loudspeaker behavior.
The TAS5825/TAS5827 is a stereo, digital input Class-D audio
amplifier optimized for efficiently driving high peak power into
small loudspeakers. An integrated on-chip DSP supports Texas
Instruments Smart Amp speaker protection algorithm.
Specifications about the audio amplifier can be found at:
https://www.ti.com/lit/gpn/tas2120
https://www.ti.com/lit/gpn/tas2320
https://www.ti.com/lit/gpn/tas2563
https://www.ti.com/lit/gpn/tas2572
https://www.ti.com/lit/gpn/tas2781
https://www.ti.com/lit/gpn/tas5825m
https://www.ti.com/lit/gpn/tas5827
properties:
compatible:
description: |
ti,tas2020: 3.2-W Mono Digital Input Class-D Speaker Amp with 5.5V PVDD
Support.
ti,tas2118: 5-W Mono Digital Input Class-D Speaker Amp with Integrated
8.4-V Class-H Boost.
ti,tas2120: 8.2-W Mono Digital Input Class-D Speaker Amp with
Integrated 14.75V Class-H Boost.
ti,tas2320: 15-W Mono Digital Input Class-D Speaker Amp with 15V Support.
ti,tas2563: 6.1-W Boosted Class-D Audio Amplifier With Integrated
DSP and IV Sense, 16/20/24/32bit stereo I2S or multichannel TDM.
ti,tas2570: 5.8-W Digital Input smart amp with I/V sense and integrated
11-V Class-H Boost
ti,tas2572: 6.6-W Digital Input smart amp with I/V sense and integrated
13-V Class-H Boost
ti,tas2781: 24-V Class-D Amplifier with Real Time Integrated Speaker
Protection and Audio Processing, 16/20/24/32bit stereo I2S or
multichannel TDM.
ti,tas5825: 38-W Stereo, Inductor-Less, Digital Input, Closed-Loop 4.5V
to 26.4V Class-D Audio Amplifier with 192-kHz Extended Audio Processing.
ti,tas5827: 47-W Stereo, Digital Input, High Efficiency Closed-Loop Class-D
Amplifier with Class-H Algorithm
oneOf:
- items:
- enum:
- ti,tas2020
- ti,tas2118
- ti,tas2120
- ti,tas2320
- ti,tas2563
- ti,tas2570
- ti,tas2572
- ti,tas5825
- ti,tas5827
- const: ti,tas2781
- enum:
- ti,tas2781
@@ -61,12 +108,30 @@ required:
allOf:
- $ref: dai-common.yaml#
- if:
properties:
compatible:
contains:
enum:
- ti,tas2020
- ti,tas2118
- ti,tas2120
- ti,tas2320
then:
properties:
reg:
maxItems: 4
items:
minimum: 0x48
maximum: 0x4b
- if:
properties:
compatible:
contains:
enum:
- ti,tas2563
- ti,tas5825
then:
properties:
reg:
@@ -79,6 +144,21 @@ allOf:
minimum: 0x4c
maximum: 0x4f
- if:
properties:
compatible:
contains:
enum:
- ti,tas2570
- ti,tas2572
then:
properties:
reg:
maxItems: 4
items:
minimum: 0x48
maximum: 0x4b
- if:
properties:
compatible:
@@ -97,6 +177,20 @@ allOf:
minimum: 0x38
maximum: 0x3f
- if:
properties:
compatible:
contains:
enum:
- ti,tas5827
then:
properties:
reg:
maxItems: 6
items:
minimum: 0x60
maximum: 0x65
additionalProperties: false
examples:

View File

@@ -0,0 +1,90 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,twl4030-audio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TWL4030-family Audio Module
maintainers:
- Peter Ujfalusi <peter.ujfalusi@gmail.com>
description:
The audio module within the TWL4030-family of companion chips consists
of an audio codec and a vibra driver. This binding describes the parent
node for these functions.
properties:
compatible:
const: ti,twl4030-audio
codec:
type: object
description: Node containing properties for the audio codec functionality.
properties:
ti,digimic_delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Delay in milliseconds after enabling digital microphones to reduce
artifacts.
ti,ramp_delay_value:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Headset ramp delay configuration to reduce pop noise.
ti,hs_extmute:
type: boolean
description:
Enable the use of an external mute for headset pop reduction.
ti,hs_extmute_gpio:
$ref: /schemas/types.yaml#/definitions/phandle-array
description:
The GPIO specifier for the external mute control.
maxItems: 1
ti,offset_cncl_path:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Offset cancellation path selection. Refer to the Technical
Reference Manual for valid values.
# The 'codec' node itself is optional, but if it exists, it can be empty.
# We don't require any of its sub-properties.
ti,enable-vibra:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
description:
Enable or disable the vibra functionality.
additionalProperties: false
required:
- compatible
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
twl: twl@48 {
reg = <0x48>;
interrupts = <7>; /* SYS_NIRQ cascaded to intc */
interrupt-parent = <&intc>;
twl_audio: audio {
compatible = "ti,twl4030-audio";
ti,enable-vibra = <1>;
codec {
ti,ramp_delay_value = <3>;
};
};
};
};

View File

@@ -9,6 +9,28 @@ title: Wolfson WM8960 audio codec
maintainers:
- patches@opensource.cirrus.com
description: |
Wolfson WM8960 audio codec
Pins on the device (for linking into audio routes):
Outputs:
* HP_L : Left Headphone/Line Output
* HP_R : Right Headphone/Line Output
* SPK_LP : Left Speaker Output (Positive)
* SPK_LN : Left Speaker Output (Negative)
* SPK_RP : Right Speaker Output (Positive)
* SPK_RN : Right Speaker Output (Negative)
* OUT3 : Mono, Left, Right or buffered midrail output for capless mode
Inputs:
* LINPUT1 : Left single-ended or negative differential microphone input
* RINPUT1 : Right single-ended or negative differential microphone input
* LINPUT2 : Left line input or positive differential microphone input
* RINPUT2 : Right line input or positive differential microphone input
* LINPUT3 : Left line input, positive differential microphone, or Jack Detect 2
* RINPUT3 : Right line input, positive differential microphone, or Jack Detect 3
properties:
compatible:
const: wlf,wm8960

View File

@@ -574,6 +574,8 @@ patternProperties:
description: FocalTech Systems Co.,Ltd
"^forlinx,.*":
description: Baoding Forlinx Embedded Technology Co., Ltd.
"^foursemi,.*":
description: Shanghai FourSemi Semiconductor Co.,Ltd.
"^foxlink,.*":
description: Foxlink Group
"^freebox,.*":

View File

@@ -2297,38 +2297,81 @@ skip_validation
of the unit descriptor instead of a driver probe error, so that we
can check its details.
quirk_flags
Contains the bit flags for various device specific workarounds.
Applied to the corresponding card index.
The option provides a refined and flexible control for applying quirk
flags. It allows to specify the quirk flags for each device, and can
be modified dynamically via sysfs.
The old usage accepts an array of integers, each of which applies quirk
flags on the device in the order of probing.
E.g., ``quirk_flags=0x01,0x02`` applies get_sample_rate to the first
device, and share_media_device to the second device.
The new usage accepts a string in the format of
``VID1:PID1:FLAGS1;VID2:PID2:FLAGS2;...``, where ``VIDx`` and ``PIDx``
specify the device, and ``FLAGSx`` specify the flags to be applied.
``VIDx`` and ``PIDx`` are 4-digit hexadecimal numbers, and can be
specified as ``*`` to match any value. ``FLAGSx`` can be a set of
flags given by name, separated by ``|``, or a hexadecimal number
representing the bit flags. The available flag names are listed below.
An exclamation mark can be prefixed to a flag name to negate the flag.
For example, ``1234:abcd:mixer_playback_min_mute|!ignore_ctl_error;*:*:0x01;``
applies the ``mixer_playback_min_mute`` flag and clears the
``ignore_ctl_error`` flag for the device 1234:abcd, and applies the
``skip_sample_rate`` flag for all devices.
* bit 0: Skip reading sample rate for devices
* bit 1: Create Media Controller API entries
* bit 2: Allow alignment on audio sub-slot at transfer
* bit 3: Add length specifier to transfers
* bit 4: Start playback stream at first in implement feedback mode
* bit 5: Skip clock selector setup
* bit 6: Ignore errors from clock source search
* bit 7: Indicates ITF-USB DSD based DACs
* bit 8: Add a delay of 20ms at each control message handling
* bit 9: Add a delay of 1-2ms at each control message handling
* bit 10: Add a delay of 5-6ms at each control message handling
* bit 11: Add a delay of 50ms at each interface setup
* bit 12: Perform sample rate validations at probe
* bit 13: Disable runtime PM autosuspend
* bit 14: Ignore errors for mixer access
* bit 15: Support generic DSD raw U32_BE format
* bit 16: Set up the interface at first like UAC1
* bit 17: Apply the generic implicit feedback sync mode
* bit 18: Don't apply implicit feedback sync mode
* bit 19: Don't closed interface during setting sample rate
* bit 20: Force an interface reset whenever stopping & restarting
a stream
* bit 21: Do not set PCM rate (frequency) when only one rate is
available for the given endpoint.
* bit 22: Set the fixed resolution 16 for Mic Capture Volume
* bit 23: Set the fixed resolution 384 for Mic Capture Volume
* bit 24: Set minimum volume control value as mute for devices
where the lowest playback value represents muted state instead
of minimum audible volume
* bit 0: ``get_sample_rate``
Skip reading sample rate for devices
* bit 1: ``share_media_device``
Create Media Controller API entries
* bit 2: ``align_transfer``
Allow alignment on audio sub-slot at transfer
* bit 3: ``tx_length``
Add length specifier to transfers
* bit 4: ``playback_first``
Start playback stream at first in implement feedback mode
* bit 5: ``skip_clock_selector``
Skip clock selector setup
* bit 6: ``ignore_clock_source``
Ignore errors from clock source search
* bit 7: ``itf_usb_dsd_dac``
Indicates ITF-USB DSD-based DACs
* bit 8: ``ctl_msg_delay``
Add a delay of 20ms at each control message handling
* bit 9: ``ctl_msg_delay_1m``
Add a delay of 1-2ms at each control message handling
* bit 10: ``ctl_msg_delay_5m``
Add a delay of 5-6ms at each control message handling
* bit 11: ``iface_delay``
Add a delay of 50ms at each interface setup
* bit 12: ``validate_rates``
Perform sample rate validations at probe
* bit 13: ``disable_autosuspend``
Disable runtime PM autosuspend
* bit 14: ``ignore_ctl_error``
Ignore errors for mixer access
* bit 15: ``dsd_raw``
Support generic DSD raw U32_BE format
* bit 16: ``set_iface_first``
Set up the interface at first like UAC1
* bit 17: ``generic_implicit_fb``
Apply the generic implicit feedback sync mode
* bit 18: ``skip_implicit_fb``
Don't apply implicit feedback sync mode
* bit 19: ``iface_skip_close``
Don't close interface during setting sample rate
* bit 20: ``force_iface_reset``
Force an interface reset whenever stopping & restarting a stream
* bit 21: ``fixed_rate``
Do not set PCM rate (frequency) when only one rate is available
for the given endpoint
* bit 22: ``mic_res_16``
Set the fixed resolution 16 for Mic Capture Volume
* bit 23: ``mic_res_384``
Set the fixed resolution 384 for Mic Capture Volume
* bit 24: ``mixer_playback_min_mute``
Set minimum volume control value as mute for devices where the
lowest playback value represents muted state instead of minimum
audible volume
* bit 25: ``mixer_capture_min_mute``
Similar to bit 24 but for capture streams
This module supports multiple devices, autoprobe and hotplugging.

View File

@@ -131,8 +131,8 @@ The codec driver also supports the following ALSA PCM operations:-
int (*prepare)(struct snd_pcm_substream *);
};
Please refer to the ALSA driver PCM documentation for details.
https://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html
Please refer to the :doc:`ALSA driver PCM documentation
<../kernel-api/writing-an-alsa-driver>` for details.
DAPM description

View File

@@ -45,8 +45,8 @@ snd_soc_component_driver:-
...
};
Please refer to the ALSA driver documentation for details of audio DMA.
https://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html
Please refer to the :doc:`ALSA driver documentation
<../kernel-api/writing-an-alsa-driver>` for details of audio DMA.
An example DMA driver is soc/pxa/pxa2xx-pcm.c

View File

@@ -9669,6 +9669,14 @@ F: lib/tests/memcpy_kunit.c
K: \bunsafe_memcpy\b
K: \b__NO_FORTIFY\b
FOURSEMI AUDIO AMPLIFIER DRIVER
M: Nick Li <nick.li@foursemi.com>
L: linux-sound@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/sound/foursemi,fs2105s.yaml
F: sound/soc/codecs/fs-amp-lib.*
F: sound/soc/codecs/fs210x.*
FPGA DFL DRIVERS
M: Xu Yilun <yilun.xu@intel.com>
R: Tom Rix <trix@redhat.com>
@@ -20635,6 +20643,8 @@ F: include/dt-bindings/sound/qcom,wcd93*
F: sound/soc/codecs/lpass-*.*
F: sound/soc/codecs/msm8916-wcd-analog.c
F: sound/soc/codecs/msm8916-wcd-digital.c
F: sound/soc/codecs/pm4125-sdw.c
F: sound/soc/codecs/pm4125.*
F: sound/soc/codecs/wcd-clsh-v2.*
F: sound/soc/codecs/wcd-mbhc-v2.*
F: sound/soc/codecs/wcd93*.*

View File

@@ -461,9 +461,16 @@ int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
ctrl = qmc_read16(&bd->cbd_sc);
if (ctrl & (QMC_BD_TX_R | QMC_BD_TX_UB)) {
/* We are full ... */
ret = -EBUSY;
goto end;
if (!(ctrl & (QMC_BD_TX_R | QMC_BD_TX_I)) && bd == chan->txbd_done) {
if (ctrl & QMC_BD_TX_W)
chan->txbd_done = chan->txbds;
else
chan->txbd_done++;
} else {
/* We are full ... */
ret = -EBUSY;
goto end;
}
}
qmc_write16(&bd->cbd_datlen, length);
@@ -475,6 +482,10 @@ int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
/* Activate the descriptor */
ctrl |= (QMC_BD_TX_R | QMC_BD_TX_UB);
if (complete)
ctrl |= QMC_BD_TX_I;
else
ctrl &= ~QMC_BD_TX_I;
wmb(); /* Be sure to flush the descriptor before control update */
qmc_write16(&bd->cbd_sc, ctrl);
@@ -569,9 +580,16 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
ctrl = qmc_read16(&bd->cbd_sc);
if (ctrl & (QMC_BD_RX_E | QMC_BD_RX_UB)) {
/* We are full ... */
ret = -EBUSY;
goto end;
if (!(ctrl & (QMC_BD_RX_E | QMC_BD_RX_I)) && bd == chan->rxbd_done) {
if (ctrl & QMC_BD_RX_W)
chan->rxbd_done = chan->rxbds;
else
chan->rxbd_done++;
} else {
/* We are full ... */
ret = -EBUSY;
goto end;
}
}
qmc_write16(&bd->cbd_datlen, 0); /* data length is updated by the QMC */
@@ -587,6 +605,10 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
/* Activate the descriptor */
ctrl |= (QMC_BD_RX_E | QMC_BD_RX_UB);
if (complete)
ctrl |= QMC_BD_RX_I;
else
ctrl &= ~QMC_BD_RX_I;
wmb(); /* Be sure to flush data before descriptor activation */
qmc_write16(&bd->cbd_sc, ctrl);
@@ -1482,19 +1504,19 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan)
/* Init Rx BDs and set Wrap bit on last descriptor */
BUILD_BUG_ON(QMC_NB_RXBDS == 0);
val = QMC_BD_RX_I;
for (i = 0; i < QMC_NB_RXBDS; i++) {
bd = chan->rxbds + i;
qmc_write16(&bd->cbd_sc, val);
qmc_write16(&bd->cbd_sc, 0);
}
bd = chan->rxbds + QMC_NB_RXBDS - 1;
qmc_write16(&bd->cbd_sc, val | QMC_BD_RX_W);
qmc_write16(&bd->cbd_sc, QMC_BD_RX_W);
/* Init Tx BDs and set Wrap bit on last descriptor */
BUILD_BUG_ON(QMC_NB_TXBDS == 0);
val = QMC_BD_TX_I;
if (chan->mode == QMC_HDLC)
val |= QMC_BD_TX_L | QMC_BD_TX_TC;
val = QMC_BD_TX_L | QMC_BD_TX_TC;
else
val = 0;
for (i = 0; i < QMC_NB_TXBDS; i++) {
bd = chan->txbds + i;
qmc_write16(&bd->cbd_sc, val);

View File

@@ -1360,6 +1360,18 @@ int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base)
}
EXPORT_SYMBOL(sdw_slave_get_scale_index);
int sdw_slave_get_current_bank(struct sdw_slave *slave)
{
int tmp;
tmp = sdw_read(slave, SDW_SCP_CTRL);
if (tmp < 0)
return tmp;
return FIELD_GET(SDW_SCP_STAT_CURR_BANK, tmp);
}
EXPORT_SYMBOL_GPL(sdw_slave_get_current_bank);
static int sdw_slave_set_frequency(struct sdw_slave *slave)
{
int scale_index;

View File

@@ -273,4 +273,10 @@ int sdw_of_find_slaves(struct sdw_bus *bus)
return 0;
}
struct device *of_sdw_find_device_by_node(struct device_node *np)
{
return bus_find_device_by_of_node(&sdw_bus_type, np);
}
EXPORT_SYMBOL_GPL(of_sdw_find_device_by_node);
MODULE_IMPORT_NS("SND_SOC_SDCA");

View File

@@ -19,6 +19,7 @@
struct dentry;
struct fwnode_handle;
struct device_node;
struct sdw_bus;
struct sdw_slave;
@@ -1086,6 +1087,10 @@ int sdw_stream_add_slave(struct sdw_slave *slave,
int sdw_stream_remove_slave(struct sdw_slave *slave,
struct sdw_stream_runtime *stream);
struct device *of_sdw_find_device_by_node(struct device_node *np);
int sdw_slave_get_current_bank(struct sdw_slave *sdev);
int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base);
/* messaging and data APIs */
@@ -1119,6 +1124,18 @@ static inline int sdw_stream_remove_slave(struct sdw_slave *slave,
return -EINVAL;
}
static inline struct device *of_sdw_find_device_by_node(struct device_node *np)
{
WARN_ONCE(1, "SoundWire API is disabled");
return NULL;
}
static inline int sdw_slave_get_current_bank(struct sdw_slave *sdev)
{
WARN_ONCE(1, "SoundWire API is disabled");
return -EINVAL;
}
/* messaging and data APIs */
static inline int sdw_read(struct sdw_slave *slave, u32 addr)
{

View File

@@ -161,7 +161,7 @@ struct snd_compr_ops {
struct snd_compr_metadata *metadata);
int (*trigger)(struct snd_compr_stream *stream, int cmd);
int (*pointer)(struct snd_compr_stream *stream,
struct snd_compr_tstamp *tstamp);
struct snd_compr_tstamp64 *tstamp);
int (*copy)(struct snd_compr_stream *stream, char __user *buf,
size_t count);
int (*mmap)(struct snd_compr_stream *stream,

View File

@@ -49,6 +49,7 @@ int cs_amp_write_cal_coeffs(struct cs_dsp *dsp,
const struct cirrus_amp_cal_data *data);
int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_index,
struct cirrus_amp_cal_data *out_data);
int cs_amp_get_vendor_spkid(struct device *dev);
struct cs_amp_test_hooks {
efi_status_t (*get_efi_variable)(efi_char16_t *name,

View File

@@ -85,7 +85,9 @@
#define CS35L56_DSP1_XMEM_UNPACKED24_0 0x2800000
#define CS35L56_DSP1_FW_VER 0x2800010
#define CS35L56_DSP1_HALO_STATE 0x28021E0
#define CS35L56_B2_DSP1_HALO_STATE 0x2803D20
#define CS35L56_DSP1_PM_CUR_STATE 0x2804308
#define CS35L56_B2_DSP1_PM_CUR_STATE 0x2804678
#define CS35L56_DSP1_XMEM_UNPACKED24_8191 0x2807FFC
#define CS35L56_DSP1_CORE_BASE 0x2B80000
#define CS35L56_DSP1_SCRATCH1 0x2B805C0
@@ -337,9 +339,6 @@ extern const struct regmap_config cs35l56_regmap_sdw;
extern const struct regmap_config cs35l63_regmap_i2c;
extern const struct regmap_config cs35l63_regmap_sdw;
extern const struct cs35l56_fw_reg cs35l56_fw_reg;
extern const struct cs35l56_fw_reg cs35l63_fw_reg;
extern const struct cirrus_amp_cal_controls cs35l56_calibration_controls;
extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC];

View File

@@ -69,6 +69,10 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
* @peripheral_config: peripheral configuration for programming peripheral
* for dmaengine transfer
* @peripheral_size: peripheral configuration buffer size
* @port_window_size: The length of the register area in words the data need
* to be accessed on the device side. It is only used for devices which is using
* an area instead of a single register to send/receive the data. Typically the
* DMA loops in this area in order to transfer the data.
*/
struct snd_dmaengine_dai_dma_data {
dma_addr_t addr;
@@ -80,6 +84,7 @@ struct snd_dmaengine_dai_dma_data {
unsigned int flags;
void *peripheral_config;
size_t peripheral_size;
u32 port_window_size;
};
void snd_dmaengine_pcm_set_config_from_dai_data(

View File

@@ -1842,8 +1842,7 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg,
void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
static inline void snd_emu1010_fpga_lock(struct snd_emu10k1 *emu) { mutex_lock(&emu->emu1010.lock); };
static inline void snd_emu1010_fpga_unlock(struct snd_emu10k1 *emu) { mutex_unlock(&emu->emu1010.lock); };
DEFINE_GUARD(snd_emu1010_fpga_lock, struct snd_emu10k1 *, mutex_lock(&(_T)->emu1010.lock), mutex_unlock(&(_T)->emu1010.lock))
void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value);
void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value);

View File

@@ -515,7 +515,6 @@ struct _SND_IW_LFO_PROGRAM {
/* gus_mem.c */
void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup);
int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * block);
struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owner,
char *name, int size, int w_16,

View File

@@ -360,8 +360,8 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
hda_nid_t nid, int recursive);
unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
u8 *dev_list, int max_devices);
unsigned int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
u8 *dev_list, unsigned int max_devices);
int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t nid, int dev_id);
@@ -503,6 +503,36 @@ static inline bool hda_codec_need_resume(struct hda_codec *codec)
return !codec->relaxed_resume && codec->jacktbl.used;
}
/*
* PM with auto-cleanup: call like CLASS(snd_hda_power, pm)(codec)
* If the error handling is needed, refer pm.err.
*/
struct __hda_power_obj {
struct hda_codec *codec;
int err;
};
static inline struct __hda_power_obj __snd_hda_power_up(struct hda_codec *codec)
{
struct __hda_power_obj T = { .codec = codec };
T.err = snd_hda_power_up(codec);
return T;
}
static inline struct __hda_power_obj __snd_hda_power_up_pm(struct hda_codec *codec)
{
struct __hda_power_obj T = { .codec = codec };
T.err = snd_hda_power_up_pm(codec);
return T;
}
DEFINE_CLASS(snd_hda_power, struct __hda_power_obj,
snd_hda_power_down((_T).codec), __snd_hda_power_up(codec),
struct hda_codec *codec)
DEFINE_CLASS(snd_hda_power_pm, struct __hda_power_obj,
snd_hda_power_down_pm((_T).codec), __snd_hda_power_up_pm(codec),
struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_PATCH_LOADER
/*
* patch firmware

View File

@@ -651,6 +651,7 @@ int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value);
#define snd_hdac_dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex)
#define snd_hdac_dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex)
#define snd_hdac_stream_is_locked(dev) ((dev)->locked)
DEFINE_GUARD(snd_hdac_dsp_lock, struct hdac_stream *, snd_hdac_dsp_lock(_T), snd_hdac_dsp_unlock(_T))
/* DSP loader helpers */
int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
unsigned int byte_size, struct snd_dma_buffer *bufp);

View File

@@ -47,7 +47,7 @@ struct snd_compress_ops {
struct snd_compr_stream *stream, int cmd);
int (*pointer)(struct snd_soc_component *component,
struct snd_compr_stream *stream,
struct snd_compr_tstamp *tstamp);
struct snd_compr_tstamp64 *tstamp);
int (*copy)(struct snd_soc_component *component,
struct snd_compr_stream *stream, char __user *buf,
size_t count);
@@ -261,89 +261,18 @@ struct snd_soc_component {
list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list)
/**
* snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
* embedded in
* @dapm: The DAPM context to cast to the component
*
* This function must only be used on DAPM contexts that are known to be part of
* a component (e.g. in a component driver). Otherwise the behavior is
* undefined.
*/
static inline struct snd_soc_component *snd_soc_dapm_to_component(
struct snd_soc_dapm_context *dapm)
{
return container_of(dapm, struct snd_soc_component, dapm);
}
/**
* snd_soc_component_get_dapm() - Returns the DAPM context associated with a
* 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_get_dapm(
static inline struct snd_soc_dapm_context *snd_soc_component_to_dapm(
struct snd_soc_component *component)
{
return &component->dapm;
}
/**
* snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level
* @component: The COMPONENT for which to initialize the DAPM bias level
* @level: The DAPM level to initialize to
*
* Initializes the COMPONENT DAPM bias level. See snd_soc_dapm_init_bias_level()
*/
static inline void
snd_soc_component_init_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
snd_soc_dapm_init_bias_level(
snd_soc_component_get_dapm(component), level);
}
/**
* snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level
* @component: The COMPONENT for which to get the DAPM bias level
*
* Returns: The current DAPM bias level of the COMPONENT.
*/
static inline enum snd_soc_bias_level
snd_soc_component_get_bias_level(struct snd_soc_component *component)
{
return snd_soc_dapm_get_bias_level(
snd_soc_component_get_dapm(component));
}
/**
* snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level
* @component: The COMPONENT for which to set the level
* @level: The level to set to
*
* Forces the COMPONENT bias level to a specific state. See
* snd_soc_dapm_force_bias_level().
*/
static inline int
snd_soc_component_force_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
return snd_soc_dapm_force_bias_level(
snd_soc_component_get_dapm(component),
level);
}
/**
* snd_soc_dapm_kcontrol_component() - Returns the component associated to a
* kcontrol
* @kcontrol: The kcontrol
*
* This function must only be used on DAPM contexts that are known to be part of
* a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined
*/
static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component(
struct snd_kcontrol *kcontrol)
{
return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol));
}
// FIXME
#define snd_soc_component_get_dapm snd_soc_component_to_dapm
/**
* snd_soc_component_cache_sync() - Sync the register cache with the hardware
@@ -498,7 +427,7 @@ int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream,
struct snd_compr_codec_caps *codec);
int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes);
int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream,
struct snd_compr_tstamp *tstamp);
struct snd_compr_tstamp64 *tstamp);
int snd_soc_component_compr_copy(struct snd_compr_stream *cstream,
char __user *buf, size_t count);
int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream,

View File

@@ -256,7 +256,7 @@ int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,
size_t bytes);
int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream,
struct snd_compr_tstamp *tstamp);
struct snd_compr_tstamp64 *tstamp);
int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream,
struct snd_compr_metadata *metadata);
@@ -383,8 +383,9 @@ struct snd_soc_cdai_ops {
struct snd_compr_metadata *, struct snd_soc_dai *);
int (*trigger)(struct snd_compr_stream *, int,
struct snd_soc_dai *);
int (*pointer)(struct snd_compr_stream *,
struct snd_compr_tstamp *, struct snd_soc_dai *);
int (*pointer)(struct snd_compr_stream *stream,
struct snd_compr_tstamp64 *tstamp,
struct snd_soc_dai *dai);
int (*ack)(struct snd_compr_stream *, size_t,
struct snd_soc_dai *);
};

View File

@@ -583,11 +583,9 @@ struct snd_soc_dapm_update {
struct snd_soc_dapm_context {
enum snd_soc_bias_level bias_level;
/* bit field */
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
unsigned int suspend_bias_off:1; /* Use BIAS_OFF in suspend if the DAPM is idle */
bool idle_bias; /* Use BIAS_OFF instead of STANDBY when false */
struct device *dev; /* from parent - for debug */
struct device *dev; /* from parent - for debug */ /* REMOVE ME */
struct snd_soc_component *component; /* parent component */
struct snd_soc_card *card; /* parent card */
@@ -660,6 +658,12 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card);
int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai);
int snd_soc_dapm_widget_name_cmp(struct snd_soc_dapm_widget *widget, const char *s);
struct device *snd_soc_dapm_to_dev(struct snd_soc_dapm_context *dapm);
struct snd_soc_card *snd_soc_dapm_to_card(struct snd_soc_dapm_context *dapm);
struct snd_soc_component *snd_soc_dapm_to_component(struct snd_soc_dapm_context *dapm);
bool snd_soc_dapm_get_idle_bias(struct snd_soc_dapm_context *dapm);
void snd_soc_dapm_set_idle_bias(struct snd_soc_dapm_context *dapm, bool on);
/* dapm path setup */
int snd_soc_dapm_new_widgets(struct snd_soc_card *card);
@@ -699,7 +703,6 @@ int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm);
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin);
int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin);
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, const char *pin);
unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol);
void snd_soc_dapm_mark_endpoints_dirty(struct snd_soc_card *card);
/*
@@ -718,47 +721,29 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
bool (*custom_stop_condition)(struct snd_soc_dapm_widget *, enum snd_soc_dapm_direction));
void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list);
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(struct snd_kcontrol *kcontrol);
struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_widget(struct snd_kcontrol *kcontrol);
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_to_dapm(struct snd_kcontrol *kcontrol);
struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_to_widget(struct snd_kcontrol *kcontrol);
struct snd_soc_component *snd_soc_dapm_kcontrol_to_component(struct snd_kcontrol *kcontrol);
unsigned int snd_soc_dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol);
int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level);
enum snd_soc_bias_level snd_soc_dapm_get_bias_level(struct snd_soc_dapm_context *dapm);
void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level);
// REMOVE ME !!
#define snd_soc_component_force_bias_level(c, l) snd_soc_dapm_force_bias_level(&(c)->dapm, l)
#define snd_soc_component_get_bias_level(c) snd_soc_dapm_get_bias_level(&(c)->dapm)
#define snd_soc_component_init_bias_level(c, l) snd_soc_dapm_init_bias_level(&(c)->dapm, l)
#define snd_soc_dapm_kcontrol_widget snd_soc_dapm_kcontrol_to_widget
#define snd_soc_dapm_kcontrol_dapm snd_soc_dapm_kcontrol_to_dapm
#define dapm_kcontrol_get_value snd_soc_dapm_kcontrol_get_value
#define snd_soc_dapm_kcontrol_component snd_soc_dapm_kcontrol_to_component
#define for_each_dapm_widgets(list, i, widget) \
for ((i) = 0; \
(i) < list->num_widgets && (widget = list->widgets[i]); \
(i)++)
/**
* snd_soc_dapm_init_bias_level() - Initialize DAPM bias level
* @dapm: The DAPM context to initialize
* @level: The DAPM level to initialize to
*
* This function only sets the driver internal state of the DAPM level and will
* not modify the state of the device. Hence it should not be used during normal
* operation, but only to synchronize the internal state to the device state.
* E.g. during driver probe to set the DAPM level to the one corresponding with
* the power-on reset state of the device.
*
* To change the DAPM state of the device use snd_soc_dapm_set_bias_level().
*/
static inline void snd_soc_dapm_init_bias_level(
struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
{
dapm->bias_level = level;
}
/**
* snd_soc_dapm_get_bias_level() - Get current DAPM bias level
* @dapm: The context for which to get the bias level
*
* Returns: The current bias level of the passed DAPM context.
*/
static inline enum snd_soc_bias_level snd_soc_dapm_get_bias_level(
struct snd_soc_dapm_context *dapm)
{
return dapm->bias_level;
}
/**
* snd_soc_dapm_widget_for_each_path - Iterates over all paths in the
* specified direction of a widget

View File

@@ -1120,6 +1120,11 @@ static inline int snd_soc_card_is_instantiated(struct snd_soc_card *card)
return card && card->instantiated;
}
static inline struct snd_soc_dapm_context *snd_soc_card_to_dapm(struct snd_soc_card *card)
{
return &card->dapm;
}
/* SoC machine DAI configuration, glues a codec and cpu DAI together */
struct snd_soc_pcm_runtime {
struct device *dev;

View File

@@ -248,5 +248,13 @@ int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_so
int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
/* TI */
int asoc_sdw_ti_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_ti_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_ti_amp_initial_settings(struct snd_soc_card *card,
const char *name_prefix);
#endif

View File

@@ -326,10 +326,14 @@ struct sof_ipc4_base_module_cfg {
#define SOF_IPC4_MOD_INSTANCE_SHIFT 16
#define SOF_IPC4_MOD_INSTANCE_MASK GENMASK(23, 16)
#define SOF_IPC4_MOD_INSTANCE(x) ((x) << SOF_IPC4_MOD_INSTANCE_SHIFT)
#define SOF_IPC4_MOD_INSTANCE_GET(x) (((x) & SOF_IPC4_MOD_INSTANCE_MASK) \
>> SOF_IPC4_MOD_INSTANCE_SHIFT)
#define SOF_IPC4_MOD_ID_SHIFT 0
#define SOF_IPC4_MOD_ID_MASK GENMASK(15, 0)
#define SOF_IPC4_MOD_ID(x) ((x) << SOF_IPC4_MOD_ID_SHIFT)
#define SOF_IPC4_MOD_ID_GET(x) (((x) & SOF_IPC4_MOD_ID_MASK) \
>> SOF_IPC4_MOD_ID_SHIFT)
/* init module ipc msg */
#define SOF_IPC4_MOD_EXT_PARAM_SIZE_SHIFT 0

View File

@@ -114,5 +114,23 @@ int snd_sf_calc_parm_decay(int msec);
extern int snd_sf_vol_table[128];
int snd_sf_linear_to_log(unsigned int amount, int offset, int ratio);
/* lock access to sflist */
static inline void snd_soundfont_lock_preset(struct snd_sf_list *sflist)
{
mutex_lock(&sflist->presets_mutex);
guard(spinlock_irqsave)(&sflist->lock);
sflist->presets_locked = 1;
}
/* remove lock */
static inline void snd_soundfont_unlock_preset(struct snd_sf_list *sflist)
{
guard(spinlock_irqsave)(&sflist->lock);
sflist->presets_locked = 0;
mutex_unlock(&sflist->presets_mutex);
}
DEFINE_GUARD(snd_soundfont_lock_preset, struct snd_sf_list *,
snd_soundfont_lock_preset(_T), snd_soundfont_unlock_preset(_T))
#endif /* __SOUND_SOUNDFONT_H */

View File

@@ -34,6 +34,7 @@
#define PPC3_VERSION_TAS2781_BASIC_MIN 0x14600
#define PPC3_VERSION_TAS2781_ALPHA_MIN 0x4a00
#define PPC3_VERSION_TAS2781_BETA_MIN 0x19400
#define PPC3_VERSION_TAS5825_BASE 0x114200
#define TASDEVICE_DEVICE_SUM 8
#define TASDEVICE_CONFIG_SUM 64
@@ -53,6 +54,8 @@ enum tasdevice_dsp_dev_idx {
TASDEVICE_DSP_TAS_2781_DUAL_MONO,
TASDEVICE_DSP_TAS_2781_21,
TASDEVICE_DSP_TAS_2781_QUAD,
TASDEVICE_DSP_TAS_5825_MONO,
TASDEVICE_DSP_TAS_5825_DUAL,
TASDEVICE_DSP_TAS_MAX_DEVICE
};
@@ -198,6 +201,14 @@ struct tasdevice_rca {
int ncfgs;
struct tasdevice_config_info **cfg_info;
int profile_cfg_id;
/*
* Since version 0x105, the keyword 'init' was introduced into the
* profile, which is used for chip initialization, particularly to
* store common settings for other non-initialization profiles.
* if (init_profile_id < 0)
* No init profile inside the RCA firmware.
*/
int init_profile_id;
};
void tasdevice_select_cfg_blk(void *context, int conf_no,

View File

@@ -49,10 +49,12 @@
#define TASDEVICE_REG(book, page, reg) (((book * 256 * 128) + \
(page * 128)) + reg)
/* Software Reset */
/* Software Reset, compatble with new device (TAS5825). */
#define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0x0, 0x01)
#define TASDEVICE_REG_SWRESET_RESET BIT(0)
#define TAS5825_REG_SWRESET_RESET (BIT(0) | BIT(4))
/* Checksum */
#define TASDEVICE_CHECKSUM_REG TASDEVICE_REG(0x0, 0x0, 0x7e)
@@ -110,8 +112,17 @@
#define TAS2781_RUNTIME_RE_REG TASDEVICE_REG(0x64, 0x63, 0x44)
enum audio_device {
TAS2020,
TAS2118,
TAS2120,
TAS2320,
TAS2563,
TAS2570,
TAS2572,
TAS2781,
TAS5825,
TAS5827,
TAS_OTHERS,
};
enum dspbin_type {
@@ -194,6 +205,7 @@ struct tasdevice_priv {
unsigned char coef_binaryname[64];
unsigned char rca_binaryname[64];
unsigned char dev_name[32];
const unsigned char (*dvc_tlv_table)[4];
const char *name_prefix;
unsigned char ndev;
unsigned int dspbin_typ;

259
include/sound/tas2x20-tlv.h Normal file
View File

@@ -0,0 +1,259 @@
/* SPDX-License-Identifier: GPL-2.0 */
//
// ALSA SoC Texas Instruments TAS2x20/TAS2118 Audio Smart Amplifier
//
// Copyright (C) 2025 Texas Instruments Incorporated
// https://www.ti.com
//
// The TAS2x20/TAS2118 hda driver implements for one, two, or even multiple
// TAS2x20/TAS2118 chips.
//
// Author: Baojun Xu <baojun.xu@ti.com>
//
#ifndef __TAS2X20_TLV_H__
#define __TAS2X20_TLV_H__
#define TAS2X20_DVC_LEVEL TASDEVICE_REG(0x0, 0x2, 0x0c)
#define TAS2X20_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x07)
static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2x20_dvc_tlv, 1650, 50, 0);
static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2x20_amp_tlv, 2100, 50, 0);
/* pow(10, db/20) * pow(2,22) */
static const __maybe_unused unsigned char tas2x20_dvc_table[][4] = {
{ 0X00, 0X00, 0X0D, 0X00 }, /* -110.0db */
{ 0X00, 0X00, 0X0E, 0X00 }, /* -109.5db */
{ 0X00, 0X00, 0X0E, 0X00 }, /* -109.0db */
{ 0X00, 0X00, 0X0F, 0X00 }, /* -108.5db */
{ 0X00, 0X00, 0X10, 0X00 }, /* -108.0db */
{ 0X00, 0X00, 0X11, 0X00 }, /* -107.5db */
{ 0X00, 0X00, 0X12, 0X00 }, /* -107.0db */
{ 0X00, 0X00, 0X13, 0X00 }, /* -106.5db */
{ 0X00, 0X00, 0X15, 0X00 }, /* -106.0db */
{ 0X00, 0X00, 0X16, 0X00 }, /* -105.5db */
{ 0X00, 0X00, 0X17, 0X00 }, /* -105.0db */
{ 0X00, 0X00, 0X18, 0X00 }, /* -104.5db */
{ 0X00, 0X00, 0X1A, 0X00 }, /* -104.0db */
{ 0X00, 0X00, 0X1C, 0X00 }, /* -103.5db */
{ 0X00, 0X00, 0X1D, 0X00 }, /* -103.0db */
{ 0X00, 0X00, 0X1F, 0X00 }, /* -102.5db */
{ 0X00, 0X00, 0X21, 0X00 }, /* -102.0db */
{ 0X00, 0X00, 0X23, 0X00 }, /* -101.5db */
{ 0X00, 0X00, 0X25, 0X00 }, /* -101.0db */
{ 0X00, 0X00, 0X27, 0X00 }, /* -100.5db */
{ 0X00, 0X00, 0X29, 0X00 }, /* -100.0db */
{ 0X00, 0X00, 0X2C, 0X00 }, /* -99.5db */
{ 0X00, 0X00, 0X2F, 0X00 }, /* -99.0db */
{ 0X00, 0X00, 0X31, 0X00 }, /* -98.5db */
{ 0X00, 0X00, 0X34, 0X00 }, /* -98.0db */
{ 0X00, 0X00, 0X37, 0X00 }, /* -97.5db */
{ 0X00, 0X00, 0X3B, 0X00 }, /* -97.0db */
{ 0X00, 0X00, 0X3E, 0X00 }, /* -96.5db */
{ 0X00, 0X00, 0X42, 0X00 }, /* -96.0db */
{ 0X00, 0X00, 0X46, 0X00 }, /* -95.5db */
{ 0X00, 0X00, 0X4A, 0X00 }, /* -95.0db */
{ 0X00, 0X00, 0X4F, 0X00 }, /* -94.5db */
{ 0X00, 0X00, 0X53, 0X00 }, /* -94.0db */
{ 0X00, 0X00, 0X58, 0X00 }, /* -93.5db */
{ 0X00, 0X00, 0X5D, 0X00 }, /* -93.0db */
{ 0X00, 0X00, 0X63, 0X00 }, /* -92.5db */
{ 0X00, 0X00, 0X69, 0X00 }, /* -92.0db */
{ 0X00, 0X00, 0X6F, 0X00 }, /* -91.5db */
{ 0X00, 0X00, 0X76, 0X00 }, /* -91.0db */
{ 0X00, 0X00, 0X7D, 0X00 }, /* -90.5db */
{ 0X00, 0X00, 0X84, 0X00 }, /* -90.0db */
{ 0X00, 0X00, 0X8C, 0X00 }, /* -89.5db */
{ 0X00, 0X00, 0X94, 0X00 }, /* -89.0db */
{ 0X00, 0X00, 0X9D, 0X00 }, /* -88.5db */
{ 0X00, 0X00, 0XA6, 0X00 }, /* -88.0db */
{ 0X00, 0X00, 0XB0, 0X00 }, /* -87.5db */
{ 0X00, 0X00, 0XBB, 0X00 }, /* -87.0db */
{ 0X00, 0X00, 0XC6, 0X00 }, /* -86.5db */
{ 0X00, 0X00, 0XD2, 0X00 }, /* -86.0db */
{ 0X00, 0X00, 0XDE, 0X00 }, /* -85.5db */
{ 0X00, 0X00, 0XEB, 0X00 }, /* -85.0db */
{ 0X00, 0X00, 0XF9, 0X00 }, /* -84.5db */
{ 0X00, 0X01, 0X08, 0X00 }, /* -84.0db */
{ 0X00, 0X01, 0X18, 0X00 }, /* -83.5db */
{ 0X00, 0X01, 0X28, 0X00 }, /* -83.0db */
{ 0X00, 0X01, 0X3A, 0X00 }, /* -82.5db */
{ 0X00, 0X01, 0X4D, 0X00 }, /* -82.0db */
{ 0X00, 0X01, 0X60, 0X00 }, /* -81.5db */
{ 0X00, 0X01, 0X75, 0X00 }, /* -81.0db */
{ 0X00, 0X01, 0X8B, 0X00 }, /* -80.5db */
{ 0X00, 0X01, 0XA3, 0X00 }, /* -80.0db */
{ 0X00, 0X01, 0XBC, 0X00 }, /* -79.5db */
{ 0X00, 0X01, 0XD6, 0X00 }, /* -79.0db */
{ 0X00, 0X01, 0XF2, 0X00 }, /* -78.5db */
{ 0X00, 0X02, 0X10, 0X00 }, /* -78.0db */
{ 0X00, 0X02, 0X2F, 0X00 }, /* -77.5db */
{ 0X00, 0X02, 0X50, 0X00 }, /* -77.0db */
{ 0X00, 0X02, 0X73, 0X00 }, /* -76.5db */
{ 0X00, 0X02, 0X98, 0X00 }, /* -76.0db */
{ 0X00, 0X02, 0XC0, 0X00 }, /* -75.5db */
{ 0X00, 0X02, 0XE9, 0X00 }, /* -75.0db */
{ 0X00, 0X03, 0X16, 0X00 }, /* -74.5db */
{ 0X00, 0X03, 0X44, 0X00 }, /* -74.0db */
{ 0X00, 0X03, 0X76, 0X00 }, /* -73.5db */
{ 0X00, 0X03, 0XAA, 0X00 }, /* -73.0db */
{ 0X00, 0X03, 0XE2, 0X00 }, /* -72.5db */
{ 0X00, 0X04, 0X1D, 0X00 }, /* -72.0db */
{ 0X00, 0X04, 0X5B, 0X00 }, /* -71.5db */
{ 0X00, 0X04, 0X9E, 0X00 }, /* -71.0db */
{ 0X00, 0X04, 0XE4, 0X00 }, /* -70.5db */
{ 0X00, 0X05, 0X2E, 0X00 }, /* -70.0db */
{ 0X00, 0X05, 0X7C, 0X00 }, /* -69.5db */
{ 0X00, 0X05, 0XD0, 0X00 }, /* -69.0db */
{ 0X00, 0X06, 0X28, 0X00 }, /* -68.5db */
{ 0X00, 0X06, 0X85, 0X00 }, /* -68.0db */
{ 0X00, 0X06, 0XE8, 0X00 }, /* -67.5db */
{ 0X00, 0X07, 0X51, 0X00 }, /* -67.0db */
{ 0X00, 0X07, 0XC0, 0X00 }, /* -66.5db */
{ 0X00, 0X08, 0X36, 0X00 }, /* -66.0db */
{ 0X00, 0X08, 0XB2, 0X00 }, /* -65.5db */
{ 0X00, 0X09, 0X36, 0X00 }, /* -65.0db */
{ 0X00, 0X09, 0XC2, 0X00 }, /* -64.5db */
{ 0X00, 0X0A, 0X56, 0X00 }, /* -64.0db */
{ 0X00, 0X0A, 0XF3, 0X00 }, /* -63.5db */
{ 0X00, 0X0B, 0X99, 0X00 }, /* -63.0db */
{ 0X00, 0X0C, 0X49, 0X00 }, /* -62.5db */
{ 0X00, 0X0D, 0X03, 0X00 }, /* -62.0db */
{ 0X00, 0X0D, 0XC9, 0X00 }, /* -61.5db */
{ 0X00, 0X0E, 0X9A, 0X00 }, /* -61.0db */
{ 0X00, 0X0F, 0X77, 0X00 }, /* -60.5db */
{ 0X00, 0X10, 0X62, 0X00 }, /* -60.0db */
{ 0X00, 0X11, 0X5A, 0X00 }, /* -59.5db */
{ 0X00, 0X12, 0X62, 0X00 }, /* -59.0db */
{ 0X00, 0X13, 0X78, 0X00 }, /* -58.5db */
{ 0X00, 0X14, 0XA0, 0X00 }, /* -58.0db */
{ 0X00, 0X15, 0XD9, 0X00 }, /* -57.5db */
{ 0X00, 0X17, 0X24, 0X00 }, /* -57.0db */
{ 0X00, 0X18, 0X83, 0X00 }, /* -56.5db */
{ 0X00, 0X19, 0XF7, 0X00 }, /* -56.0db */
{ 0X00, 0X1B, 0X81, 0X00 }, /* -55.5db */
{ 0X00, 0X1D, 0X22, 0X00 }, /* -55.0db */
{ 0X00, 0X1E, 0XDC, 0X00 }, /* -54.5db */
{ 0X00, 0X20, 0XB0, 0X00 }, /* -54.0db */
{ 0X00, 0X22, 0XA0, 0X00 }, /* -53.5db */
{ 0X00, 0X24, 0XAD, 0X00 }, /* -53.0db */
{ 0X00, 0X26, 0XDA, 0X00 }, /* -52.5db */
{ 0X00, 0X29, 0X27, 0X00 }, /* -52.0db */
{ 0X00, 0X2B, 0X97, 0X00 }, /* -51.5db */
{ 0X00, 0X2E, 0X2D, 0X00 }, /* -51.0db */
{ 0X00, 0X30, 0XE9, 0X00 }, /* -50.5db */
{ 0X00, 0X33, 0XCF, 0X00 }, /* -50.0db */
{ 0X00, 0X36, 0XE1, 0X00 }, /* -49.5db */
{ 0X00, 0X3A, 0X21, 0X00 }, /* -49.0db */
{ 0X00, 0X3D, 0X93, 0X00 }, /* -48.5db */
{ 0X00, 0X41, 0X39, 0X00 }, /* -48.0db */
{ 0X00, 0X45, 0X17, 0X00 }, /* -47.5db */
{ 0X00, 0X49, 0X2F, 0X00 }, /* -47.0db */
{ 0X00, 0X4D, 0X85, 0X00 }, /* -46.5db */
{ 0X00, 0X52, 0X1D, 0X00 }, /* -46.0db */
{ 0X00, 0X56, 0XFA, 0X00 }, /* -45.5db */
{ 0X00, 0X5C, 0X22, 0X00 }, /* -45.0db */
{ 0X00, 0X61, 0X97, 0X00 }, /* -44.5db */
{ 0X00, 0X67, 0X60, 0X00 }, /* -44.0db */
{ 0X00, 0X6D, 0X80, 0X00 }, /* -43.5db */
{ 0X00, 0X73, 0XFD, 0X00 }, /* -43.0db */
{ 0X00, 0X7A, 0XDC, 0X00 }, /* -42.5db */
{ 0X00, 0X82, 0X24, 0X00 }, /* -42.0db */
{ 0X00, 0X89, 0XDA, 0X00 }, /* -41.5db */
{ 0X00, 0X92, 0X05, 0X00 }, /* -41.0db */
{ 0X00, 0X9A, 0XAC, 0X00 }, /* -40.5db */
{ 0X00, 0XA3, 0XD7, 0X00 }, /* -40.0db */
{ 0X00, 0XAD, 0X8C, 0X00 }, /* -39.5db */
{ 0X00, 0XB7, 0XD4, 0X00 }, /* -39.0db */
{ 0X00, 0XC2, 0XB9, 0X00 }, /* -38.5db */
{ 0X00, 0XCE, 0X43, 0X00 }, /* -38.0db */
{ 0X00, 0XDA, 0X7B, 0X00 }, /* -37.5db */
{ 0X00, 0XE7, 0X6E, 0X00 }, /* -37.0db */
{ 0X00, 0XF5, 0X24, 0X00 }, /* -36.5db */
{ 0X01, 0X03, 0XAB, 0X00 }, /* -36.0db */
{ 0X01, 0X13, 0X0E, 0X00 }, /* -35.5db */
{ 0X01, 0X23, 0X5A, 0X00 }, /* -35.0db */
{ 0X01, 0X34, 0X9D, 0X00 }, /* -34.5db */
{ 0X01, 0X46, 0XE7, 0X00 }, /* -34.0db */
{ 0X01, 0X5A, 0X46, 0X00 }, /* -33.5db */
{ 0X01, 0X6E, 0XCA, 0X00 }, /* -33.0db */
{ 0X01, 0X84, 0X86, 0X00 }, /* -32.5db */
{ 0X01, 0X9B, 0X8C, 0X00 }, /* -32.0db */
{ 0X01, 0XB3, 0XEE, 0X00 }, /* -31.5db */
{ 0X01, 0XCD, 0XC3, 0X00 }, /* -31.0db */
{ 0X01, 0XE9, 0X20, 0X00 }, /* -30.5db */
{ 0X02, 0X06, 0X1B, 0X00 }, /* -30.0db */
{ 0X02, 0X24, 0XCE, 0X00 }, /* -29.5db */
{ 0X02, 0X45, 0X53, 0X00 }, /* -29.0db */
{ 0X02, 0X67, 0XC5, 0X00 }, /* -28.5db */
{ 0X02, 0X8C, 0X42, 0X00 }, /* -28.0db */
{ 0X02, 0XB2, 0XE8, 0X00 }, /* -27.5db */
{ 0X02, 0XDB, 0XD8, 0X00 }, /* -27.0db */
{ 0X03, 0X07, 0X36, 0X00 }, /* -26.5db */
{ 0X03, 0X35, 0X25, 0X00 }, /* -26.0db */
{ 0X03, 0X65, 0XCD, 0X00 }, /* -25.5db */
{ 0X03, 0X99, 0X57, 0X00 }, /* -25.0db */
{ 0X03, 0XCF, 0XEE, 0X00 }, /* -24.5db */
{ 0X04, 0X09, 0XC2, 0X00 }, /* -24.0db */
{ 0X04, 0X47, 0X03, 0X00 }, /* -23.5db */
{ 0X04, 0X87, 0XE5, 0X00 }, /* -23.0db */
{ 0X04, 0XCC, 0XA0, 0X00 }, /* -22.5db */
{ 0X05, 0X15, 0X6D, 0X00 }, /* -22.0db */
{ 0X05, 0X62, 0X8A, 0X00 }, /* -21.5db */
{ 0X05, 0XB4, 0X39, 0X00 }, /* -21.0db */
{ 0X06, 0X0A, 0XBF, 0X00 }, /* -20.5db */
{ 0X06, 0X66, 0X66, 0X00 }, /* -20.0db */
{ 0X06, 0XC7, 0X7B, 0X00 }, /* -19.5db */
{ 0X07, 0X2E, 0X50, 0X00 }, /* -19.0db */
{ 0X07, 0X9B, 0X3D, 0X00 }, /* -18.5db */
{ 0X08, 0X0E, 0X9F, 0X00 }, /* -18.0db */
{ 0X08, 0X88, 0XD7, 0X00 }, /* -17.5db */
{ 0X09, 0X0A, 0X4D, 0X00 }, /* -17.0db */
{ 0X09, 0X93, 0X6E, 0X00 }, /* -16.5db */
{ 0X0A, 0X24, 0XB0, 0X00 }, /* -16.0db */
{ 0X0A, 0XBE, 0X8D, 0X00 }, /* -15.5db */
{ 0X0B, 0X61, 0X88, 0X00 }, /* -15.0db */
{ 0X0C, 0X0E, 0X2B, 0X00 }, /* -14.5db */
{ 0X0C, 0XC5, 0X09, 0X00 }, /* -14.0db */
{ 0X0D, 0X86, 0XBD, 0X00 }, /* -13.5db */
{ 0X0E, 0X53, 0XEB, 0X00 }, /* -13.0db */
{ 0X0F, 0X2D, 0X42, 0X00 }, /* -12.5db */
{ 0X10, 0X13, 0X79, 0X00 }, /* -12.0db */
{ 0X11, 0X07, 0X54, 0X00 }, /* -11.5db */
{ 0X12, 0X09, 0XA3, 0X00 }, /* -11.0db */
{ 0X13, 0X1B, 0X40, 0X00 }, /* -10.5db */
{ 0X14, 0X3D, 0X13, 0X00 }, /* -10.0db */
{ 0X15, 0X70, 0X12, 0X00 }, /* -9.5db */
{ 0X16, 0XB5, 0X43, 0X00 }, /* -9.0db */
{ 0X18, 0X0D, 0XB8, 0X00 }, /* -8.5db */
{ 0X19, 0X7A, 0X96, 0X00 }, /* -8.0db */
{ 0X1A, 0XFD, 0X13, 0X00 }, /* -7.5db */
{ 0X1C, 0X96, 0X76, 0X00 }, /* -7.0db */
{ 0X1E, 0X48, 0X1C, 0X00 }, /* -6.5db */
{ 0X20, 0X13, 0X73, 0X00 }, /* -6.0db */
{ 0X21, 0XFA, 0X02, 0X00 }, /* -5.5db */
{ 0X23, 0XFD, 0X66, 0X00 }, /* -5.0db */
{ 0X26, 0X1F, 0X54, 0X00 }, /* -4.5db */
{ 0X28, 0X61, 0X9A, 0X00 }, /* -4.0db */
{ 0X2A, 0XC6, 0X25, 0X00 }, /* -3.5db */
{ 0X2D, 0X4E, 0XFB, 0X00 }, /* -3.0db */
{ 0X2F, 0XFE, 0X44, 0X00 }, /* -2.5db */
{ 0X32, 0XD6, 0X46, 0X00 }, /* -2.0db */
{ 0X35, 0XD9, 0X6B, 0X00 }, /* -1.5db */
{ 0X39, 0X0A, 0X41, 0X00 }, /* -1.0db */
{ 0X3C, 0X6B, 0X7E, 0X00 }, /* -0.5db */
{ 0X40, 0X00, 0X00, 0X00 }, /* 0.0db */
{ 0X43, 0XCA, 0XD0, 0X00 }, /* 0.5db */
{ 0X47, 0XCF, 0X26, 0X00 }, /* 1.0db */
{ 0X4C, 0X10, 0X6B, 0X00 }, /* 1.5db */
{ 0X50, 0X92, 0X3B, 0X00 }, /* 2.0db */
{ 0X55, 0X58, 0X6A, 0X00 }, /* 2.5db */
{ 0X5A, 0X67, 0X03, 0X00 }, /* 3.0db */
{ 0X5F, 0XC2, 0X53, 0X00 }, /* 3.5db */
{ 0X65, 0X6E, 0XE3, 0X00 }, /* 4.0db */
{ 0X6B, 0X71, 0X86, 0X00 }, /* 4.5db */
{ 0X71, 0XCF, 0X54, 0X00 }, /* 5.0db */
{ 0X78, 0X8D, 0XB4, 0X00 }, /* 5.5db */
{ 0X7F, 0XB2, 0X61, 0X00 }, /* 6.0db */
};
#endif

View File

@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0 */
//
// ALSA SoC Texas Instruments TAS5825 Audio Smart Amplifier
//
// Copyright (C) 2025 Texas Instruments Incorporated
// https://www.ti.com
//
// The TAS5825 hda driver implements for one or two TAS5825 chips.
//
// Author: Baojun Xu <baojun.xu@ti.com>
//
#ifndef __TAS5825_TLV_H__
#define __TAS5825_TLV_H__
#define TAS5825_DVC_LEVEL TASDEVICE_REG(0x0, 0x0, 0x4c)
#define TAS5825_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x54)
static const __maybe_unused DECLARE_TLV_DB_SCALE(
tas5825_dvc_tlv, -10300, 50, 0);
static const __maybe_unused DECLARE_TLV_DB_SCALE(
tas5825_amp_tlv, -1550, 50, 0);
#endif

View File

@@ -1,21 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Platform header for Texas Instruments TLV320DAC33 codec driver
*
* Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
*
* Copyright: (C) 2009 Nokia Corporation
*/
#ifndef __TLV320DAC33_PLAT_H
#define __TLV320DAC33_PLAT_H
struct tlv320dac33_platform_data {
int power_gpio;
int mode1_latency; /* latency caused by the i2c writes in us */
int auto_fifo_config; /* FIFO config based on the period size */
int keep_bclk; /* Keep the BCLK running in FIFO modes */
u8 burst_bclkdiv;
};
#endif /* __TLV320DAC33_PLAT_H */

View File

@@ -13,8 +13,7 @@
#include <sound/asound.h>
#include <sound/compress_params.h>
#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 0)
#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 4, 1)
/**
* struct snd_compressed_buffer - compressed buffer
* @fragment_size: size of buffer fragment in bytes
@@ -56,6 +55,25 @@ struct snd_compr_tstamp {
__u32 sampling_rate;
} __attribute__((packed, aligned(4)));
/**
* struct snd_compr_tstamp64 - timestamp descriptor with fields in 64 bit
* @byte_offset: Byte offset in ring buffer to DSP
* @copied_total: Total number of bytes copied from/to ring buffer to/by DSP
* @pcm_frames: Frames decoded or encoded by DSP. This field will evolve by
* large steps and should only be used to monitor encoding/decoding
* progress. It shall not be used for timing estimates.
* @pcm_io_frames: Frames rendered or received by DSP into a mixer or an audio
* output/input. This field should be used for A/V sync or time estimates.
* @sampling_rate: sampling rate of audio
*/
struct snd_compr_tstamp64 {
__u32 byte_offset;
__u64 copied_total;
__u64 pcm_frames;
__u64 pcm_io_frames;
__u32 sampling_rate;
} __attribute__((packed, aligned(4)));
/**
* struct snd_compr_avail - avail descriptor
* @avail: Number of bytes available in ring buffer for writing/reading
@@ -66,6 +84,16 @@ struct snd_compr_avail {
struct snd_compr_tstamp tstamp;
} __attribute__((packed, aligned(4)));
/**
* struct snd_compr_avail64 - avail descriptor with tstamp in 64 bit format
* @avail: Number of bytes available in ring buffer for writing/reading
* @tstamp: timestamp information
*/
struct snd_compr_avail64 {
__u64 avail;
struct snd_compr_tstamp64 tstamp;
} __attribute__((packed, aligned(4)));
enum snd_compr_direction {
SND_COMPRESS_PLAYBACK = 0,
SND_COMPRESS_CAPTURE,
@@ -189,6 +217,7 @@ struct snd_compr_task_status {
* Note: only codec params can be changed runtime and stream params cant be
* SNDRV_COMPRESS_GET_PARAMS: Query codec params
* SNDRV_COMPRESS_TSTAMP: get the current timestamp value
* SNDRV_COMPRESS_TSTAMP64: get the current timestamp value in 64 bit format
* SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
* This also queries the tstamp properties
* SNDRV_COMPRESS_PAUSE: Pause the running stream
@@ -211,6 +240,8 @@ struct snd_compr_task_status {
struct snd_compr_metadata)
#define SNDRV_COMPRESS_TSTAMP _IOR('C', 0x20, struct snd_compr_tstamp)
#define SNDRV_COMPRESS_AVAIL _IOR('C', 0x21, struct snd_compr_avail)
#define SNDRV_COMPRESS_TSTAMP64 _IOR('C', 0x22, struct snd_compr_tstamp64)
#define SNDRV_COMPRESS_AVAIL64 _IOR('C', 0x23, struct snd_compr_avail64)
#define SNDRV_COMPRESS_PAUSE _IO('C', 0x30)
#define SNDRV_COMPRESS_RESUME _IO('C', 0x31)
#define SNDRV_COMPRESS_START _IO('C', 0x32)

View File

@@ -43,7 +43,8 @@
#define SND_AUDIOCODEC_BESPOKE ((__u32) 0x0000000E)
#define SND_AUDIOCODEC_ALAC ((__u32) 0x0000000F)
#define SND_AUDIOCODEC_APE ((__u32) 0x00000010)
#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_APE
#define SND_AUDIOCODEC_OPUS_RAW ((__u32) 0x00000011)
#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_OPUS_RAW
/*
* Profile and modes are listed with bit masks. This allows for a
@@ -324,6 +325,43 @@ struct snd_dec_ape {
__u32 seek_table_present;
} __attribute__((packed, aligned(4)));
/**
* struct snd_dec_opus - Opus decoder parameters (raw opus packets)
* @version: Usually should be '1' but can be split into major (4 upper bits)
* and minor (4 lower bits) sub-fields.
* @num_channels: Number of output channels.
* @pre_skip: Number of samples to discard at 48 kHz.
* @sample_rate: Sample rate of original input.
* @output_gain: Gain to apply when decoding (in Q7.8 format).
* @mapping_family: Order and meaning of output channels. Only values 0 and 1
* are expected; values 2..255 are not recommended for playback.
*
* @chan_map: Optional channel mapping table. Describes mapping of opus streams
* to decoded channels. Fields:
* @chan_map.stream_count: Number of streams encoded in each Ogg packet.
* @chan_map.coupled_count: Number of streams whose decoders are used
* for two channels.
* @chan_map.channel_map: Which decoded channel to be used for each one.
* Supports only mapping families 0 and 1,
* max number of channels is 8.
*
* These options were extracted from RFC7845 Section 5.
*/
struct snd_dec_opus {
__u8 version;
__u8 num_channels;
__u16 pre_skip;
__u32 sample_rate;
__u16 output_gain;
__u8 mapping_family;
struct snd_dec_opus_ch_map {
__u8 stream_count;
__u8 coupled_count;
__u8 channel_map[8];
} chan_map;
} __attribute__((packed, aligned(4)));
union snd_codec_options {
struct snd_enc_wma wma;
struct snd_enc_vorbis vorbis;
@@ -334,6 +372,7 @@ union snd_codec_options {
struct snd_dec_wma wma_d;
struct snd_dec_alac alac_d;
struct snd_dec_ape ape_d;
struct snd_dec_opus opus_d;
struct {
__u32 out_sample_rate;
} src_d;

View File

@@ -133,6 +133,21 @@ enum avs_tplg_token {
AVS_TKN_PATH_FE_FMT_ID_U32 = 1902,
AVS_TKN_PATH_BE_FMT_ID_U32 = 1903,
/* struct avs_tplg_path_template (conditional) */
AVS_TKN_CONDPATH_TMPL_ID_U32 = 1801,
AVS_TKN_CONDPATH_TMPL_SOURCE_TPLG_NAME_STRING = 2002,
AVS_TKN_CONDPATH_TMPL_SOURCE_PATH_TMPL_ID_U32 = 2003,
AVS_TKN_CONDPATH_TMPL_SINK_TPLG_NAME_STRING = 2004,
AVS_TKN_CONDPATH_TMPL_SINK_PATH_TMPL_ID_U32 = 2005,
AVS_TKN_CONDPATH_TMPL_COND_TYPE_U32 = 2006,
AVS_TKN_CONDPATH_TMPL_OVERRIDABLE_BOOL = 2007,
AVS_TKN_CONDPATH_TMPL_PRIORITY_U8 = 2008,
/* struct avs_tplg_path (conditional) */
AVS_TKN_CONDPATH_ID_U32 = 1901,
AVS_TKN_CONDPATH_SOURCE_PATH_ID_U32 = 2102,
AVS_TKN_CONDPATH_SINK_PATH_ID_U32 = 2103,
/* struct avs_tplg_pin_format */
AVS_TKN_PIN_FMT_INDEX_U32 = 2201,
AVS_TKN_PIN_FMT_IOBS_U32 = 2202,

View File

@@ -3,6 +3,8 @@
#ifndef __SND_AR_TOKENS_H__
#define __SND_AR_TOKENS_H__
#include <linux/types.h>
#define APM_SUB_GRAPH_PERF_MODE_LOW_POWER 0x1
#define APM_SUB_GRAPH_PERF_MODE_LOW_LATENCY 0x2
@@ -118,6 +120,12 @@ enum ar_event_types {
* LPAIF_WSA = 2,
* LPAIF_VA = 3,
* LPAIF_AXI = 4
* Possible values for MI2S
* I2S_INTF_TYPE_PRIMARY = 0,
* I2S_INTF_TYPE_SECONDARY = 1,
* I2S_INTF_TYPE_TERTIARY = 2,
* I2S_INTF_TYPE_QUATERNARY = 3,
* I2S_INTF_TYPE_QUINARY = 4,
*
* %AR_TKN_U32_MODULE_FMT_INTERLEAVE: PCM Interleaving
* PCM_INTERLEAVED = 1,
@@ -184,8 +192,8 @@ enum ar_event_types {
#define AR_TKN_U32_MODULE_INSTANCE_ID 201
#define AR_TKN_U32_MODULE_MAX_IP_PORTS 202
#define AR_TKN_U32_MODULE_MAX_OP_PORTS 203
#define AR_TKN_U32_MODULE_IN_PORTS 204
#define AR_TKN_U32_MODULE_OUT_PORTS 205
#define AR_TKN_U32_MODULE_IN_PORTS 204 /* deprecated */
#define AR_TKN_U32_MODULE_OUT_PORTS 205 /* deprecated */
#define AR_TKN_U32_MODULE_SRC_OP_PORT_ID 206
#define AR_TKN_U32_MODULE_DST_IN_PORT_ID 207
#define AR_TKN_U32_MODULE_SRC_INSTANCE_ID 208
@@ -232,4 +240,12 @@ enum ar_event_types {
#define AR_TKN_U32_MODULE_LOG_TAP_POINT_ID 260
#define AR_TKN_U32_MODULE_LOG_MODE 261
#define SND_SOC_AR_TPLG_MODULE_CFG_TYPE 0x01001006
struct audioreach_module_priv_data {
__le32 size; /* size in bytes of the array, including all elements */
__le32 type; /* SND_SOC_AR_TPLG_MODULE_CFG_TYPE */
__le32 priv[2]; /* Private data for future expansion */
__le32 data[0]; /* config data */
};
#endif /* __SND_AR_TOKENS_H__ */

View File

@@ -106,6 +106,8 @@
*/
#define SOF_TKN_COMP_NO_WNAME_IN_KCONTROL_NAME 417
#define SOF_TKN_COMP_SCHED_DOMAIN 418
/* SSP */
#define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500
#define SOF_TKN_INTEL_SSP_MCLK_ID 501

View File

@@ -241,10 +241,9 @@ static ssize_t cold_reset_store(struct device *dev,
{
struct ac97_controller *ac97_ctrl;
mutex_lock(&ac97_controllers_mutex);
guard(mutex)(&ac97_controllers_mutex);
ac97_ctrl = to_ac97_controller(dev);
ac97_ctrl->ops->reset(ac97_ctrl);
mutex_unlock(&ac97_controllers_mutex);
return len;
}
static DEVICE_ATTR_WO(cold_reset);
@@ -258,10 +257,9 @@ static ssize_t warm_reset_store(struct device *dev,
if (!dev)
return -ENODEV;
mutex_lock(&ac97_controllers_mutex);
guard(mutex)(&ac97_controllers_mutex);
ac97_ctrl = to_ac97_controller(dev);
ac97_ctrl->ops->warm_reset(ac97_ctrl);
mutex_unlock(&ac97_controllers_mutex);
return len;
}
static DEVICE_ATTR_WO(warm_reset);
@@ -284,10 +282,10 @@ static const struct attribute_group *ac97_adapter_groups[] = {
static void ac97_del_adapter(struct ac97_controller *ac97_ctrl)
{
mutex_lock(&ac97_controllers_mutex);
ac97_ctrl_codecs_unregister(ac97_ctrl);
list_del(&ac97_ctrl->controllers);
mutex_unlock(&ac97_controllers_mutex);
scoped_guard(mutex, &ac97_controllers_mutex) {
ac97_ctrl_codecs_unregister(ac97_ctrl);
list_del(&ac97_ctrl->controllers);
}
device_unregister(&ac97_ctrl->adap);
}
@@ -311,7 +309,7 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl)
{
int ret;
mutex_lock(&ac97_controllers_mutex);
guard(mutex)(&ac97_controllers_mutex);
ret = idr_alloc(&ac97_adapter_idr, ac97_ctrl, 0, 0, GFP_KERNEL);
ac97_ctrl->nr = ret;
if (ret >= 0) {
@@ -322,13 +320,11 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl)
if (ret)
put_device(&ac97_ctrl->adap);
}
if (!ret)
if (!ret) {
list_add(&ac97_ctrl->controllers, &ac97_controllers);
mutex_unlock(&ac97_controllers_mutex);
if (!ret)
dev_dbg(&ac97_ctrl->adap, "adapter registered by %s\n",
dev_name(ac97_ctrl->parent));
}
return ret;
}

View File

@@ -122,10 +122,9 @@ static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol,
struct onyx *onyx = snd_kcontrol_chip(kcontrol);
s8 l, r;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
mutex_unlock(&onyx->mutex);
ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT;
ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT;
@@ -146,15 +145,13 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT)
return -EINVAL;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] &&
r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) {
mutex_unlock(&onyx->mutex);
r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1])
return 0;
}
onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT,
ucontrol->value.integer.value[0]
@@ -162,7 +159,6 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol,
onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT,
ucontrol->value.integer.value[1]
- VOLUME_RANGE_SHIFT);
mutex_unlock(&onyx->mutex);
return 1;
}
@@ -198,9 +194,8 @@ static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol,
struct onyx *onyx = snd_kcontrol_chip(kcontrol);
u8 ig;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig);
mutex_unlock(&onyx->mutex);
ucontrol->value.integer.value[0] =
(ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT;
@@ -217,14 +212,13 @@ static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol,
if (ucontrol->value.integer.value[0] < 3 + INPUTGAIN_RANGE_SHIFT ||
ucontrol->value.integer.value[0] > 28 + INPUTGAIN_RANGE_SHIFT)
return -EINVAL;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
n = v;
n &= ~ONYX_ADC_PGA_GAIN_MASK;
n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT)
& ONYX_ADC_PGA_GAIN_MASK;
onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n);
mutex_unlock(&onyx->mutex);
return n != v;
}
@@ -252,9 +246,8 @@ static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol,
struct onyx *onyx = snd_kcontrol_chip(kcontrol);
s8 v;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
mutex_unlock(&onyx->mutex);
ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC);
@@ -265,13 +258,12 @@ static void onyx_set_capture_source(struct onyx *onyx, int mic)
{
s8 v;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
v &= ~ONYX_ADC_INPUT_MIC;
if (mic)
v |= ONYX_ADC_INPUT_MIC;
onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v);
mutex_unlock(&onyx->mutex);
}
static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
@@ -312,9 +304,8 @@ static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol,
struct onyx *onyx = snd_kcontrol_chip(kcontrol);
u8 c;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c);
mutex_unlock(&onyx->mutex);
ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT);
ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT);
@@ -329,9 +320,9 @@ static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol,
u8 v = 0, c = 0;
int err = -EBUSY;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
if (onyx->analog_locked)
goto out_unlock;
return -EBUSY;
onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
c = v;
@@ -342,9 +333,6 @@ static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol,
c |= ONYX_MUTE_RIGHT;
err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c);
out_unlock:
mutex_unlock(&onyx->mutex);
return !err ? (v != c) : err;
}
@@ -373,9 +361,8 @@ static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol,
u8 address = (pv >> 8) & 0xff;
u8 mask = pv & 0xff;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, address, &c);
mutex_unlock(&onyx->mutex);
ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity;
@@ -394,11 +381,10 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,
u8 address = (pv >> 8) & 0xff;
u8 mask = pv & 0xff;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
if (spdiflock && onyx->spdif_locked) {
/* even if alsamixer doesn't care.. */
err = -EBUSY;
goto out_unlock;
return -EBUSY;
}
onyx_read_register(onyx, address, &v);
c = v;
@@ -407,9 +393,6 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,
c |= mask;
err = onyx_write_register(onyx, address, c);
out_unlock:
mutex_unlock(&onyx->mutex);
return !err ? (v != c) : err;
}
@@ -490,7 +473,7 @@ static int onyx_spdif_get(struct snd_kcontrol *kcontrol,
struct onyx *onyx = snd_kcontrol_chip(kcontrol);
u8 v;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
ucontrol->value.iec958.status[0] = v & 0x3e;
@@ -502,7 +485,6 @@ static int onyx_spdif_get(struct snd_kcontrol *kcontrol,
onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
ucontrol->value.iec958.status[4] = v & 0x0f;
mutex_unlock(&onyx->mutex);
return 0;
}
@@ -513,7 +495,7 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol,
struct onyx *onyx = snd_kcontrol_chip(kcontrol);
u8 v;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e);
onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v);
@@ -528,7 +510,6 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol,
onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f);
onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
mutex_unlock(&onyx->mutex);
return 1;
}
@@ -673,14 +654,13 @@ static int onyx_usable(struct codec_info_item *cii,
struct onyx *onyx = cii->codec_data;
int spdif_enabled, analog_enabled;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
spdif_enabled = !!(v & ONYX_SPDIF_ENABLE);
onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
analog_enabled =
(v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT))
!= (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT);
mutex_unlock(&onyx->mutex);
switch (ti->tag) {
case 0: return 1;
@@ -696,9 +676,8 @@ static int onyx_prepare(struct codec_info_item *cii,
{
u8 v;
struct onyx *onyx = cii->codec_data;
int err = -EBUSY;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) {
@@ -707,10 +686,9 @@ static int onyx_prepare(struct codec_info_item *cii,
if (onyx_write_register(onyx,
ONYX_REG_DAC_CONTROL,
v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT))
goto out_unlock;
return -EBUSY;
onyx->analog_locked = 1;
err = 0;
goto out_unlock;
return 0;
}
#endif
switch (substream->runtime->rate) {
@@ -720,8 +698,7 @@ static int onyx_prepare(struct codec_info_item *cii,
/* these rates are ok for all outputs */
/* FIXME: program spdif channel control bits here so that
* userspace doesn't have to if it only plays pcm! */
err = 0;
goto out_unlock;
return 0;
default:
/* got some rate that the digital output can't do,
* so disable and lock it */
@@ -729,16 +706,12 @@ static int onyx_prepare(struct codec_info_item *cii,
if (onyx_write_register(onyx,
ONYX_REG_DIG_INFO4,
v & ~ONYX_SPDIF_ENABLE))
goto out_unlock;
return -EBUSY;
onyx->spdif_locked = 1;
err = 0;
goto out_unlock;
return 0;
}
out_unlock:
mutex_unlock(&onyx->mutex);
return err;
return -EBUSY;
}
static int onyx_open(struct codec_info_item *cii,
@@ -746,9 +719,8 @@ static int onyx_open(struct codec_info_item *cii,
{
struct onyx *onyx = cii->codec_data;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx->open_count++;
mutex_unlock(&onyx->mutex);
return 0;
}
@@ -758,11 +730,10 @@ static int onyx_close(struct codec_info_item *cii,
{
struct onyx *onyx = cii->codec_data;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
onyx->open_count--;
if (!onyx->open_count)
onyx->spdif_locked = onyx->analog_locked = 0;
mutex_unlock(&onyx->mutex);
return 0;
}
@@ -772,7 +743,7 @@ static int onyx_switch_clock(struct codec_info_item *cii,
{
struct onyx *onyx = cii->codec_data;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
/* this *MUST* be more elaborate later... */
switch (what) {
case CLOCK_SWITCH_PREPARE_SLAVE:
@@ -784,7 +755,6 @@ static int onyx_switch_clock(struct codec_info_item *cii,
default: /* silence warning */
break;
}
mutex_unlock(&onyx->mutex);
return 0;
}
@@ -795,27 +765,21 @@ static int onyx_suspend(struct codec_info_item *cii, pm_message_t state)
{
struct onyx *onyx = cii->codec_data;
u8 v;
int err = -ENXIO;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
goto out_unlock;
return -ENXIO;
onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV);
/* Apple does a sleep here but the datasheet says to do it on resume */
err = 0;
out_unlock:
mutex_unlock(&onyx->mutex);
return err;
return 0;
}
static int onyx_resume(struct codec_info_item *cii)
{
struct onyx *onyx = cii->codec_data;
u8 v;
int err = -ENXIO;
mutex_lock(&onyx->mutex);
guard(mutex)(&onyx->mutex);
/* reset codec */
onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
@@ -827,17 +791,13 @@ static int onyx_resume(struct codec_info_item *cii)
/* take codec out of suspend (if it still is after reset) */
if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
goto out_unlock;
return -ENXIO;
onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV));
/* FIXME: should divide by sample rate, but 8k is the lowest we go */
msleep(2205000/8000);
/* reset all values */
onyx_register_init(onyx);
err = 0;
out_unlock:
mutex_unlock(&onyx->mutex);
return err;
return 0;
}
#endif /* CONFIG_PM */
@@ -1013,7 +973,7 @@ static int onyx_i2c_probe(struct i2c_client *client)
goto fail;
}
strscpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
strscpy(onyx->codec.name, "onyx");
onyx->codec.owner = THIS_MODULE;
onyx->codec.init = onyx_init_codec;
onyx->codec.exit = onyx_exit_codec;

View File

@@ -235,10 +235,9 @@ static int tas_snd_vol_get(struct snd_kcontrol *kcontrol,
{
struct tas *tas = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
ucontrol->value.integer.value[0] = tas->cached_volume_l;
ucontrol->value.integer.value[1] = tas->cached_volume_r;
mutex_unlock(&tas->mtx);
return 0;
}
@@ -254,18 +253,15 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[1] > 177)
return -EINVAL;
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
if (tas->cached_volume_l == ucontrol->value.integer.value[0]
&& tas->cached_volume_r == ucontrol->value.integer.value[1]) {
mutex_unlock(&tas->mtx);
&& tas->cached_volume_r == ucontrol->value.integer.value[1])
return 0;
}
tas->cached_volume_l = ucontrol->value.integer.value[0];
tas->cached_volume_r = ucontrol->value.integer.value[1];
if (tas->hw_enabled)
tas_set_volume(tas);
mutex_unlock(&tas->mtx);
return 1;
}
@@ -285,10 +281,9 @@ static int tas_snd_mute_get(struct snd_kcontrol *kcontrol,
{
struct tas *tas = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
ucontrol->value.integer.value[0] = !tas->mute_l;
ucontrol->value.integer.value[1] = !tas->mute_r;
mutex_unlock(&tas->mtx);
return 0;
}
@@ -297,18 +292,15 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
{
struct tas *tas = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
if (tas->mute_l == !ucontrol->value.integer.value[0]
&& tas->mute_r == !ucontrol->value.integer.value[1]) {
mutex_unlock(&tas->mtx);
&& tas->mute_r == !ucontrol->value.integer.value[1])
return 0;
}
tas->mute_l = !ucontrol->value.integer.value[0];
tas->mute_r = !ucontrol->value.integer.value[1];
if (tas->hw_enabled)
tas_set_volume(tas);
mutex_unlock(&tas->mtx);
return 1;
}
@@ -337,10 +329,9 @@ static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol,
struct tas *tas = snd_kcontrol_chip(kcontrol);
int idx = kcontrol->private_value;
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
ucontrol->value.integer.value[0] = tas->mixer_l[idx];
ucontrol->value.integer.value[1] = tas->mixer_r[idx];
mutex_unlock(&tas->mtx);
return 0;
}
@@ -351,19 +342,16 @@ static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol,
struct tas *tas = snd_kcontrol_chip(kcontrol);
int idx = kcontrol->private_value;
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
if (tas->mixer_l[idx] == ucontrol->value.integer.value[0]
&& tas->mixer_r[idx] == ucontrol->value.integer.value[1]) {
mutex_unlock(&tas->mtx);
&& tas->mixer_r[idx] == ucontrol->value.integer.value[1])
return 0;
}
tas->mixer_l[idx] = ucontrol->value.integer.value[0];
tas->mixer_r[idx] = ucontrol->value.integer.value[1];
if (tas->hw_enabled)
tas_set_mixer(tas);
mutex_unlock(&tas->mtx);
return 1;
}
@@ -396,9 +384,8 @@ static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol,
{
struct tas *tas = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
ucontrol->value.integer.value[0] = tas->drc_range;
mutex_unlock(&tas->mtx);
return 0;
}
@@ -411,16 +398,13 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[0] > TAS3004_DRC_MAX)
return -EINVAL;
mutex_lock(&tas->mtx);
if (tas->drc_range == ucontrol->value.integer.value[0]) {
mutex_unlock(&tas->mtx);
guard(mutex)(&tas->mtx);
if (tas->drc_range == ucontrol->value.integer.value[0])
return 0;
}
tas->drc_range = ucontrol->value.integer.value[0];
if (tas->hw_enabled)
tas3004_set_drc(tas);
mutex_unlock(&tas->mtx);
return 1;
}
@@ -440,9 +424,8 @@ static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol,
{
struct tas *tas = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
ucontrol->value.integer.value[0] = tas->drc_enabled;
mutex_unlock(&tas->mtx);
return 0;
}
@@ -451,16 +434,13 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol,
{
struct tas *tas = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas->mtx);
if (tas->drc_enabled == ucontrol->value.integer.value[0]) {
mutex_unlock(&tas->mtx);
guard(mutex)(&tas->mtx);
if (tas->drc_enabled == ucontrol->value.integer.value[0])
return 0;
}
tas->drc_enabled = !!ucontrol->value.integer.value[0];
if (tas->hw_enabled)
tas3004_set_drc(tas);
mutex_unlock(&tas->mtx);
return 1;
}
@@ -486,9 +466,8 @@ static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol,
{
struct tas *tas = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B);
mutex_unlock(&tas->mtx);
return 0;
}
@@ -500,7 +479,7 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
if (ucontrol->value.enumerated.item[0] > 1)
return -EINVAL;
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
oldacr = tas->acr;
/*
@@ -512,13 +491,10 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
if (ucontrol->value.enumerated.item[0])
tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL |
TAS_ACR_B_MON_SEL_RIGHT;
if (oldacr == tas->acr) {
mutex_unlock(&tas->mtx);
if (oldacr == tas->acr)
return 0;
}
if (tas->hw_enabled)
tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
mutex_unlock(&tas->mtx);
return 1;
}
@@ -557,9 +533,8 @@ static int tas_snd_treble_get(struct snd_kcontrol *kcontrol,
{
struct tas *tas = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
ucontrol->value.integer.value[0] = tas->treble;
mutex_unlock(&tas->mtx);
return 0;
}
@@ -571,16 +546,13 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
if (ucontrol->value.integer.value[0] < TAS3004_TREBLE_MIN ||
ucontrol->value.integer.value[0] > TAS3004_TREBLE_MAX)
return -EINVAL;
mutex_lock(&tas->mtx);
if (tas->treble == ucontrol->value.integer.value[0]) {
mutex_unlock(&tas->mtx);
guard(mutex)(&tas->mtx);
if (tas->treble == ucontrol->value.integer.value[0])
return 0;
}
tas->treble = ucontrol->value.integer.value[0];
if (tas->hw_enabled)
tas_set_treble(tas);
mutex_unlock(&tas->mtx);
return 1;
}
@@ -608,9 +580,8 @@ static int tas_snd_bass_get(struct snd_kcontrol *kcontrol,
{
struct tas *tas = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
ucontrol->value.integer.value[0] = tas->bass;
mutex_unlock(&tas->mtx);
return 0;
}
@@ -622,16 +593,13 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
if (ucontrol->value.integer.value[0] < TAS3004_BASS_MIN ||
ucontrol->value.integer.value[0] > TAS3004_BASS_MAX)
return -EINVAL;
mutex_lock(&tas->mtx);
if (tas->bass == ucontrol->value.integer.value[0]) {
mutex_unlock(&tas->mtx);
guard(mutex)(&tas->mtx);
if (tas->bass == ucontrol->value.integer.value[0])
return 0;
}
tas->bass = ucontrol->value.integer.value[0];
if (tas->hw_enabled)
tas_set_bass(tas);
mutex_unlock(&tas->mtx);
return 1;
}
@@ -722,13 +690,13 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock
break;
case CLOCK_SWITCH_SLAVE:
/* Clocks are back, re-init the codec */
mutex_lock(&tas->mtx);
tas_reset_init(tas);
tas_set_volume(tas);
tas_set_mixer(tas);
tas->hw_enabled = 1;
tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
mutex_unlock(&tas->mtx);
scoped_guard(mutex, &tas->mtx) {
tas_reset_init(tas);
tas_set_volume(tas);
tas_set_mixer(tas);
tas->hw_enabled = 1;
tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
}
break;
default:
/* doesn't happen as of now */
@@ -743,23 +711,21 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock
* our i2c device is suspended, and then take note of that! */
static int tas_suspend(struct tas *tas)
{
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
tas->hw_enabled = 0;
tas->acr |= TAS_ACR_ANALOG_PDOWN;
tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
mutex_unlock(&tas->mtx);
return 0;
}
static int tas_resume(struct tas *tas)
{
/* reset codec */
mutex_lock(&tas->mtx);
guard(mutex)(&tas->mtx);
tas_reset_init(tas);
tas_set_volume(tas);
tas_set_mixer(tas);
tas->hw_enabled = 1;
mutex_unlock(&tas->mtx);
return 0;
}
@@ -802,14 +768,13 @@ static int tas_init_codec(struct aoa_codec *codec)
return -EINVAL;
}
mutex_lock(&tas->mtx);
if (tas_reset_init(tas)) {
printk(KERN_ERR PFX "tas failed to initialise\n");
mutex_unlock(&tas->mtx);
return -ENXIO;
scoped_guard(mutex, &tas->mtx) {
if (tas_reset_init(tas)) {
printk(KERN_ERR PFX "tas failed to initialise\n");
return -ENXIO;
}
tas->hw_enabled = 1;
}
tas->hw_enabled = 1;
mutex_unlock(&tas->mtx);
if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev,
aoa_get_card(),
@@ -892,7 +857,7 @@ static int tas_i2c_probe(struct i2c_client *client)
/* seems that half is a saner default */
tas->drc_range = TAS3004_DRC_MAX / 2;
strscpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
strscpy(tas->codec.name, "tas");
tas->codec.owner = THIS_MODULE;
tas->codec.init = tas_init_codec;
tas->codec.exit = tas_exit_codec;

View File

@@ -126,7 +126,7 @@ static int __init toonie_init(void)
if (!toonie)
return -ENOMEM;
strscpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name));
strscpy(toonie->codec.name, "toonie");
toonie->codec.owner = THIS_MODULE;
toonie->codec.init = toonie_init_codec;
toonie->codec.exit = toonie_exit_codec;

View File

@@ -28,10 +28,10 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev)
return err;
aoa_card = alsa_card->private_data;
aoa_card->alsa_card = alsa_card;
strscpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
strscpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
strscpy(alsa_card->longname, name, sizeof(alsa_card->longname));
strscpy(alsa_card->mixername, name, sizeof(alsa_card->mixername));
strscpy(alsa_card->driver, "AppleOnbdAudio");
strscpy(alsa_card->shortname, name);
strscpy(alsa_card->longname, name);
strscpy(alsa_card->mixername, name);
err = snd_card_register(aoa_card->alsa_card);
if (err < 0) {
printk(KERN_ERR "snd-aoa: couldn't register alsa card\n");

View File

@@ -212,10 +212,9 @@ static void ftr_handle_notify(struct work_struct *work)
struct gpio_notification *notif =
container_of(work, struct gpio_notification, work.work);
mutex_lock(&notif->mutex);
guard(mutex)(&notif->mutex);
if (notif->notify)
notif->notify(notif->data);
mutex_unlock(&notif->mutex);
}
static void gpio_enable_dual_edge(int gpio)
@@ -341,19 +340,17 @@ static int ftr_set_notify(struct gpio_runtime *rt,
if (!irq)
return -ENODEV;
mutex_lock(&notif->mutex);
guard(mutex)(&notif->mutex);
old = notif->notify;
if (!old && !notify) {
err = 0;
goto out_unlock;
}
if (!old && !notify)
return 0;
if (old && notify) {
if (old == notify && notif->data == data)
err = 0;
goto out_unlock;
return err;
}
if (old && !notify)
@@ -362,16 +359,13 @@ static int ftr_set_notify(struct gpio_runtime *rt,
if (!old && notify) {
err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif);
if (err)
goto out_unlock;
return err;
}
notif->notify = notify;
notif->data = data;
err = 0;
out_unlock:
mutex_unlock(&notif->mutex);
return err;
return 0;
}
static int ftr_get_detect(struct gpio_runtime *rt,

View File

@@ -74,10 +74,9 @@ static void pmf_handle_notify(struct work_struct *work)
struct gpio_notification *notif =
container_of(work, struct gpio_notification, work.work);
mutex_lock(&notif->mutex);
guard(mutex)(&notif->mutex);
if (notif->notify)
notif->notify(notif->data);
mutex_unlock(&notif->mutex);
}
static void pmf_gpio_init(struct gpio_runtime *rt)
@@ -154,19 +153,17 @@ static int pmf_set_notify(struct gpio_runtime *rt,
return -EINVAL;
}
mutex_lock(&notif->mutex);
guard(mutex)(&notif->mutex);
old = notif->notify;
if (!old && !notify) {
err = 0;
goto out_unlock;
}
if (!old && !notify)
return 0;
if (old && notify) {
if (old == notify && notif->data == data)
err = 0;
goto out_unlock;
return err;
}
if (old && !notify) {
@@ -178,10 +175,8 @@ static int pmf_set_notify(struct gpio_runtime *rt,
if (!old && notify) {
irq_client = kzalloc(sizeof(struct pmf_irq_client),
GFP_KERNEL);
if (!irq_client) {
err = -ENOMEM;
goto out_unlock;
}
if (!irq_client)
return -ENOMEM;
irq_client->data = notif;
irq_client->handler = pmf_handle_notify_irq;
irq_client->owner = THIS_MODULE;
@@ -192,17 +187,14 @@ static int pmf_set_notify(struct gpio_runtime *rt,
printk(KERN_ERR "snd-aoa: gpio layer failed to"
" register %s irq (%d)\n", name, err);
kfree(irq_client);
goto out_unlock;
return err;
}
notif->gpio_private = irq_client;
}
notif->notify = notify;
notif->data = data;
err = 0;
out_unlock:
mutex_unlock(&notif->mutex);
return err;
return 0;
}
static int pmf_get_detect(struct gpio_runtime *rt,

View File

@@ -949,8 +949,7 @@ static void layout_attached_codec(struct aoa_codec *codec)
ldev->gpio.methods->set_lineout(codec->gpio, 1);
ctl = snd_ctl_new1(&lineout_ctl, codec->gpio);
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
strscpy(ctl->id.name,
"Headphone Switch", sizeof(ctl->id.name));
strscpy(ctl->id.name, "Headphone Switch");
ldev->lineout_ctrl = ctl;
aoa_snd_ctl_add(ctl);
ldev->have_lineout_detect =
@@ -964,15 +963,13 @@ static void layout_attached_codec(struct aoa_codec *codec)
ldev);
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
strscpy(ctl->id.name,
"Headphone Detect Autoswitch",
sizeof(ctl->id.name));
"Headphone Detect Autoswitch");
aoa_snd_ctl_add(ctl);
ctl = snd_ctl_new1(&lineout_detected,
ldev);
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
strscpy(ctl->id.name,
"Headphone Detected",
sizeof(ctl->id.name));
"Headphone Detected");
ldev->lineout_detected_ctrl = ctl;
aoa_snd_ctl_add(ctl);
}

View File

@@ -93,14 +93,12 @@ static irqreturn_t i2sbus_bus_intr(int irq, void *devid)
struct i2sbus_dev *dev = devid;
u32 intreg;
spin_lock(&dev->low_lock);
guard(spinlock)(&dev->low_lock);
intreg = in_le32(&dev->intfregs->intr_ctl);
/* acknowledge interrupt reasons */
out_le32(&dev->intfregs->intr_ctl, intreg);
spin_unlock(&dev->low_lock);
return IRQ_HANDLED;
}

View File

@@ -79,11 +79,10 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
u64 formats = 0;
unsigned int rates = 0;
struct transfer_info v;
int result = 0;
int bus_factor = 0, sysclock_factor = 0;
int found_this;
mutex_lock(&i2sdev->lock);
guard(mutex)(&i2sdev->lock);
get_pcm_info(i2sdev, in, &pi, &other);
@@ -92,8 +91,7 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
if (pi->active) {
/* alsa messed up */
result = -EBUSY;
goto out_unlock;
return -EBUSY;
}
/* we now need to assign the hw */
@@ -117,10 +115,8 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
ti++;
}
}
if (!masks_inited || !bus_factor || !sysclock_factor) {
result = -ENODEV;
goto out_unlock;
}
if (!masks_inited || !bus_factor || !sysclock_factor)
return -ENODEV;
/* bus dependent stuff */
hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME |
@@ -194,15 +190,12 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
hw->periods_max = MAX_DBDMA_COMMANDS;
err = snd_pcm_hw_constraint_integer(pi->substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
if (err < 0) {
result = err;
goto out_unlock;
}
if (err < 0)
return err;
list_for_each_entry(cii, &sdev->codec_list, list) {
if (cii->codec->open) {
err = cii->codec->open(cii, pi->substream);
if (err) {
result = err;
/* unwind */
found_this = 0;
list_for_each_entry_reverse(rev,
@@ -214,14 +207,12 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
if (rev == cii)
found_this = 1;
}
goto out_unlock;
return err;
}
}
}
out_unlock:
mutex_unlock(&i2sdev->lock);
return result;
return 0;
}
#undef CHECK_RATE
@@ -232,7 +223,7 @@ static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in)
struct pcm_info *pi;
int err = 0, tmp;
mutex_lock(&i2sdev->lock);
guard(mutex)(&i2sdev->lock);
get_pcm_info(i2sdev, in, &pi, NULL);
@@ -246,7 +237,6 @@ static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in)
pi->substream = NULL;
pi->active = 0;
mutex_unlock(&i2sdev->lock);
return err;
}
@@ -330,33 +320,26 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
int input_16bit;
struct pcm_info *pi, *other;
int cnt;
int result = 0;
unsigned int cmd, stopaddr;
mutex_lock(&i2sdev->lock);
guard(mutex)(&i2sdev->lock);
get_pcm_info(i2sdev, in, &pi, &other);
if (pi->dbdma_ring.running) {
result = -EBUSY;
goto out_unlock;
}
if (pi->dbdma_ring.running)
return -EBUSY;
if (pi->dbdma_ring.stopping)
i2sbus_wait_for_stop(i2sdev, pi);
if (!pi->substream || !pi->substream->runtime) {
result = -EINVAL;
goto out_unlock;
}
if (!pi->substream || !pi->substream->runtime)
return -EINVAL;
runtime = pi->substream->runtime;
pi->active = 1;
if (other->active &&
((i2sdev->format != runtime->format)
|| (i2sdev->rate != runtime->rate))) {
result = -EINVAL;
goto out_unlock;
}
|| (i2sdev->rate != runtime->rate)))
return -EINVAL;
i2sdev->format = runtime->format;
i2sdev->rate = runtime->rate;
@@ -412,10 +395,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
bi.bus_factor = cii->codec->bus_factor;
break;
}
if (!bi.bus_factor) {
result = -ENODEV;
goto out_unlock;
}
if (!bi.bus_factor)
return -ENODEV;
input_16bit = 1;
break;
case SNDRV_PCM_FORMAT_S32_BE:
@@ -426,8 +407,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
input_16bit = 0;
break;
default:
result = -EINVAL;
goto out_unlock;
return -EINVAL;
}
/* we assume all sysclocks are the same! */
list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
@@ -438,10 +418,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
if (clock_and_divisors(bi.sysclock_factor,
bi.bus_factor,
runtime->rate,
&sfr) < 0) {
result = -EINVAL;
goto out_unlock;
}
&sfr) < 0)
return -EINVAL;
switch (bi.bus_factor) {
case 32:
sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X;
@@ -457,10 +435,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
int err = 0;
if (cii->codec->prepare)
err = cii->codec->prepare(cii, &bi, pi->substream);
if (err) {
result = err;
goto out_unlock;
}
if (err)
return err;
}
/* codecs are fine with it, so set our clocks */
if (input_16bit)
@@ -476,7 +452,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
/* not locking these is fine since we touch them only in this function */
if (in_le32(&i2sdev->intfregs->serial_format) == sfr
&& in_le32(&i2sdev->intfregs->data_word_sizes) == dws)
goto out_unlock;
return 0;
/* let's notify the codecs about clocks going away.
* For now we only do mastering on the i2s cell... */
@@ -514,9 +490,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
if (cii->codec->switch_clock)
cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE);
out_unlock:
mutex_unlock(&i2sdev->lock);
return result;
return 0;
}
#ifdef CONFIG_PM
@@ -531,20 +505,16 @@ static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
{
struct codec_info_item *cii;
struct pcm_info *pi;
int result = 0;
unsigned long flags;
spin_lock_irqsave(&i2sdev->low_lock, flags);
guard(spinlock_irqsave)(&i2sdev->low_lock);
get_pcm_info(i2sdev, in, &pi, NULL);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
if (pi->dbdma_ring.running) {
result = -EALREADY;
goto out_unlock;
}
if (pi->dbdma_ring.running)
return -EALREADY;
list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
if (cii->codec->start)
cii->codec->start(cii, pi->substream);
@@ -558,7 +528,7 @@ static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
udelay(10);
if (in_le32(&pi->dbdma->status) & ACTIVE) {
pi->dbdma_ring.stopping = 0;
goto out_unlock; /* keep running */
return 0; /* keep running */
}
}
}
@@ -584,10 +554,8 @@ static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
if (!pi->dbdma_ring.running) {
result = -EALREADY;
goto out_unlock;
}
if (!pi->dbdma_ring.running)
return -EALREADY;
pi->dbdma_ring.running = 0;
/* Set the S0 bit to make the DMA branch to the stop cmd */
@@ -599,13 +567,10 @@ static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
cii->codec->stop(cii, pi->substream);
break;
default:
result = -EINVAL;
goto out_unlock;
return -EINVAL;
}
out_unlock:
spin_unlock_irqrestore(&i2sdev->low_lock, flags);
return result;
return 0;
}
static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in)
@@ -632,70 +597,67 @@ static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in)
int dma_stopped = 0;
struct snd_pcm_runtime *runtime;
spin_lock(&i2sdev->low_lock);
get_pcm_info(i2sdev, in, &pi, NULL);
if (!pi->dbdma_ring.running && !pi->dbdma_ring.stopping)
goto out_unlock;
scoped_guard(spinlock, &i2sdev->low_lock) {
get_pcm_info(i2sdev, in, &pi, NULL);
if (!pi->dbdma_ring.running && !pi->dbdma_ring.stopping)
return;
i = pi->current_period;
runtime = pi->substream->runtime;
while (pi->dbdma_ring.cmds[i].xfer_status) {
if (le16_to_cpu(pi->dbdma_ring.cmds[i].xfer_status) & BT)
/*
* BT is the branch taken bit. If it took a branch
* it is because we set the S0 bit to make it
* branch to the stop command.
*/
dma_stopped = 1;
pi->dbdma_ring.cmds[i].xfer_status = 0;
i = pi->current_period;
runtime = pi->substream->runtime;
while (pi->dbdma_ring.cmds[i].xfer_status) {
if (le16_to_cpu(pi->dbdma_ring.cmds[i].xfer_status) & BT)
/*
* BT is the branch taken bit. If it took a branch
* it is because we set the S0 bit to make it
* branch to the stop command.
*/
dma_stopped = 1;
pi->dbdma_ring.cmds[i].xfer_status = 0;
if (++i >= runtime->periods) {
i = 0;
pi->frame_count += runtime->buffer_size;
}
pi->current_period = i;
/*
* Check the frame count. The DMA tends to get a bit
* ahead of the frame counter, which confuses the core.
*/
fc = in_le32(&i2sdev->intfregs->frame_count);
nframes = i * runtime->period_size;
if (fc < pi->frame_count + nframes)
pi->frame_count = fc - nframes;
}
if (dma_stopped) {
timeout = 1000;
for (;;) {
status = in_le32(&pi->dbdma->status);
if (!(status & ACTIVE) && (!in || (status & 0x80)))
break;
if (--timeout <= 0) {
printk(KERN_ERR "i2sbus: timed out "
"waiting for DMA to stop!\n");
break;
if (++i >= runtime->periods) {
i = 0;
pi->frame_count += runtime->buffer_size;
}
udelay(1);
pi->current_period = i;
/*
* Check the frame count. The DMA tends to get a bit
* ahead of the frame counter, which confuses the core.
*/
fc = in_le32(&i2sdev->intfregs->frame_count);
nframes = i * runtime->period_size;
if (fc < pi->frame_count + nframes)
pi->frame_count = fc - nframes;
}
/* Turn off DMA controller, clear S0 bit */
out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
if (dma_stopped) {
timeout = 1000;
for (;;) {
status = in_le32(&pi->dbdma->status);
if (!(status & ACTIVE) && (!in || (status & 0x80)))
break;
if (--timeout <= 0) {
printk(KERN_ERR
"i2sbus: timed out waiting for DMA to stop!\n");
break;
}
udelay(1);
}
pi->dbdma_ring.stopping = 0;
if (pi->stop_completion)
complete(pi->stop_completion);
/* Turn off DMA controller, clear S0 bit */
out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
pi->dbdma_ring.stopping = 0;
if (pi->stop_completion)
complete(pi->stop_completion);
}
if (!pi->dbdma_ring.running)
return;
}
if (!pi->dbdma_ring.running)
goto out_unlock;
spin_unlock(&i2sdev->low_lock);
/* may call _trigger again, hence needs to be unlocked */
snd_pcm_period_elapsed(pi->substream);
return;
out_unlock:
spin_unlock(&i2sdev->low_lock);
}
irqreturn_t i2sbus_tx_intr(int irq, void *devid)

View File

@@ -73,7 +73,7 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
if (ac97->num >= 4)
return;
mutex_lock(&aaci->ac97_sem);
guard(mutex)(&aaci->ac97_sem);
aaci_ac97_select_codec(aaci, ac97);
@@ -97,8 +97,6 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
if (v & (SLFR_1TXB|SLFR_2TXB))
dev_err(&aaci->dev->dev,
"timeout waiting for write to complete\n");
mutex_unlock(&aaci->ac97_sem);
}
/*
@@ -113,7 +111,7 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
if (ac97->num >= 4)
return ~0;
mutex_lock(&aaci->ac97_sem);
guard(mutex)(&aaci->ac97_sem);
aaci_ac97_select_codec(aaci, ac97);
@@ -134,8 +132,7 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
if (v & SLFR_1TXB) {
dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n");
v = ~0;
goto out;
return ~0;
}
/* Now wait for the response frame */
@@ -151,8 +148,7 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
if (v != (SLFR_1RXV|SLFR_2RXV)) {
dev_err(&aaci->dev->dev, "timeout on RX valid\n");
v = ~0;
goto out;
return ~0;
}
do {
@@ -171,8 +167,6 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
v = ~0;
}
} while (retries);
out:
mutex_unlock(&aaci->ac97_sem);
return v;
}
@@ -216,45 +210,43 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
return;
}
spin_lock(&aacirun->lock);
scoped_guard(spinlock, &aacirun->lock) {
ptr = aacirun->ptr;
do {
unsigned int len = aacirun->fifo_bytes;
u32 val;
ptr = aacirun->ptr;
do {
unsigned int len = aacirun->fifo_bytes;
u32 val;
if (aacirun->bytes <= 0) {
aacirun->bytes += aacirun->period;
period_elapsed = true;
}
if (!(aacirun->cr & CR_EN))
break;
if (aacirun->bytes <= 0) {
aacirun->bytes += aacirun->period;
period_elapsed = true;
}
if (!(aacirun->cr & CR_EN))
break;
val = readl(aacirun->base + AACI_SR);
if (!(val & SR_RXHF))
break;
if (!(val & SR_RXFF))
len >>= 1;
val = readl(aacirun->base + AACI_SR);
if (!(val & SR_RXHF))
break;
if (!(val & SR_RXFF))
len >>= 1;
aacirun->bytes -= len;
aacirun->bytes -= len;
/* reading 16 bytes at a time */
for( ; len > 0; len -= 16) {
asm(
"ldmia %1, {r0, r1, r2, r3}\n\t"
"stmia %0!, {r0, r1, r2, r3}"
: "+r" (ptr)
: "r" (aacirun->fifo)
: "r0", "r1", "r2", "r3", "cc");
/* reading 16 bytes at a time */
for( ; len > 0; len -= 16) {
asm(
"ldmia %1, {r0, r1, r2, r3}\n\t"
"stmia %0!, {r0, r1, r2, r3}"
: "+r" (ptr)
: "r" (aacirun->fifo)
: "r0", "r1", "r2", "r3", "cc");
if (ptr >= aacirun->end)
ptr = aacirun->start;
}
} while(1);
if (ptr >= aacirun->end)
ptr = aacirun->start;
}
} while(1);
aacirun->ptr = ptr;
spin_unlock(&aacirun->lock);
aacirun->ptr = ptr;
}
if (period_elapsed)
snd_pcm_period_elapsed(aacirun->substream);
@@ -276,45 +268,43 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
return;
}
spin_lock(&aacirun->lock);
scoped_guard(spinlock, &aacirun->lock) {
ptr = aacirun->ptr;
do {
unsigned int len = aacirun->fifo_bytes;
u32 val;
ptr = aacirun->ptr;
do {
unsigned int len = aacirun->fifo_bytes;
u32 val;
if (aacirun->bytes <= 0) {
aacirun->bytes += aacirun->period;
period_elapsed = true;
}
if (!(aacirun->cr & CR_EN))
break;
if (aacirun->bytes <= 0) {
aacirun->bytes += aacirun->period;
period_elapsed = true;
}
if (!(aacirun->cr & CR_EN))
break;
val = readl(aacirun->base + AACI_SR);
if (!(val & SR_TXHE))
break;
if (!(val & SR_TXFE))
len >>= 1;
val = readl(aacirun->base + AACI_SR);
if (!(val & SR_TXHE))
break;
if (!(val & SR_TXFE))
len >>= 1;
aacirun->bytes -= len;
aacirun->bytes -= len;
/* writing 16 bytes at a time */
for ( ; len > 0; len -= 16) {
asm(
"ldmia %0!, {r0, r1, r2, r3}\n\t"
"stmia %1, {r0, r1, r2, r3}"
: "+r" (ptr)
: "r" (aacirun->fifo)
: "r0", "r1", "r2", "r3", "cc");
/* writing 16 bytes at a time */
for ( ; len > 0; len -= 16) {
asm(
"ldmia %0!, {r0, r1, r2, r3}\n\t"
"stmia %1, {r0, r1, r2, r3}"
: "+r" (ptr)
: "r" (aacirun->fifo)
: "r0", "r1", "r2", "r3", "cc");
if (ptr >= aacirun->end)
ptr = aacirun->start;
}
} while (1);
if (ptr >= aacirun->end)
ptr = aacirun->start;
}
} while (1);
aacirun->ptr = ptr;
spin_unlock(&aacirun->lock);
aacirun->ptr = ptr;
}
if (period_elapsed)
snd_pcm_period_elapsed(aacirun->substream);
@@ -437,14 +427,13 @@ static int aaci_pcm_open(struct snd_pcm_substream *substream)
*/
runtime->hw.fifo_size = aaci->fifo_depth * 2;
mutex_lock(&aaci->irq_lock);
guard(mutex)(&aaci->irq_lock);
if (!aaci->users++) {
ret = request_irq(aaci->dev->irq[0], aaci_irq,
IRQF_SHARED, DRIVER_NAME, aaci);
if (ret != 0)
aaci->users--;
}
mutex_unlock(&aaci->irq_lock);
return ret;
}
@@ -462,10 +451,9 @@ static int aaci_pcm_close(struct snd_pcm_substream *substream)
aacirun->substream = NULL;
mutex_lock(&aaci->irq_lock);
guard(mutex)(&aaci->irq_lock);
if (!--aaci->users)
free_irq(aaci->dev->irq[0], aaci);
mutex_unlock(&aaci->irq_lock);
return 0;
}
@@ -585,10 +573,8 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct aaci_runtime *aacirun = substream->runtime->private_data;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&aacirun->lock, flags);
guard(spinlock_irqsave)(&aacirun->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -614,12 +600,10 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm
break;
default:
ret = -EINVAL;
return -EINVAL;
}
spin_unlock_irqrestore(&aacirun->lock, flags);
return ret;
return 0;
}
static const struct snd_pcm_ops aaci_playback_ops = {
@@ -669,10 +653,8 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct aaci_runtime *aacirun = substream->runtime->private_data;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&aacirun->lock, flags);
guard(spinlock_irqsave)(&aacirun->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -698,12 +680,10 @@ static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd
break;
default:
ret = -EINVAL;
return -EINVAL;
}
spin_unlock_irqrestore(&aacirun->lock, flags);
return ret;
return 0;
}
static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream)

View File

@@ -51,7 +51,7 @@ int pxa2xx_ac97_read(int slot, unsigned short reg)
if (slot > 0)
return -ENODEV;
mutex_lock(&car_mutex);
guard(mutex)(&car_mutex);
/* set up primary or secondary codec space */
if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
@@ -67,13 +67,12 @@ int pxa2xx_ac97_read(int slot, unsigned short reg)
gsr_bits = 0;
val = (readl(reg_addr) & 0xffff);
if (reg == AC97_GPIO_STATUS)
goto out;
return val;
if (wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE, 1) <= 0 &&
!((readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE)) {
printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
__func__, reg, readl(ac97_reg_base + GSR) | gsr_bits);
val = -ETIMEDOUT;
goto out;
return -ETIMEDOUT;
}
/* valid data now */
@@ -82,8 +81,6 @@ int pxa2xx_ac97_read(int slot, unsigned short reg)
val = (readl(reg_addr) & 0xffff);
/* but we've just started another cycle... */
wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE, 1);
out: mutex_unlock(&car_mutex);
return val;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_read);
@@ -93,7 +90,7 @@ int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val)
u32 __iomem *reg_addr;
int ret = 0;
mutex_lock(&car_mutex);
guard(mutex)(&car_mutex);
/* set up primary or secondary codec space */
if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
@@ -114,7 +111,6 @@ int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val)
ret = -EIO;
}
mutex_unlock(&car_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_write);

View File

@@ -88,7 +88,7 @@ static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream)
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
mutex_lock(&opened_mutex);
guard(mutex)(&opened_mutex);
chip->opened++;
runtime->hw = atmel_ac97c_hw;
if (chip->cur_rate) {
@@ -97,7 +97,6 @@ static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream)
}
if (chip->cur_format)
runtime->hw.formats = pcm_format_to_bits(chip->cur_format);
mutex_unlock(&opened_mutex);
chip->playback_substream = substream;
return 0;
}
@@ -107,7 +106,7 @@ static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream)
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
mutex_lock(&opened_mutex);
guard(mutex)(&opened_mutex);
chip->opened++;
runtime->hw = atmel_ac97c_hw;
if (chip->cur_rate) {
@@ -116,7 +115,6 @@ static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream)
}
if (chip->cur_format)
runtime->hw.formats = pcm_format_to_bits(chip->cur_format);
mutex_unlock(&opened_mutex);
chip->capture_substream = substream;
return 0;
}
@@ -125,13 +123,12 @@ static int atmel_ac97c_playback_close(struct snd_pcm_substream *substream)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
mutex_lock(&opened_mutex);
guard(mutex)(&opened_mutex);
chip->opened--;
if (!chip->opened) {
chip->cur_rate = 0;
chip->cur_format = 0;
}
mutex_unlock(&opened_mutex);
chip->playback_substream = NULL;
@@ -142,13 +139,12 @@ static int atmel_ac97c_capture_close(struct snd_pcm_substream *substream)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
mutex_lock(&opened_mutex);
guard(mutex)(&opened_mutex);
chip->opened--;
if (!chip->opened) {
chip->cur_rate = 0;
chip->cur_format = 0;
}
mutex_unlock(&opened_mutex);
chip->capture_substream = NULL;
@@ -161,10 +157,9 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream,
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
/* Set restrictions to params. */
mutex_lock(&opened_mutex);
guard(mutex)(&opened_mutex);
chip->cur_rate = params_rate(hw_params);
chip->cur_format = params_format(hw_params);
mutex_unlock(&opened_mutex);
return 0;
}
@@ -175,10 +170,9 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
/* Set restrictions to params. */
mutex_lock(&opened_mutex);
guard(mutex)(&opened_mutex);
chip->cur_rate = params_rate(hw_params);
chip->cur_format = params_format(hw_params);
mutex_unlock(&opened_mutex);
return 0;
}

View File

@@ -176,14 +176,25 @@ static int snd_compr_free(struct inode *inode, struct file *f)
return 0;
}
static void
snd_compr_tstamp32_from_64(struct snd_compr_tstamp *tstamp32,
const struct snd_compr_tstamp64 *tstamp64)
{
tstamp32->byte_offset = tstamp64->byte_offset;
tstamp32->copied_total = (u32)tstamp64->copied_total;
tstamp32->pcm_frames = (u32)tstamp64->pcm_frames;
tstamp32->pcm_io_frames = (u32)tstamp64->pcm_io_frames;
tstamp32->sampling_rate = tstamp64->sampling_rate;
}
static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
struct snd_compr_tstamp *tstamp)
struct snd_compr_tstamp64 *tstamp)
{
if (!stream->ops->pointer)
return -ENOTSUPP;
stream->ops->pointer(stream, tstamp);
pr_debug("dsp consumed till %d total %d bytes\n",
tstamp->byte_offset, tstamp->copied_total);
pr_debug("dsp consumed till %u total %llu bytes\n", tstamp->byte_offset,
tstamp->copied_total);
if (stream->direction == SND_COMPRESS_PLAYBACK)
stream->runtime->total_bytes_transferred = tstamp->copied_total;
else
@@ -192,7 +203,7 @@ static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
}
static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
struct snd_compr_avail *avail)
struct snd_compr_avail64 *avail)
{
memset(avail, 0, sizeof(*avail));
snd_compr_update_tstamp(stream, &avail->tstamp);
@@ -204,9 +215,9 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
pr_debug("detected init and someone forgot to do a write\n");
return stream->runtime->buffer_size;
}
pr_debug("app wrote %lld, DSP consumed %lld\n",
stream->runtime->total_bytes_available,
stream->runtime->total_bytes_transferred);
pr_debug("app wrote %llu, DSP consumed %llu\n",
stream->runtime->total_bytes_available,
stream->runtime->total_bytes_transferred);
if (stream->runtime->total_bytes_available ==
stream->runtime->total_bytes_transferred) {
if (stream->direction == SND_COMPRESS_PLAYBACK) {
@@ -223,28 +234,43 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
if (stream->direction == SND_COMPRESS_PLAYBACK)
avail->avail = stream->runtime->buffer_size - avail->avail;
pr_debug("ret avail as %lld\n", avail->avail);
pr_debug("ret avail as %zu\n", (size_t)avail->avail);
return avail->avail;
}
static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
{
struct snd_compr_avail avail;
struct snd_compr_avail64 avail;
return snd_compr_calc_avail(stream, &avail);
}
static int
snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
static void snd_compr_avail32_from_64(struct snd_compr_avail *avail32,
const struct snd_compr_avail64 *avail64)
{
struct snd_compr_avail ioctl_avail;
avail32->avail = avail64->avail;
snd_compr_tstamp32_from_64(&avail32->tstamp, &avail64->tstamp);
}
static int snd_compr_ioctl_avail(struct snd_compr_stream *stream,
unsigned long arg, bool is_32bit)
{
struct snd_compr_avail64 ioctl_avail64;
struct snd_compr_avail ioctl_avail32;
size_t avail;
const void *copy_from = &ioctl_avail64;
size_t copy_size = sizeof(ioctl_avail64);
if (stream->direction == SND_COMPRESS_ACCEL)
return -EBADFD;
avail = snd_compr_calc_avail(stream, &ioctl_avail);
ioctl_avail.avail = avail;
avail = snd_compr_calc_avail(stream, &ioctl_avail64);
ioctl_avail64.avail = avail;
if (is_32bit) {
snd_compr_avail32_from_64(&ioctl_avail32, &ioctl_avail64);
copy_from = &ioctl_avail32;
copy_size = sizeof(ioctl_avail32);
}
switch (stream->runtime->state) {
case SNDRV_PCM_STATE_OPEN:
@@ -255,8 +281,7 @@ snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
break;
}
if (copy_to_user((__u64 __user *)arg,
&ioctl_avail, sizeof(ioctl_avail)))
if (copy_to_user((__u64 __user *)arg, copy_from, copy_size))
return -EFAULT;
return 0;
}
@@ -274,8 +299,7 @@ static int snd_compr_write_data(struct snd_compr_stream *stream,
(app_pointer * runtime->buffer_size);
dstn = runtime->buffer + app_pointer;
pr_debug("copying %ld at %lld\n",
(unsigned long)count, app_pointer);
pr_debug("copying %lu at %llu\n", (unsigned long)count, app_pointer);
if (count < runtime->buffer_size - app_pointer) {
if (copy_from_user(dstn, buf, count))
return -EFAULT;
@@ -318,7 +342,7 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf,
}
avail = snd_compr_get_avail(stream);
pr_debug("avail returned %ld\n", (unsigned long)avail);
pr_debug("avail returned %lu\n", (unsigned long)avail);
/* calculate how much we can write to buffer */
if (avail > count)
avail = count;
@@ -374,7 +398,7 @@ static ssize_t snd_compr_read(struct file *f, char __user *buf,
}
avail = snd_compr_get_avail(stream);
pr_debug("avail returned %ld\n", (unsigned long)avail);
pr_debug("avail returned %lu\n", (unsigned long)avail);
/* calculate how much we can read from buffer */
if (avail > count)
avail = count;
@@ -443,7 +467,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait)
#endif
avail = snd_compr_get_avail(stream);
pr_debug("avail is %ld\n", (unsigned long)avail);
pr_debug("avail is %lu\n", (unsigned long)avail);
/* check if we have at least one fragment to fill */
switch (runtime->state) {
case SNDRV_PCM_STATE_DRAINING:
@@ -723,16 +747,26 @@ snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg)
return retval;
}
static inline int
snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
static inline int snd_compr_tstamp(struct snd_compr_stream *stream,
unsigned long arg, bool is_32bit)
{
struct snd_compr_tstamp tstamp = {0};
struct snd_compr_tstamp64 tstamp64 = { 0 };
struct snd_compr_tstamp tstamp32 = { 0 };
const void *copy_from = &tstamp64;
size_t copy_size = sizeof(tstamp64);
int ret;
ret = snd_compr_update_tstamp(stream, &tstamp);
if (ret == 0)
ret = copy_to_user((struct snd_compr_tstamp __user *)arg,
&tstamp, sizeof(tstamp)) ? -EFAULT : 0;
ret = snd_compr_update_tstamp(stream, &tstamp64);
if (ret == 0) {
if (is_32bit) {
snd_compr_tstamp32_from_64(&tstamp32, &tstamp64);
copy_from = &tstamp32;
copy_size = sizeof(tstamp32);
}
ret = copy_to_user((void __user *)arg, copy_from, copy_size) ?
-EFAULT :
0;
}
return ret;
}
@@ -1309,9 +1343,13 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
switch (cmd) {
case SNDRV_COMPRESS_TSTAMP:
return snd_compr_tstamp(stream, arg);
return snd_compr_tstamp(stream, arg, true);
case SNDRV_COMPRESS_TSTAMP64:
return snd_compr_tstamp(stream, arg, false);
case SNDRV_COMPRESS_AVAIL:
return snd_compr_ioctl_avail(stream, arg);
return snd_compr_ioctl_avail(stream, arg, true);
case SNDRV_COMPRESS_AVAIL64:
return snd_compr_ioctl_avail(stream, arg, false);
case SNDRV_COMPRESS_PAUSE:
return snd_compr_pause(stream);
case SNDRV_COMPRESS_RESUME:

View File

@@ -127,35 +127,30 @@ int snd_fasync_helper(int fd, struct file *file, int on,
INIT_LIST_HEAD(&fasync->list);
}
spin_lock_irq(&snd_fasync_lock);
if (*fasyncp) {
kfree(fasync);
fasync = *fasyncp;
} else {
if (!fasync) {
spin_unlock_irq(&snd_fasync_lock);
return 0;
scoped_guard(spinlock_irq, &snd_fasync_lock) {
if (*fasyncp) {
kfree(fasync);
fasync = *fasyncp;
} else {
if (!fasync)
return 0;
*fasyncp = fasync;
}
*fasyncp = fasync;
fasync->on = on;
}
fasync->on = on;
spin_unlock_irq(&snd_fasync_lock);
return fasync_helper(fd, file, on, &fasync->fasync);
}
EXPORT_SYMBOL_GPL(snd_fasync_helper);
void snd_kill_fasync(struct snd_fasync *fasync, int signal, int poll)
{
unsigned long flags;
if (!fasync || !fasync->on)
return;
spin_lock_irqsave(&snd_fasync_lock, flags);
guard(spinlock_irqsave)(&snd_fasync_lock);
fasync->signal = signal;
fasync->poll = poll;
list_move(&fasync->list, &snd_fasync_list);
schedule_work(&snd_fasync_work);
spin_unlock_irqrestore(&snd_fasync_lock, flags);
}
EXPORT_SYMBOL_GPL(snd_kill_fasync);

View File

@@ -2002,9 +2002,8 @@ static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsig
static int snd_pcm_oss_nonblock(struct file * file)
{
spin_lock(&file->f_lock);
guard(spinlock)(&file->f_lock);
file->f_flags |= O_NONBLOCK;
spin_unlock(&file->f_lock);
return 0;
}

View File

@@ -111,6 +111,7 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
slave_config->dst_addr = dma_data->addr;
slave_config->dst_maxburst = dma_data->maxburst;
slave_config->dst_port_window_size = dma_data->port_window_size;
if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)
slave_config->dst_addr_width =
DMA_SLAVE_BUSWIDTH_UNDEFINED;
@@ -119,6 +120,7 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
} else {
slave_config->src_addr = dma_data->addr;
slave_config->src_maxburst = dma_data->maxburst;
slave_config->src_port_window_size = dma_data->port_window_size;
if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)
slave_config->src_addr_width =
DMA_SLAVE_BUSWIDTH_UNDEFINED;

View File

@@ -84,19 +84,24 @@ void snd_pcm_group_init(struct snd_pcm_group *group)
}
/* define group lock helpers */
#define DEFINE_PCM_GROUP_LOCK(action, mutex_action) \
#define DEFINE_PCM_GROUP_LOCK(action, bh_lock, bh_unlock, mutex_action) \
static void snd_pcm_group_ ## action(struct snd_pcm_group *group, bool nonatomic) \
{ \
if (nonatomic) \
if (nonatomic) { \
mutex_ ## mutex_action(&group->mutex); \
else \
spin_ ## action(&group->lock); \
} else { \
if (IS_ENABLED(CONFIG_PREEMPT_RT) && bh_lock) \
local_bh_disable(); \
spin_ ## action(&group->lock); \
if (IS_ENABLED(CONFIG_PREEMPT_RT) && bh_unlock) \
local_bh_enable(); \
} \
}
DEFINE_PCM_GROUP_LOCK(lock, lock);
DEFINE_PCM_GROUP_LOCK(unlock, unlock);
DEFINE_PCM_GROUP_LOCK(lock_irq, lock);
DEFINE_PCM_GROUP_LOCK(unlock_irq, unlock);
DEFINE_PCM_GROUP_LOCK(lock, false, false, lock);
DEFINE_PCM_GROUP_LOCK(unlock, false, false, unlock);
DEFINE_PCM_GROUP_LOCK(lock_irq, true, false, lock);
DEFINE_PCM_GROUP_LOCK(unlock_irq, false, true, unlock);
/**
* snd_pcm_stream_lock - Lock the PCM stream

View File

@@ -117,18 +117,15 @@ static DEFINE_MUTEX(register_mutex);
static int
odev_open(struct inode *inode, struct file *file)
{
int level, rc;
int level;
if (iminor(inode) == SNDRV_MINOR_OSS_MUSIC)
level = SNDRV_SEQ_OSS_MODE_MUSIC;
else
level = SNDRV_SEQ_OSS_MODE_SYNTH;
mutex_lock(&register_mutex);
rc = snd_seq_oss_open(file, level);
mutex_unlock(&register_mutex);
return rc;
guard(mutex)(&register_mutex);
return snd_seq_oss_open(file, level);
}
static int
@@ -140,10 +137,8 @@ odev_release(struct inode *inode, struct file *file)
if (!dp)
return 0;
mutex_lock(&register_mutex);
guard(mutex)(&register_mutex);
snd_seq_oss_release(dp);
mutex_unlock(&register_mutex);
return 0;
}
@@ -229,13 +224,12 @@ register_device(void)
{
int rc;
mutex_lock(&register_mutex);
guard(mutex)(&register_mutex);
rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
NULL, 0,
&seq_oss_f_ops, NULL);
if (rc < 0) {
pr_err("ALSA: seq_oss: can't register device seq\n");
mutex_unlock(&register_mutex);
return rc;
}
rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
@@ -244,22 +238,19 @@ register_device(void)
if (rc < 0) {
pr_err("ALSA: seq_oss: can't register device music\n");
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
mutex_unlock(&register_mutex);
return rc;
}
mutex_unlock(&register_mutex);
return 0;
}
static void
unregister_device(void)
{
mutex_lock(&register_mutex);
guard(mutex)(&register_mutex);
if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0)
pr_err("ALSA: seq_oss: error unregister device music\n");
if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0)
pr_err("ALSA: seq_oss: error unregister device seq\n");
mutex_unlock(&register_mutex);
}
/*
@@ -273,12 +264,11 @@ static struct snd_info_entry *info_entry;
static void
info_read(struct snd_info_entry *entry, struct snd_info_buffer *buf)
{
mutex_lock(&register_mutex);
guard(mutex)(&register_mutex);
snd_iprintf(buf, "OSS sequencer emulation version %s\n", SNDRV_SEQ_OSS_VERSION_STR);
snd_seq_oss_system_info_read(buf);
snd_seq_oss_synth_info_read(buf);
snd_seq_oss_midi_info_read(buf);
mutex_unlock(&register_mutex);
}

View File

@@ -137,12 +137,7 @@ snd_seq_oss_dispatch(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int a
static inline int
snd_seq_oss_control(struct seq_oss_devinfo *dp, unsigned int type, void *arg)
{
int err;
snd_seq_client_ioctl_lock(dp->cseq);
err = snd_seq_kernel_client_ctl(dp->cseq, type, arg);
snd_seq_client_ioctl_unlock(dp->cseq);
return err;
return snd_seq_kernel_client_ioctl(dp->cseq, type, arg);
}
/* fill the addresses in header */

View File

@@ -40,6 +40,7 @@ struct seq_oss_midi {
struct mutex open_mutex;
};
DEFINE_FREE(seq_oss_midi, struct seq_oss_midi *, if (!IS_ERR_OR_NULL(_T)) snd_use_lock_free(&(_T)->use_lock))
/*
* midi device table
@@ -90,13 +91,11 @@ static struct seq_oss_midi *
get_mdev(int dev)
{
struct seq_oss_midi *mdev;
unsigned long flags;
spin_lock_irqsave(&register_lock, flags);
guard(spinlock_irqsave)(&register_lock);
mdev = midi_devs[dev];
if (mdev)
snd_use_lock_use(&mdev->use_lock);
spin_unlock_irqrestore(&register_lock, flags);
return mdev;
}
@@ -108,19 +107,16 @@ find_slot(int client, int port)
{
int i;
struct seq_oss_midi *mdev;
unsigned long flags;
spin_lock_irqsave(&register_lock, flags);
guard(spinlock_irqsave)(&register_lock);
for (i = 0; i < max_midi_devs; i++) {
mdev = midi_devs[i];
if (mdev && mdev->client == client && mdev->port == port) {
/* found! */
snd_use_lock_use(&mdev->use_lock);
spin_unlock_irqrestore(&register_lock, flags);
return mdev;
}
}
spin_unlock_irqrestore(&register_lock, flags);
return NULL;
}
@@ -135,7 +131,6 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
{
int i;
struct seq_oss_midi *mdev;
unsigned long flags;
/* the port must include generic midi */
if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC))
@@ -185,14 +180,13 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
/*
* look for en empty slot
*/
spin_lock_irqsave(&register_lock, flags);
guard(spinlock_irqsave)(&register_lock);
for (i = 0; i < max_midi_devs; i++) {
if (midi_devs[i] == NULL)
break;
}
if (i >= max_midi_devs) {
if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) {
spin_unlock_irqrestore(&register_lock, flags);
snd_midi_event_free(mdev->coder);
kfree(mdev);
return -ENOMEM;
@@ -201,7 +195,6 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
}
mdev->seq_device = i;
midi_devs[mdev->seq_device] = mdev;
spin_unlock_irqrestore(&register_lock, flags);
return 0;
}
@@ -213,26 +206,24 @@ int
snd_seq_oss_midi_check_exit_port(int client, int port)
{
struct seq_oss_midi *mdev;
unsigned long flags;
int index;
mdev = find_slot(client, port);
if (mdev) {
spin_lock_irqsave(&register_lock, flags);
midi_devs[mdev->seq_device] = NULL;
spin_unlock_irqrestore(&register_lock, flags);
scoped_guard(spinlock_irqsave, &register_lock) {
midi_devs[mdev->seq_device] = NULL;
}
snd_use_lock_free(&mdev->use_lock);
snd_use_lock_sync(&mdev->use_lock);
snd_midi_event_free(mdev->coder);
kfree(mdev);
}
spin_lock_irqsave(&register_lock, flags);
guard(spinlock_irqsave)(&register_lock);
for (index = max_midi_devs - 1; index >= 0; index--) {
if (midi_devs[index])
break;
}
max_midi_devs = index + 1;
spin_unlock_irqrestore(&register_lock, flags);
return 0;
}
@@ -245,9 +236,8 @@ snd_seq_oss_midi_clear_all(void)
{
int i;
struct seq_oss_midi *mdev;
unsigned long flags;
spin_lock_irqsave(&register_lock, flags);
guard(spinlock_irqsave)(&register_lock);
for (i = 0; i < max_midi_devs; i++) {
mdev = midi_devs[i];
if (mdev) {
@@ -257,7 +247,6 @@ snd_seq_oss_midi_clear_all(void)
}
}
max_midi_devs = 0;
spin_unlock_irqrestore(&register_lock, flags);
}
@@ -267,9 +256,8 @@ snd_seq_oss_midi_clear_all(void)
void
snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
{
spin_lock_irq(&register_lock);
guard(spinlock_irq)(&register_lock);
dp->max_mididev = max_midi_devs;
spin_unlock_irq(&register_lock);
}
/*
@@ -317,20 +305,17 @@ int
snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
{
int perm;
struct seq_oss_midi *mdev;
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
struct snd_seq_port_subscribe subs;
int err;
mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV;
mutex_lock(&mdev->open_mutex);
guard(mutex)(&mdev->open_mutex);
/* already used? */
if (mdev->opened && mdev->devinfo != dp) {
err = -EBUSY;
goto unlock;
}
if (mdev->opened && mdev->devinfo != dp)
return -EBUSY;
perm = 0;
if (is_write_mode(fmode))
@@ -338,16 +323,12 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
if (is_read_mode(fmode))
perm |= PERM_READ;
perm &= mdev->flags;
if (perm == 0) {
err = -ENXIO;
goto unlock;
}
if (perm == 0)
return -ENXIO;
/* already opened? */
if ((mdev->opened & perm) == perm) {
err = 0;
goto unlock;
}
if ((mdev->opened & perm) == perm)
return 0;
perm &= ~mdev->opened;
@@ -370,18 +351,11 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
mdev->opened |= PERM_READ;
}
if (! mdev->opened) {
err = -ENXIO;
goto unlock;
}
if (!mdev->opened)
return -ENXIO;
mdev->devinfo = dp;
err = 0;
unlock:
mutex_unlock(&mdev->open_mutex);
snd_use_lock_free(&mdev->use_lock);
return err;
return 0;
}
/*
@@ -390,15 +364,15 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
int
snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
{
struct seq_oss_midi *mdev;
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
struct snd_seq_port_subscribe subs;
mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV;
mutex_lock(&mdev->open_mutex);
guard(mutex)(&mdev->open_mutex);
if (!mdev->opened || mdev->devinfo != dp)
goto unlock;
return 0;
memset(&subs, 0, sizeof(subs));
if (mdev->opened & PERM_WRITE) {
@@ -416,10 +390,6 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
mdev->opened = 0;
mdev->devinfo = NULL;
unlock:
mutex_unlock(&mdev->open_mutex);
snd_use_lock_free(&mdev->use_lock);
return 0;
}
@@ -429,7 +399,7 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
int
snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
{
struct seq_oss_midi *mdev;
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
int mode;
mdev = get_mididev(dp, dev);
@@ -442,7 +412,6 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
if (mdev->opened & PERM_READ)
mode |= SNDRV_SEQ_OSS_FILE_READ;
snd_use_lock_free(&mdev->use_lock);
return mode;
}
@@ -453,15 +422,13 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
void
snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
{
struct seq_oss_midi *mdev;
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
mdev = get_mididev(dp, dev);
if (!mdev)
return;
if (! mdev->opened) {
snd_use_lock_free(&mdev->use_lock);
if (!mdev->opened)
return;
}
if (mdev->opened & PERM_WRITE) {
struct snd_seq_event ev;
@@ -492,7 +459,6 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
}
}
// snd_seq_oss_midi_close(dp, dev);
snd_use_lock_free(&mdev->use_lock);
}
@@ -502,14 +468,13 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
void
snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr)
{
struct seq_oss_midi *mdev;
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
mdev = get_mididev(dp, dev);
if (!mdev)
return;
addr->client = mdev->client;
addr->port = mdev->port;
snd_use_lock_free(&mdev->use_lock);
}
@@ -520,26 +485,20 @@ int
snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data)
{
struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
struct seq_oss_midi *mdev;
int rc;
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
if (dp->readq == NULL)
return 0;
mdev = find_slot(ev->source.client, ev->source.port);
if (!mdev)
return 0;
if (! (mdev->opened & PERM_READ)) {
snd_use_lock_free(&mdev->use_lock);
if (!(mdev->opened & PERM_READ))
return 0;
}
if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
rc = send_synth_event(dp, ev, mdev->seq_device);
return send_synth_event(dp, ev, mdev->seq_device);
else
rc = send_midi_event(dp, ev, mdev);
snd_use_lock_free(&mdev->use_lock);
return rc;
return send_midi_event(dp, ev, mdev);
}
/*
@@ -636,17 +595,15 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq
int
snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
{
struct seq_oss_midi *mdev;
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV;
if (snd_midi_event_encode_byte(mdev->coder, c, ev)) {
snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port);
snd_use_lock_free(&mdev->use_lock);
return 0;
}
snd_use_lock_free(&mdev->use_lock);
return -EINVAL;
}
@@ -656,7 +613,7 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru
int
snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf)
{
struct seq_oss_midi *mdev;
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
mdev = get_mididev(dp, dev);
if (!mdev)
@@ -665,7 +622,6 @@ snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info
inf->dev_type = 0; /* FIXME: ?? */
inf->capabilities = 0; /* FIXME: ?? */
strscpy(inf->name, mdev->name, sizeof(inf->name));
snd_use_lock_free(&mdev->use_lock);
return 0;
}
@@ -692,10 +648,11 @@ void
snd_seq_oss_midi_info_read(struct snd_info_buffer *buf)
{
int i;
struct seq_oss_midi *mdev;
snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs);
for (i = 0; i < max_midi_devs; i++) {
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
snd_iprintf(buf, "\nmidi %d: ", i);
mdev = get_mdev(i);
if (mdev == NULL) {
@@ -707,7 +664,6 @@ snd_seq_oss_midi_info_read(struct snd_info_buffer *buf)
snd_iprintf(buf, " capability %s / opened %s\n",
capmode_str(mdev->flags),
capmode_str(mdev->opened));
snd_use_lock_free(&mdev->use_lock);
}
}
#endif /* CONFIG_SND_PROC_FS */

View File

@@ -140,13 +140,9 @@ int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev,
int
snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
{
unsigned long flags;
spin_lock_irqsave(&q->lock, flags);
if (q->qlen >= q->maxlen - 1) {
spin_unlock_irqrestore(&q->lock, flags);
guard(spinlock_irqsave)(&q->lock);
if (q->qlen >= q->maxlen - 1)
return -ENOMEM;
}
memcpy(&q->q[q->tail], ev, sizeof(*ev));
q->tail = (q->tail + 1) % q->maxlen;
@@ -155,8 +151,6 @@ snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
/* wake up sleeper */
wake_up(&q->midi_sleep);
spin_unlock_irqrestore(&q->lock, flags);
return 0;
}

View File

@@ -44,6 +44,7 @@ struct seq_oss_synth {
snd_use_lock_t use_lock;
};
DEFINE_FREE(seq_oss_synth, struct seq_oss_synth *, if (!IS_ERR_OR_NULL(_T)) snd_use_lock_free(&(_T)->use_lock))
/*
* device table
@@ -85,7 +86,6 @@ snd_seq_oss_synth_probe(struct device *_dev)
int i;
struct seq_oss_synth *rec;
struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
unsigned long flags;
rec = kzalloc(sizeof(*rec), GFP_KERNEL);
if (!rec)
@@ -103,23 +103,22 @@ snd_seq_oss_synth_probe(struct device *_dev)
strscpy(rec->name, dev->name, sizeof(rec->name));
/* registration */
spin_lock_irqsave(&register_lock, flags);
for (i = 0; i < max_synth_devs; i++) {
if (synth_devs[i] == NULL)
break;
}
if (i >= max_synth_devs) {
if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
spin_unlock_irqrestore(&register_lock, flags);
pr_err("ALSA: seq_oss: no more synth slot\n");
kfree(rec);
return -ENOMEM;
scoped_guard(spinlock_irqsave, &register_lock) {
for (i = 0; i < max_synth_devs; i++) {
if (synth_devs[i] == NULL)
break;
}
max_synth_devs++;
if (i >= max_synth_devs) {
if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
pr_err("ALSA: seq_oss: no more synth slot\n");
kfree(rec);
return -ENOMEM;
}
max_synth_devs++;
}
rec->seq_device = i;
synth_devs[i] = rec;
}
rec->seq_device = i;
synth_devs[i] = rec;
spin_unlock_irqrestore(&register_lock, flags);
dev->driver_data = rec;
#ifdef SNDRV_OSS_INFO_DEV_SYNTH
if (i < SNDRV_CARDS)
@@ -135,27 +134,25 @@ snd_seq_oss_synth_remove(struct device *_dev)
struct snd_seq_device *dev = to_seq_dev(_dev);
int index;
struct seq_oss_synth *rec = dev->driver_data;
unsigned long flags;
spin_lock_irqsave(&register_lock, flags);
for (index = 0; index < max_synth_devs; index++) {
if (synth_devs[index] == rec)
break;
}
if (index >= max_synth_devs) {
spin_unlock_irqrestore(&register_lock, flags);
pr_err("ALSA: seq_oss: can't unregister synth\n");
return -EINVAL;
}
synth_devs[index] = NULL;
if (index == max_synth_devs - 1) {
for (index--; index >= 0; index--) {
if (synth_devs[index])
scoped_guard(spinlock_irqsave, &register_lock) {
for (index = 0; index < max_synth_devs; index++) {
if (synth_devs[index] == rec)
break;
}
max_synth_devs = index + 1;
if (index >= max_synth_devs) {
pr_err("ALSA: seq_oss: can't unregister synth\n");
return -EINVAL;
}
synth_devs[index] = NULL;
if (index == max_synth_devs - 1) {
for (index--; index >= 0; index--) {
if (synth_devs[index])
break;
}
max_synth_devs = index + 1;
}
}
spin_unlock_irqrestore(&register_lock, flags);
#ifdef SNDRV_OSS_INFO_DEV_SYNTH
if (rec->seq_device < SNDRV_CARDS)
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device);
@@ -174,13 +171,11 @@ static struct seq_oss_synth *
get_sdev(int dev)
{
struct seq_oss_synth *rec;
unsigned long flags;
spin_lock_irqsave(&register_lock, flags);
guard(spinlock_irqsave)(&register_lock);
rec = synth_devs[dev];
if (rec)
snd_use_lock_use(&rec->use_lock);
spin_unlock_irqrestore(&register_lock, flags);
return rec;
}
@@ -193,20 +188,18 @@ void
snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
{
int i;
struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
dp->max_synthdev = max_synth_devs;
dp->synth_opened = 0;
memset(dp->synths, 0, sizeof(dp->synths));
for (i = 0; i < dp->max_synthdev; i++) {
rec = get_sdev(i);
struct seq_oss_synth *rec __free(seq_oss_synth) = get_sdev(i);
if (rec == NULL)
continue;
if (rec->oper.open == NULL || rec->oper.close == NULL) {
snd_use_lock_free(&rec->use_lock);
if (rec->oper.open == NULL || rec->oper.close == NULL)
continue;
}
info = &dp->synths[i];
info->arg.app_index = dp->port;
info->arg.file_mode = dp->file_mode;
@@ -216,13 +209,10 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
else
info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
info->opened = 0;
if (!try_module_get(rec->oper.owner)) {
snd_use_lock_free(&rec->use_lock);
if (!try_module_get(rec->oper.owner))
continue;
}
if (rec->oper.open(&info->arg, rec->private_data) < 0) {
module_put(rec->oper.owner);
snd_use_lock_free(&rec->use_lock);
continue;
}
info->nr_voices = rec->nr_voices;
@@ -231,7 +221,6 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
if (!info->ch) {
rec->oper.close(&info->arg);
module_put(rec->oper.owner);
snd_use_lock_free(&rec->use_lock);
continue;
}
reset_channels(info);
@@ -239,7 +228,6 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
info->opened++;
rec->opened++;
dp->synth_opened++;
snd_use_lock_free(&rec->use_lock);
}
}
@@ -286,7 +274,6 @@ void
snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
{
int i;
struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
@@ -301,7 +288,9 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
midi_synth_dev.opened--;
}
} else {
rec = get_sdev(i);
struct seq_oss_synth *rec __free(seq_oss_synth) =
get_sdev(i);
if (rec == NULL)
continue;
if (rec->opened > 0) {
@@ -309,7 +298,6 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
module_put(rec->oper.owner);
rec->opened = 0;
}
snd_use_lock_free(&rec->use_lock);
}
kfree(info->ch);
info->ch = NULL;
@@ -380,7 +368,7 @@ reset_channels(struct seq_oss_synthinfo *info)
void
snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
{
struct seq_oss_synth *rec;
struct seq_oss_synth *rec __free(seq_oss_synth) = NULL;
struct seq_oss_synthinfo *info;
info = get_synthinfo_nospec(dp, dev);
@@ -416,7 +404,6 @@ snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
ev.type = SNDRV_SEQ_EVENT_RESET;
snd_seq_oss_dispatch(dp, &ev, 0, 0);
}
snd_use_lock_free(&rec->use_lock);
}
@@ -428,9 +415,8 @@ int
snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
const char __user *buf, int p, int c)
{
struct seq_oss_synth *rec;
struct seq_oss_synth *rec __free(seq_oss_synth) = NULL;
struct seq_oss_synthinfo *info;
int rc;
info = get_synthinfo_nospec(dp, dev);
if (!info)
@@ -443,11 +429,9 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
return -ENXIO;
if (rec->oper.load_patch == NULL)
rc = -ENXIO;
return -ENXIO;
else
rc = rec->oper.load_patch(&info->arg, fmt, buf, p, c);
snd_use_lock_free(&rec->use_lock);
return rc;
return rec->oper.load_patch(&info->arg, fmt, buf, p, c);
}
/*
@@ -456,13 +440,11 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
struct seq_oss_synthinfo *
snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev)
{
struct seq_oss_synth *rec;
struct seq_oss_synth *rec __free(seq_oss_synth) = NULL;
rec = get_synthdev(dp, dev);
if (rec) {
snd_use_lock_free(&rec->use_lock);
if (rec)
return get_synthinfo_nospec(dp, dev);
}
return NULL;
}
@@ -513,9 +495,8 @@ snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event
int
snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
{
struct seq_oss_synth *rec;
struct seq_oss_synth *rec __free(seq_oss_synth) = NULL;
struct seq_oss_synthinfo *info;
int rc;
info = get_synthinfo_nospec(dp, dev);
if (!info || info->is_midi)
@@ -524,11 +505,9 @@ snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, u
if (!rec)
return -ENXIO;
if (rec->oper.ioctl == NULL)
rc = -ENXIO;
return -ENXIO;
else
rc = rec->oper.ioctl(&info->arg, cmd, addr);
snd_use_lock_free(&rec->use_lock);
return rc;
return rec->oper.ioctl(&info->arg, cmd, addr);
}
@@ -555,7 +534,6 @@ snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *
int
snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf)
{
struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev);
if (!info)
@@ -571,7 +549,9 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
inf->device = dev;
strscpy(inf->name, minf.name, sizeof(inf->name));
} else {
rec = get_synthdev(dp, dev);
struct seq_oss_synth *rec __free(seq_oss_synth) =
get_synthdev(dp, dev);
if (!rec)
return -ENXIO;
inf->synth_type = rec->synth_type;
@@ -579,7 +559,6 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
inf->nr_voices = rec->nr_voices;
inf->device = dev;
strscpy(inf->name, rec->name, sizeof(inf->name));
snd_use_lock_free(&rec->use_lock);
}
return 0;
}
@@ -593,10 +572,11 @@ void
snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
{
int i;
struct seq_oss_synth *rec;
snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs);
for (i = 0; i < max_synth_devs; i++) {
struct seq_oss_synth *rec __free(seq_oss_synth) = NULL;
snd_iprintf(buf, "\nsynth %d: ", i);
rec = get_sdev(i);
if (rec == NULL) {
@@ -610,7 +590,6 @@ snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
snd_iprintf(buf, " capabilities : ioctl %s / load_patch %s\n",
str_enabled_disabled((long)rec->oper.ioctl),
str_enabled_disabled((long)rec->oper.load_patch));
snd_use_lock_free(&rec->use_lock);
}
}
#endif /* CONFIG_SND_PROC_FS */

View File

@@ -122,13 +122,10 @@ snd_seq_oss_writeq_sync(struct seq_oss_writeq *q)
void
snd_seq_oss_writeq_wakeup(struct seq_oss_writeq *q, abstime_t time)
{
unsigned long flags;
spin_lock_irqsave(&q->sync_lock, flags);
guard(spinlock_irqsave)(&q->sync_lock);
q->sync_time = time;
q->sync_event_put = 0;
wake_up(&q->sync_sleep);
spin_unlock_irqrestore(&q->sync_lock, flags);
}

File diff suppressed because it is too large Load Diff

View File

@@ -78,8 +78,20 @@ void snd_sequencer_device_done(void);
/* get locked pointer to client */
struct snd_seq_client *snd_seq_client_use_ptr(int clientid);
static inline struct snd_seq_client *
snd_seq_client_ref(struct snd_seq_client *client)
{
snd_use_lock_use(&client->use_lock);
return client;
}
/* unlock pointer to client */
#define snd_seq_client_unlock(client) snd_use_lock_free(&(client)->use_lock)
static inline void snd_seq_client_unref(struct snd_seq_client *client)
{
snd_use_lock_free(&client->use_lock);
}
DEFINE_FREE(snd_seq_client, struct snd_seq_client *, if (!IS_ERR_OR_NULL(_T)) snd_seq_client_unref(_T))
/* dispatch event to client(s) */
int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop);
@@ -94,8 +106,7 @@ int __snd_seq_deliver_single_event(struct snd_seq_client *dest,
int atomic, int hop);
/* only for OSS sequencer */
bool snd_seq_client_ioctl_lock(int clientid);
void snd_seq_client_ioctl_unlock(int clientid);
int snd_seq_kernel_client_ioctl(int clientid, unsigned int cmd, void *arg);
extern int seq_client_load[15];

View File

@@ -106,12 +106,11 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
if (snd_BUG_ON(!f))
return -EINVAL;
snd_use_lock_use(&f->use_lock);
guard(snd_seq_fifo)(f);
err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL, NULL); /* always non-blocking */
if (err < 0) {
if ((err == -ENOMEM) || (err == -EAGAIN))
atomic_inc(&f->overflow);
snd_use_lock_free(&f->use_lock);
return err;
}
@@ -130,8 +129,6 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
if (waitqueue_active(&f->input_sleep))
wake_up(&f->input_sleep);
snd_use_lock_free(&f->use_lock);
return 0; /* success */
}
@@ -213,6 +210,7 @@ int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file,
poll_table *wait)
{
poll_wait(file, &f->input_sleep, wait);
guard(spinlock_irq)(&f->lock);
return (f->cells > 0);
}
@@ -263,14 +261,10 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize)
/* get the number of unused cells safely */
int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f)
{
int cells;
if (!f)
return 0;
snd_use_lock_use(&f->use_lock);
scoped_guard(spinlock_irqsave, &f->lock)
cells = snd_seq_unused_cells(f->pool);
snd_use_lock_free(&f->use_lock);
return cells;
guard(snd_seq_fifo)(f);
guard(spinlock_irqsave)(&f->lock);
return snd_seq_unused_cells(f->pool);
}

View File

@@ -37,6 +37,7 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, struct snd_seq_event *event);
/* lock fifo from release */
#define snd_seq_fifo_lock(fifo) snd_use_lock_use(&(fifo)->use_lock)
#define snd_seq_fifo_unlock(fifo) snd_use_lock_free(&(fifo)->use_lock)
DEFINE_GUARD(snd_seq_fifo, struct snd_seq_fifo *, snd_seq_fifo_lock(_T), snd_seq_fifo_unlock(_T))
/* get a cell from fifo - fifo should be locked */
int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, struct snd_seq_event_cell **cellp, int nonblock);

View File

@@ -178,17 +178,10 @@ static int unsubscribe_port(struct snd_seq_client *client,
static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
struct snd_seq_client **cp)
{
struct snd_seq_client_port *p;
*cp = snd_seq_client_use_ptr(addr->client);
if (*cp) {
p = snd_seq_port_use_ptr(*cp, addr->port);
if (! p) {
snd_seq_client_unlock(*cp);
*cp = NULL;
}
return p;
}
return NULL;
if (!*cp)
return NULL;
return snd_seq_port_use_ptr(*cp, addr->port);
}
static void delete_and_unsubscribe_port(struct snd_seq_client *client,
@@ -218,8 +211,8 @@ static void clear_subscriber_list(struct snd_seq_client *client,
list_for_each_safe(p, n, &grp->list_head) {
struct snd_seq_subscribers *subs;
struct snd_seq_client *c;
struct snd_seq_client_port *aport;
struct snd_seq_client *c __free(snd_seq_client) = NULL;
struct snd_seq_client_port *aport __free(snd_seq_port) = NULL;
subs = get_subscriber(p, is_src);
if (is_src)
@@ -241,8 +234,6 @@ static void clear_subscriber_list(struct snd_seq_client *client,
/* ok we got the connected port */
delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
kfree(subs);
snd_seq_port_unlock(aport);
snd_seq_client_unlock(c);
}
}

View File

@@ -96,6 +96,8 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl
/* unlock the port */
#define snd_seq_port_unlock(port) snd_use_lock_free(&(port)->use_lock)
DEFINE_FREE(snd_seq_port, struct snd_seq_client_port *, if (!IS_ERR_OR_NULL(_T)) snd_seq_port_unlock(_T))
/* create a port, port number or a negative error code is returned */
int snd_seq_create_port(struct snd_seq_client *client, int port_index,
struct snd_seq_client_port **port_ret);

View File

@@ -209,14 +209,13 @@ struct snd_seq_queue *queueptr(int queueid)
struct snd_seq_queue *snd_seq_queue_find_name(char *name)
{
int i;
struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
q = queueptr(i);
if (q) {
if (strncmp(q->name, name, sizeof(q->name)) == 0)
return q;
queuefree(q);
return no_free_ptr(q);
}
}
return NULL;
@@ -286,7 +285,7 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop)
{
int dest, err;
struct snd_seq_queue *q;
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
if (snd_BUG_ON(!cell))
return -EINVAL;
@@ -321,16 +320,12 @@ int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop)
break;
}
if (err < 0) {
queuefree(q); /* unlock */
if (err < 0)
return err;
}
/* trigger dispatching */
snd_seq_check_queue(q, atomic, hop);
queuefree(q); /* unlock */
return 0;
}
@@ -366,15 +361,12 @@ static inline void queue_access_unlock(struct snd_seq_queue *q)
/* exported - only checking permission */
int snd_seq_queue_check_access(int queueid, int client)
{
struct snd_seq_queue *q = queueptr(queueid);
int access_ok;
struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(queueid);
if (! q)
return 0;
scoped_guard(spinlock_irqsave, &q->owner_lock)
access_ok = check_access(q, client);
queuefree(q);
return access_ok;
guard(spinlock_irqsave)(&q->owner_lock);
return check_access(q, client);
}
/*----------------------------------------------------------------*/
@@ -384,22 +376,19 @@ int snd_seq_queue_check_access(int queueid, int client)
*/
int snd_seq_queue_set_owner(int queueid, int client, int locked)
{
struct snd_seq_queue *q = queueptr(queueid);
struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(queueid);
if (q == NULL)
return -EINVAL;
if (! queue_access_lock(q, client)) {
queuefree(q);
if (!queue_access_lock(q, client))
return -EPERM;
}
scoped_guard(spinlock_irqsave, &q->owner_lock) {
q->locked = locked ? 1 : 0;
q->owner = client;
}
queue_access_unlock(q);
queuefree(q);
return 0;
}
@@ -414,7 +403,7 @@ int snd_seq_queue_set_owner(int queueid, int client, int locked)
int snd_seq_queue_timer_open(int queueid)
{
int result = 0;
struct snd_seq_queue *queue;
struct snd_seq_queue *queue __free(snd_seq_queue) = NULL;
struct snd_seq_timer *tmr;
queue = queueptr(queueid);
@@ -426,7 +415,6 @@ int snd_seq_queue_timer_open(int queueid)
snd_seq_timer_defaults(tmr);
result = snd_seq_timer_open(queue);
}
queuefree(queue);
return result;
}
@@ -435,14 +423,13 @@ int snd_seq_queue_timer_open(int queueid)
*/
int snd_seq_queue_timer_close(int queueid)
{
struct snd_seq_queue *queue;
struct snd_seq_queue *queue __free(snd_seq_queue) = NULL;
int result = 0;
queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
snd_seq_timer_close(queue);
queuefree(queue);
return result;
}
@@ -450,15 +437,13 @@ int snd_seq_queue_timer_close(int queueid)
int snd_seq_queue_timer_set_tempo(int queueid, int client,
struct snd_seq_queue_tempo *info)
{
struct snd_seq_queue *q = queueptr(queueid);
struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(queueid);
int result;
if (q == NULL)
return -EINVAL;
if (! queue_access_lock(q, client)) {
queuefree(q);
if (!queue_access_lock(q, client))
return -EPERM;
}
result = snd_seq_timer_set_tempo_ppq(q->timer, info->tempo, info->ppq,
info->tempo_base);
@@ -466,7 +451,6 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client,
result = snd_seq_timer_set_skew(q->timer, info->skew_value,
info->skew_base);
queue_access_unlock(q);
queuefree(q);
return result;
}
@@ -495,15 +479,13 @@ static void queue_use(struct snd_seq_queue *queue, int client, int use)
*/
int snd_seq_queue_use(int queueid, int client, int use)
{
struct snd_seq_queue *queue;
struct snd_seq_queue *queue __free(snd_seq_queue) = NULL;
queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
mutex_lock(&queue->timer_mutex);
guard(mutex)(&queue->timer_mutex);
queue_use(queue, client, use);
mutex_unlock(&queue->timer_mutex);
queuefree(queue);
return 0;
}
@@ -514,15 +496,12 @@ int snd_seq_queue_use(int queueid, int client, int use)
*/
int snd_seq_queue_is_used(int queueid, int client)
{
struct snd_seq_queue *q;
int result;
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
q = queueptr(queueid);
if (q == NULL)
return -EINVAL; /* invalid queue */
result = test_bit(client, q->clients_bitmap) ? 1 : 0;
queuefree(q);
return result;
return test_bit(client, q->clients_bitmap) ? 1 : 0;
}
@@ -535,11 +514,10 @@ int snd_seq_queue_is_used(int queueid, int client)
void snd_seq_queue_client_leave(int client)
{
int i;
struct snd_seq_queue *q;
/* delete own queues from queue list */
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
q = queue_list_remove(i, client);
struct snd_seq_queue *q = queue_list_remove(i, client);
if (q)
queue_delete(q);
}
@@ -548,7 +526,7 @@ void snd_seq_queue_client_leave(int client)
* they are not owned by this client
*/
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
q = queueptr(i);
struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(i);
if (!q)
continue;
if (test_bit(client, q->clients_bitmap)) {
@@ -556,7 +534,6 @@ void snd_seq_queue_client_leave(int client)
snd_seq_prioq_leave(q->timeq, client, 0);
snd_seq_queue_use(q->queue, client, 0);
}
queuefree(q);
}
}
@@ -568,10 +545,9 @@ void snd_seq_queue_client_leave(int client)
void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info)
{
int i;
struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
q = queueptr(i);
struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(i);
if (!q)
continue;
if (test_bit(client, q->clients_bitmap) &&
@@ -580,7 +556,6 @@ void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info)
snd_seq_prioq_remove_events(q->tickq, client, info);
snd_seq_prioq_remove_events(q->timeq, client, info);
}
queuefree(q);
}
}
@@ -667,7 +642,7 @@ static void snd_seq_queue_process_event(struct snd_seq_queue *q,
*/
int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop)
{
struct snd_seq_queue *q;
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
if (snd_BUG_ON(!ev))
return -EINVAL;
@@ -676,15 +651,12 @@ int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop)
if (q == NULL)
return -EINVAL;
if (! queue_access_lock(q, ev->source.client)) {
queuefree(q);
if (!queue_access_lock(q, ev->source.client))
return -EPERM;
}
snd_seq_queue_process_event(q, ev, atomic, hop);
queue_access_unlock(q);
queuefree(q);
return 0;
}
@@ -697,13 +669,12 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
int i, bpm;
struct snd_seq_queue *q;
struct snd_seq_timer *tmr;
bool locked;
int owner;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
q = queueptr(i);
struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(i);
if (!q)
continue;
@@ -731,7 +702,6 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "current time : %d.%09d s\n", tmr->cur_time.tv_sec, tmr->cur_time.tv_nsec);
snd_iprintf(buffer, "current tick : %d\n", tmr->tick.cur_tick);
snd_iprintf(buffer, "\n");
queuefree(q);
}
}
#endif /* CONFIG_SND_PROC_FS */

View File

@@ -73,6 +73,8 @@ struct snd_seq_queue *queueptr(int queueid);
/* unlock */
#define queuefree(q) snd_use_lock_free(&(q)->use_lock)
DEFINE_FREE(snd_seq_queue, struct snd_seq_queue *, if (!IS_ERR_OR_NULL(_T)) queuefree(_T))
/* return the (first) queue matching with the specified name */
struct snd_seq_queue *snd_seq_queue_find_name(char *name);

View File

@@ -440,13 +440,13 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
int idx;
struct snd_seq_queue *q;
struct snd_seq_timer *tmr;
struct snd_timer_instance *ti;
unsigned long resolution;
for (idx = 0; idx < SNDRV_SEQ_MAX_QUEUES; idx++) {
q = queueptr(idx);
struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(idx);
if (q == NULL)
continue;
scoped_guard(mutex, &q->timer_mutex) {
@@ -461,7 +461,6 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry,
snd_iprintf(buffer, " Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000);
snd_iprintf(buffer, " Skew : %u / %u\n", tmr->skew, tmr->skew_base);
}
queuefree(q);
}
}
#endif /* CONFIG_SND_PROC_FS */

View File

@@ -414,39 +414,39 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
dpcm->last_jiffies = jiffies;
dpcm->pcm_rate_shift = 0;
dpcm->last_drift = 0;
spin_lock(&cable->lock);
cable->running |= stream;
cable->pause &= ~stream;
err = cable->ops->start(dpcm);
spin_unlock(&cable->lock);
scoped_guard(spinlock, &cable->lock) {
cable->running |= stream;
cable->pause &= ~stream;
err = cable->ops->start(dpcm);
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
loopback_active_notify(dpcm);
break;
case SNDRV_PCM_TRIGGER_STOP:
spin_lock(&cable->lock);
cable->running &= ~stream;
cable->pause &= ~stream;
err = cable->ops->stop(dpcm);
spin_unlock(&cable->lock);
scoped_guard(spinlock, &cable->lock) {
cable->running &= ~stream;
cable->pause &= ~stream;
err = cable->ops->stop(dpcm);
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
loopback_active_notify(dpcm);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
spin_lock(&cable->lock);
cable->pause |= stream;
err = cable->ops->stop(dpcm);
spin_unlock(&cable->lock);
scoped_guard(spinlock, &cable->lock) {
cable->pause |= stream;
err = cable->ops->stop(dpcm);
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
loopback_active_notify(dpcm);
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
spin_lock(&cable->lock);
dpcm->last_jiffies = jiffies;
cable->pause &= ~stream;
err = cable->ops->start(dpcm);
spin_unlock(&cable->lock);
scoped_guard(spinlock, &cable->lock) {
dpcm->last_jiffies = jiffies;
cable->pause &= ~stream;
err = cable->ops->start(dpcm);
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
loopback_active_notify(dpcm);
break;
@@ -511,13 +511,12 @@ static int loopback_prepare(struct snd_pcm_substream *substream)
dpcm->pcm_salign = salign;
dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size);
mutex_lock(&dpcm->loopback->cable_lock);
guard(mutex)(&dpcm->loopback->cable_lock);
if (!(cable->valid & ~(1 << substream->stream)) ||
(get_setup(dpcm)->notify &&
substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
params_change(substream);
cable->valid |= 1 << substream->stream;
mutex_unlock(&dpcm->loopback->cable_lock);
return 0;
}
@@ -701,21 +700,22 @@ static unsigned int loopback_jiffies_timer_pos_update
static void loopback_jiffies_timer_function(struct timer_list *t)
{
struct loopback_pcm *dpcm = timer_container_of(dpcm, t, timer);
unsigned long flags;
bool period_elapsed = false;
spin_lock_irqsave(&dpcm->cable->lock, flags);
if (loopback_jiffies_timer_pos_update(dpcm->cable) &
(1 << dpcm->substream->stream)) {
loopback_jiffies_timer_start(dpcm);
if (dpcm->period_update_pending) {
dpcm->period_update_pending = 0;
spin_unlock_irqrestore(&dpcm->cable->lock, flags);
/* need to unlock before calling below */
snd_pcm_period_elapsed(dpcm->substream);
return;
scoped_guard(spinlock_irqsave, &dpcm->cable->lock) {
if (loopback_jiffies_timer_pos_update(dpcm->cable) &
(1 << dpcm->substream->stream)) {
loopback_jiffies_timer_start(dpcm);
if (dpcm->period_update_pending) {
dpcm->period_update_pending = 0;
period_elapsed = true;
break;
}
}
}
spin_unlock_irqrestore(&dpcm->cable->lock, flags);
if (period_elapsed)
snd_pcm_period_elapsed(dpcm->substream);
}
/* call in cable->lock */
@@ -760,69 +760,69 @@ static void loopback_snd_timer_period_elapsed(struct loopback_cable *cable,
struct snd_pcm_substream *substream_play, *substream_capt;
struct snd_pcm_runtime *valid_runtime;
unsigned int running, elapsed_bytes;
unsigned long flags;
bool xrun = false;
spin_lock_irqsave(&cable->lock, flags);
running = cable->running ^ cable->pause;
/* no need to do anything if no stream is running */
if (!running) {
spin_unlock_irqrestore(&cable->lock, flags);
scoped_guard(spinlock_irqsave, &cable->lock) {
running = cable->running ^ cable->pause;
/* no need to do anything if no stream is running */
if (!running)
return;
dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE];
if (event == SNDRV_TIMER_EVENT_MSTOP) {
if (!dpcm_play ||
dpcm_play->substream->runtime->state !=
SNDRV_PCM_STATE_DRAINING)
return;
}
substream_play = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ?
dpcm_play->substream : NULL;
substream_capt = (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) ?
dpcm_capt->substream : NULL;
valid_runtime = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ?
dpcm_play->substream->runtime :
dpcm_capt->substream->runtime;
/* resolution is only valid for SNDRV_TIMER_EVENT_TICK events */
if (event == SNDRV_TIMER_EVENT_TICK) {
/* The hardware rules guarantee that playback and capture period
* are the same. Therefore only one device has to be checked
* here.
*/
if (loopback_snd_timer_check_resolution(valid_runtime,
resolution) < 0) {
xrun = true;
break;
}
}
elapsed_bytes = frames_to_bytes(valid_runtime,
valid_runtime->period_size);
/* The same timer interrupt is used for playback and capture device */
if ((running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&
(running & (1 << SNDRV_PCM_STREAM_CAPTURE))) {
copy_play_buf(dpcm_play, dpcm_capt, elapsed_bytes);
bytepos_finish(dpcm_play, elapsed_bytes);
bytepos_finish(dpcm_capt, elapsed_bytes);
} else if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
bytepos_finish(dpcm_play, elapsed_bytes);
} else if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) {
clear_capture_buf(dpcm_capt, elapsed_bytes);
bytepos_finish(dpcm_capt, elapsed_bytes);
}
}
if (xrun) {
if (substream_play)
snd_pcm_stop_xrun(substream_play);
if (substream_capt)
snd_pcm_stop_xrun(substream_capt);
return;
}
dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE];
if (event == SNDRV_TIMER_EVENT_MSTOP) {
if (!dpcm_play ||
dpcm_play->substream->runtime->state !=
SNDRV_PCM_STATE_DRAINING) {
spin_unlock_irqrestore(&cable->lock, flags);
return;
}
}
substream_play = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ?
dpcm_play->substream : NULL;
substream_capt = (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) ?
dpcm_capt->substream : NULL;
valid_runtime = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ?
dpcm_play->substream->runtime :
dpcm_capt->substream->runtime;
/* resolution is only valid for SNDRV_TIMER_EVENT_TICK events */
if (event == SNDRV_TIMER_EVENT_TICK) {
/* The hardware rules guarantee that playback and capture period
* are the same. Therefore only one device has to be checked
* here.
*/
if (loopback_snd_timer_check_resolution(valid_runtime,
resolution) < 0) {
spin_unlock_irqrestore(&cable->lock, flags);
if (substream_play)
snd_pcm_stop_xrun(substream_play);
if (substream_capt)
snd_pcm_stop_xrun(substream_capt);
return;
}
}
elapsed_bytes = frames_to_bytes(valid_runtime,
valid_runtime->period_size);
/* The same timer interrupt is used for playback and capture device */
if ((running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&
(running & (1 << SNDRV_PCM_STREAM_CAPTURE))) {
copy_play_buf(dpcm_play, dpcm_capt, elapsed_bytes);
bytepos_finish(dpcm_play, elapsed_bytes);
bytepos_finish(dpcm_capt, elapsed_bytes);
} else if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
bytepos_finish(dpcm_play, elapsed_bytes);
} else if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) {
clear_capture_buf(dpcm_capt, elapsed_bytes);
bytepos_finish(dpcm_capt, elapsed_bytes);
}
spin_unlock_irqrestore(&cable->lock, flags);
if (substream_play)
snd_pcm_period_elapsed(substream_play);
if (substream_capt)
@@ -910,11 +910,10 @@ static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
struct loopback_pcm *dpcm = runtime->private_data;
snd_pcm_uframes_t pos;
spin_lock(&dpcm->cable->lock);
guard(spinlock)(&dpcm->cable->lock);
if (dpcm->cable->ops->pos_update)
dpcm->cable->ops->pos_update(dpcm->cable);
pos = dpcm->buf_pos;
spin_unlock(&dpcm->cable->lock);
return bytes_to_frames(runtime, pos);
}
@@ -958,9 +957,8 @@ static int loopback_hw_free(struct snd_pcm_substream *substream)
struct loopback_pcm *dpcm = runtime->private_data;
struct loopback_cable *cable = dpcm->cable;
mutex_lock(&dpcm->loopback->cable_lock);
guard(mutex)(&dpcm->loopback->cable_lock);
cable->valid &= ~(1 << substream->stream);
mutex_unlock(&dpcm->loopback->cable_lock);
return 0;
}
@@ -980,10 +978,10 @@ static int rule_format(struct snd_pcm_hw_params *params,
struct snd_mask m;
snd_mask_none(&m);
mutex_lock(&dpcm->loopback->cable_lock);
m.bits[0] = (u_int32_t)cable->hw.formats;
m.bits[1] = (u_int32_t)(cable->hw.formats >> 32);
mutex_unlock(&dpcm->loopback->cable_lock);
scoped_guard(mutex, &dpcm->loopback->cable_lock) {
m.bits[0] = (u_int32_t)cable->hw.formats;
m.bits[1] = (u_int32_t)(cable->hw.formats >> 32);
}
return snd_mask_refine(hw_param_mask(params, rule->var), &m);
}
@@ -994,10 +992,10 @@ static int rule_rate(struct snd_pcm_hw_params *params,
struct loopback_cable *cable = dpcm->cable;
struct snd_interval t;
mutex_lock(&dpcm->loopback->cable_lock);
t.min = cable->hw.rate_min;
t.max = cable->hw.rate_max;
mutex_unlock(&dpcm->loopback->cable_lock);
scoped_guard(mutex, &dpcm->loopback->cable_lock) {
t.min = cable->hw.rate_min;
t.max = cable->hw.rate_max;
}
t.openmin = t.openmax = 0;
t.integer = 0;
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
@@ -1010,10 +1008,10 @@ static int rule_channels(struct snd_pcm_hw_params *params,
struct loopback_cable *cable = dpcm->cable;
struct snd_interval t;
mutex_lock(&dpcm->loopback->cable_lock);
t.min = cable->hw.channels_min;
t.max = cable->hw.channels_max;
mutex_unlock(&dpcm->loopback->cable_lock);
scoped_guard(mutex, &dpcm->loopback->cable_lock) {
t.min = cable->hw.channels_min;
t.max = cable->hw.channels_max;
}
t.openmin = t.openmax = 0;
t.integer = 0;
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
@@ -1026,10 +1024,10 @@ static int rule_period_bytes(struct snd_pcm_hw_params *params,
struct loopback_cable *cable = dpcm->cable;
struct snd_interval t;
mutex_lock(&dpcm->loopback->cable_lock);
t.min = cable->hw.period_bytes_min;
t.max = cable->hw.period_bytes_max;
mutex_unlock(&dpcm->loopback->cable_lock);
scoped_guard(mutex, &dpcm->loopback->cable_lock) {
t.min = cable->hw.period_bytes_min;
t.max = cable->hw.period_bytes_max;
}
t.openmin = 0;
t.openmax = 0;
t.integer = 0;
@@ -1047,9 +1045,8 @@ static void free_cable(struct snd_pcm_substream *substream)
return;
if (cable->streams[!substream->stream]) {
/* other stream is still alive */
spin_lock_irq(&cable->lock);
guard(spinlock_irq)(&cable->lock);
cable->streams[substream->stream] = NULL;
spin_unlock_irq(&cable->lock);
} else {
struct loopback_pcm *dpcm = substream->runtime->private_data;
@@ -1238,12 +1235,10 @@ static int loopback_open(struct snd_pcm_substream *substream)
int err = 0;
int dev = get_cable_index(substream);
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
if (!dpcm) {
err = -ENOMEM;
goto unlock;
}
if (!dpcm)
return -ENOMEM;
dpcm->loopback = loopback;
dpcm->substream = substream;
@@ -1317,16 +1312,15 @@ static int loopback_open(struct snd_pcm_substream *substream)
else
runtime->hw = cable->hw;
spin_lock_irq(&cable->lock);
cable->streams[substream->stream] = dpcm;
spin_unlock_irq(&cable->lock);
scoped_guard(spinlock_irq, &cable->lock) {
cable->streams[substream->stream] = dpcm;
}
unlock:
if (err < 0) {
free_cable(substream);
kfree(dpcm);
}
mutex_unlock(&loopback->cable_lock);
return err;
}
@@ -1338,9 +1332,8 @@ static int loopback_close(struct snd_pcm_substream *substream)
if (dpcm->cable->ops->close_substream)
err = dpcm->cable->ops->close_substream(dpcm);
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
free_cable(substream);
mutex_unlock(&loopback->cable_lock);
return err;
}
@@ -1391,11 +1384,10 @@ static int loopback_rate_shift_get(struct snd_kcontrol *kcontrol,
{
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
ucontrol->value.integer.value[0] =
loopback->setup[kcontrol->id.subdevice]
[kcontrol->id.device].rate_shift;
mutex_unlock(&loopback->cable_lock);
return 0;
}
@@ -1411,14 +1403,13 @@ static int loopback_rate_shift_put(struct snd_kcontrol *kcontrol,
val = 80000;
if (val > 120000)
val = 120000;
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
if (val != loopback->setup[kcontrol->id.subdevice]
[kcontrol->id.device].rate_shift) {
loopback->setup[kcontrol->id.subdevice]
[kcontrol->id.device].rate_shift = val;
change = 1;
}
mutex_unlock(&loopback->cable_lock);
return change;
}
@@ -1427,11 +1418,10 @@ static int loopback_notify_get(struct snd_kcontrol *kcontrol,
{
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
ucontrol->value.integer.value[0] =
loopback->setup[kcontrol->id.subdevice]
[kcontrol->id.device].notify;
mutex_unlock(&loopback->cable_lock);
return 0;
}
@@ -1443,14 +1433,13 @@ static int loopback_notify_put(struct snd_kcontrol *kcontrol,
int change = 0;
val = ucontrol->value.integer.value[0] ? 1 : 0;
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
if (val != loopback->setup[kcontrol->id.subdevice]
[kcontrol->id.device].notify) {
loopback->setup[kcontrol->id.subdevice]
[kcontrol->id.device].notify = val;
change = 1;
}
mutex_unlock(&loopback->cable_lock);
return change;
}
@@ -1462,14 +1451,13 @@ static int loopback_active_get(struct snd_kcontrol *kcontrol,
unsigned int val = 0;
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
cable = loopback->cables[kcontrol->id.subdevice][kcontrol->id.device ^ 1];
if (cable != NULL) {
unsigned int running = cable->running ^ cable->pause;
val = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? 1 : 0;
}
mutex_unlock(&loopback->cable_lock);
ucontrol->value.integer.value[0] = val;
return 0;
}
@@ -1512,11 +1500,10 @@ static int loopback_rate_get(struct snd_kcontrol *kcontrol,
{
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
ucontrol->value.integer.value[0] =
loopback->setup[kcontrol->id.subdevice]
[kcontrol->id.device].rate;
mutex_unlock(&loopback->cable_lock);
return 0;
}
@@ -1536,11 +1523,10 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
{
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
ucontrol->value.integer.value[0] =
loopback->setup[kcontrol->id.subdevice]
[kcontrol->id.device].channels;
mutex_unlock(&loopback->cable_lock);
return 0;
}
@@ -1558,12 +1544,11 @@ static int loopback_access_get(struct snd_kcontrol *kcontrol,
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
snd_pcm_access_t access;
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
access = loopback->setup[kcontrol->id.subdevice][kcontrol->id.device].access;
ucontrol->value.enumerated.item[0] = !is_access_interleaved(access);
mutex_unlock(&loopback->cable_lock);
return 0;
}
@@ -1731,12 +1716,11 @@ static void print_cable_info(struct snd_info_entry *entry,
struct loopback *loopback = entry->private_data;
int sub, num;
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
num = entry->name[strlen(entry->name)-1];
num = num == '0' ? 0 : 1;
for (sub = 0; sub < MAX_PCM_SUBSTREAMS; sub++)
print_substream_info(buffer, loopback, sub, num);
mutex_unlock(&loopback->cable_lock);
}
static int loopback_cable_proc_new(struct loopback *loopback, int cidx)
@@ -1765,10 +1749,9 @@ static void print_timer_source_info(struct snd_info_entry *entry,
{
struct loopback *loopback = entry->private_data;
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
snd_iprintf(buffer, "%s\n",
loopback->timer_source ? loopback->timer_source : "");
mutex_unlock(&loopback->cable_lock);
}
static void change_timer_source_info(struct snd_info_entry *entry,
@@ -1777,10 +1760,9 @@ static void change_timer_source_info(struct snd_info_entry *entry,
struct loopback *loopback = entry->private_data;
char line[64];
mutex_lock(&loopback->cable_lock);
guard(mutex)(&loopback->cable_lock);
if (!snd_info_get_line(buffer, line, sizeof(line)))
loopback_set_timer_source(loopback, strim(line));
mutex_unlock(&loopback->cable_lock);
}
static int loopback_timer_source_proc_new(struct loopback *loopback)

Some files were not shown because too many files have changed in this diff Show More