mirror of
https://github.com/torvalds/linux.git
synced 2025-11-30 23:16:01 +07:00
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:
@@ -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>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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:
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
@@ -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";
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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#
|
||||
|
||||
|
||||
101
Documentation/devicetree/bindings/sound/foursemi,fs2105s.yaml
Normal file
101
Documentation/devicetree/bindings/sound/foursemi,fs2105s.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -23,6 +23,9 @@ properties:
|
||||
|
||||
sound-name-prefix: true
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
required:
|
||||
- "#sound-dai-cells"
|
||||
- compatible
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
...
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
...
|
||||
@@ -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";
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
@@ -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#
|
||||
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
134
Documentation/devicetree/bindings/sound/qcom,pm4125-codec.yaml
Normal file
134
Documentation/devicetree/bindings/sound/qcom,pm4125-codec.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
...
|
||||
79
Documentation/devicetree/bindings/sound/qcom,pm4125-sdw.yaml
Normal file
79
Documentation/devicetree/bindings/sound/qcom,pm4125-sdw.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
54
Documentation/devicetree/bindings/sound/realtek,alc5623.yaml
Normal file
54
Documentation/devicetree/bindings/sound/realtek,alc5623.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
98
Documentation/devicetree/bindings/sound/ti,omap-twl4030.yaml
Normal file
98
Documentation/devicetree/bindings/sound/ti,omap-twl4030.yaml
Normal 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>;
|
||||
};
|
||||
55
Documentation/devicetree/bindings/sound/ti,pcm1754.yaml
Normal file
55
Documentation/devicetree/bindings/sound/ti,pcm1754.yaml
Normal 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>;
|
||||
};
|
||||
@@ -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:
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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,.*":
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
10
MAINTAINERS
10
MAINTAINERS
@@ -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*.*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 *);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
259
include/sound/tas2x20-tlv.h
Normal 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
|
||||
24
include/sound/tas5825-tlv.h
Normal file
24
include/sound/tas5825-tlv.h
Normal 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
|
||||
@@ -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 */
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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(¬if->mutex);
|
||||
guard(mutex)(¬if->mutex);
|
||||
if (notif->notify)
|
||||
notif->notify(notif->data);
|
||||
mutex_unlock(¬if->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(¬if->mutex);
|
||||
guard(mutex)(¬if->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(¬if->mutex);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ftr_get_detect(struct gpio_runtime *rt,
|
||||
|
||||
@@ -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(¬if->mutex);
|
||||
guard(mutex)(¬if->mutex);
|
||||
if (notif->notify)
|
||||
notif->notify(notif->data);
|
||||
mutex_unlock(¬if->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(¬if->mutex);
|
||||
guard(mutex)(¬if->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(¬if->mutex);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmf_get_detect(struct gpio_runtime *rt,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
168
sound/arm/aaci.c
168
sound/arm/aaci.c
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(®ister_mutex);
|
||||
rc = snd_seq_oss_open(file, level);
|
||||
mutex_unlock(®ister_mutex);
|
||||
|
||||
return rc;
|
||||
guard(mutex)(®ister_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(®ister_mutex);
|
||||
guard(mutex)(®ister_mutex);
|
||||
snd_seq_oss_release(dp);
|
||||
mutex_unlock(®ister_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -229,13 +224,12 @@ register_device(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
mutex_lock(®ister_mutex);
|
||||
guard(mutex)(®ister_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(®ister_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(®ister_mutex);
|
||||
return rc;
|
||||
}
|
||||
mutex_unlock(®ister_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
unregister_device(void)
|
||||
{
|
||||
mutex_lock(®ister_mutex);
|
||||
guard(mutex)(®ister_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(®ister_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(®ister_mutex);
|
||||
guard(mutex)(®ister_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(®ister_mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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(®ister_lock, flags);
|
||||
guard(spinlock_irqsave)(®ister_lock);
|
||||
mdev = midi_devs[dev];
|
||||
if (mdev)
|
||||
snd_use_lock_use(&mdev->use_lock);
|
||||
spin_unlock_irqrestore(®ister_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(®ister_lock, flags);
|
||||
guard(spinlock_irqsave)(®ister_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(®ister_lock, flags);
|
||||
return mdev;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(®ister_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(®ister_lock, flags);
|
||||
guard(spinlock_irqsave)(®ister_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(®ister_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(®ister_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(®ister_lock, flags);
|
||||
midi_devs[mdev->seq_device] = NULL;
|
||||
spin_unlock_irqrestore(®ister_lock, flags);
|
||||
scoped_guard(spinlock_irqsave, ®ister_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(®ister_lock, flags);
|
||||
guard(spinlock_irqsave)(®ister_lock);
|
||||
for (index = max_midi_devs - 1; index >= 0; index--) {
|
||||
if (midi_devs[index])
|
||||
break;
|
||||
}
|
||||
max_midi_devs = index + 1;
|
||||
spin_unlock_irqrestore(®ister_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(®ister_lock, flags);
|
||||
guard(spinlock_irqsave)(®ister_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(®ister_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(®ister_lock);
|
||||
guard(spinlock_irq)(®ister_lock);
|
||||
dp->max_mididev = max_midi_devs;
|
||||
spin_unlock_irq(®ister_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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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(®ister_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(®ister_lock, flags);
|
||||
pr_err("ALSA: seq_oss: no more synth slot\n");
|
||||
kfree(rec);
|
||||
return -ENOMEM;
|
||||
scoped_guard(spinlock_irqsave, ®ister_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(®ister_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(®ister_lock, flags);
|
||||
for (index = 0; index < max_synth_devs; index++) {
|
||||
if (synth_devs[index] == rec)
|
||||
break;
|
||||
}
|
||||
if (index >= max_synth_devs) {
|
||||
spin_unlock_irqrestore(®ister_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, ®ister_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(®ister_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(®ister_lock, flags);
|
||||
guard(spinlock_irqsave)(®ister_lock);
|
||||
rec = synth_devs[dev];
|
||||
if (rec)
|
||||
snd_use_lock_use(&rec->use_lock);
|
||||
spin_unlock_irqrestore(®ister_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 */
|
||||
|
||||
@@ -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
@@ -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];
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user