mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
sound updates for 6.12-rc1
A fairly big update at this time, both in core and driver sides. The core received rewrites in PCM buffer allocation handling and locking optimizations, PCM rate updates followed by lots of cleanups. In ASoC side, the legacy Intel drivers have been deprecated by AVS drivers which leaded to the significant amount of code reduction. SoundWire driver updates and other cleanups contributed more code reduction, too. USB-audio driver received a large cleanup of its big quirk table, and the old snd_print*() API usages in many legacy drivers are replaced with the standard print API. Here are some highlights: Core: - More optimized locking in ALSA control code - Rewrites of memalloc helpers for better DMA API usage - Drop of obsoleted vmalloc PCM buffer helper API - Continued MIDI2 UMP updates - Support of a new user-space driven timer instance - Update for more PCM support rates and cleanups - Xrun counter report in the proc files ASoC: - Continued simplification and cleanup works for ASoC - Extensive cleanups and refactoring of the Soundwire drivers - Removal of Intel machine support obsoleted by the AVS driver - Lots of DT schema conversions - Machine support for many AMD and Intel x86 platforms - Support for AMD ACP 7.1, Mediatek MT6367 and MT8365, Realtek RTL1320 SoundWire and rev C, and Texas Instruments TAS2563 USB-audio: - Add support of multiple control interfaces - A large rewrite of quirk table with macros - Support for RME Digiface USB HD-audio: - Cleanup of quirk code for Samsung Galaxy laptops - Clean up of detection of Cirrus codecs - C-Media CM9825 HD-audio codec support Others: - Rewrites to standard print API in a lot of legacy drivers -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmblvDMOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE823BAAktHgwGbgu+s/U4osgk5M+x1IAzbbRFDEEhuG Pck6K1NikgUGXg/x/m6O0/M4CmLcGv7NeebD4ihJJPxdK7fpsEOcIeCiPoWfpumN whtrzf6DP6gMxrE/ov4qUydItuCGVNWcEF/bWv7inEcoJ+qtqiRAWLGvpwQurrvn NwO+9V/L8NSTWiZVX5ve1+hVVxpLoEQEhRpvMfrVyPXgX0zXgSexka9pwSdb+3xD vkIKQ1ju1JD8HG6JLfsIOBQYndrz3KLYWhozzrPKh+hGz3vOkhUPrfhYz5hyoWO9 Ep95ZHF4ynAIV0pHlsQTH79BmkxmAJKVQImYHOnOWDvL4T6OVpoY6bzIMXzE9IHJ p/5JkG422qguoqIEBhM1mkggdXXIjwARFEtqQs+NvUErAd2Pnckl38TSrBtswa1c FcEjVq8MfIMFroDIPbEt6UY5K5GLWjwFG8rYFYbbEI4qIMLYSi4pbGtedpGxVZ4P eZGbAlAL6cpzXhTh90maA+NXSyeZUl9Tg8aHF48WjkU8LsEi9fHW/YU8JYyMfyQ3 nYWAZocvXOlIpul8MOPVOg1vXpFKhSVXITKXolQQK1e/C3PirfWsrDxbdF8HduTi tfVGPiHprwPw2PE0E7ZqjBO1nRLMGcCqv2Iz69lFisPprDJr75C4voPDK+rjo7We YIhyUMU= =HLUp -----END PGP SIGNATURE----- Merge tag 'sound-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "A fairly big update at this time, both in core and driver sides. The core received rewrites in PCM buffer allocation handling and locking optimizations, PCM rate updates followed by lots of cleanups. In ASoC side, the legacy Intel drivers have been deprecated by AVS drivers which leaded to the significant amount of code reduction. SoundWire driver updates and other cleanups contributed more code reduction, too. USB-audio driver received a large cleanup of its big quirk table, and the old snd_print*() API usages in many legacy drivers are replaced with the standard print API. Here are some highlights: Core: - More optimized locking in ALSA control code - Rewrites of memalloc helpers for better DMA API usage - Drop of obsoleted vmalloc PCM buffer helper API - Continued MIDI2 UMP updates - Support of a new user-space driven timer instance - Update for more PCM support rates and cleanups - Xrun counter report in the proc files ASoC: - Continued simplification and cleanup works for ASoC - Extensive cleanups and refactoring of the Soundwire drivers - Removal of Intel machine support obsoleted by the AVS driver - Lots of DT schema conversions - Machine support for many AMD and Intel x86 platforms - Support for AMD ACP 7.1, Mediatek MT6367 and MT8365, Realtek RTL1320 SoundWire and rev C, and Texas Instruments TAS2563 USB-audio: - Add support of multiple control interfaces - A large rewrite of quirk table with macros - Support for RME Digiface USB HD-audio: - Cleanup of quirk code for Samsung Galaxy laptops - Clean up of detection of Cirrus codecs - C-Media CM9825 HD-audio codec support Others: - Rewrites to standard print API in a lot of legacy drivers" * tag 'sound-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (410 commits) ASoC: topology: Fix redundant logical jump ASoC: tas2781: Add Calibration Kcontrols for Chromebook ASoC: amd: acp: refactor SoundWire machine driver code ASoC: sdw_utils/intel: move soundwire endpoint parsing helper functions ASoC: sdw_util/intel: move soundwire endpoint and dai link structures ASoC: intel: sof_sdw: rename soundwire parsing helper functions ASoC: intel: sof_sdw: rename soundwire endpoint and dailink structures ASoC: atmel: mchp-pdmc: Retain Non-Runtime Controls ALSA: hda/realtek: Add support for Galaxy Book2 Pro (NP950XEE) ASoC: mediatek: mt7986-afe-pcm: Remove redundant error message ALSA: memalloc: Use proper DMA mapping API for x86 S/G buffer allocations ALSA: memalloc: Use proper DMA mapping API for x86 WC buffer allocations ALSA: usb-audio: Add logitech Audio profile quirk ASoc: mediatek: mt8365: Remove unneeded assignment ASoC: Intel: ARL: Add entry for HDMI-In capture support to non-I2S codec boards. ASoC: Intel: sof_rt5682: Add HDMI-In capture with rt5682 support for ARL. ASoC: SOF: Intel: hda: remove common_hdmi_codec_drv ASoC: Intel: sof_pcm512x: do not check common_hdmi_codec_drv ASoC: Intel: ehl_rt5660: do not check common_hdmi_codec_drv ASoC: Intel: skl_hda_dsp_generic: use common module for DAI links ...
This commit is contained in:
commit
2f27fce671
@ -37,6 +37,24 @@ properties:
|
|||||||
"#interrupt-cells":
|
"#interrupt-cells":
|
||||||
const: 2
|
const: 2
|
||||||
|
|
||||||
|
mediatek,hp-pull-down:
|
||||||
|
description:
|
||||||
|
Earphone driver positive output stage short to
|
||||||
|
the audio reference ground.
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
mediatek,micbias0-microvolt:
|
||||||
|
description: Selects MIC Bias 0 output voltage.
|
||||||
|
enum: [1700000, 1800000, 1900000, 2000000,
|
||||||
|
2100000, 2500000, 2600000, 2700000]
|
||||||
|
default: 1700000
|
||||||
|
|
||||||
|
mediatek,micbias1-microvolt:
|
||||||
|
description: Selects MIC Bias 1 output voltage.
|
||||||
|
enum: [1700000, 1800000, 1900000, 2000000,
|
||||||
|
2100000, 2500000, 2600000, 2700000]
|
||||||
|
default: 1700000
|
||||||
|
|
||||||
regulators:
|
regulators:
|
||||||
type: object
|
type: object
|
||||||
$ref: /schemas/regulator/mediatek,mt6357-regulator.yaml
|
$ref: /schemas/regulator/mediatek,mt6357-regulator.yaml
|
||||||
@ -83,6 +101,9 @@ examples:
|
|||||||
interrupt-controller;
|
interrupt-controller;
|
||||||
#interrupt-cells = <2>;
|
#interrupt-cells = <2>;
|
||||||
|
|
||||||
|
mediatek,micbias0-microvolt = <1700000>;
|
||||||
|
mediatek,micbias1-microvolt = <1700000>;
|
||||||
|
|
||||||
regulators {
|
regulators {
|
||||||
mt6357_vproc_reg: buck-vproc {
|
mt6357_vproc_reg: buck-vproc {
|
||||||
regulator-name = "vproc";
|
regulator-name = "vproc";
|
||||||
|
@ -26,6 +26,13 @@ properties:
|
|||||||
A list off component DAPM widget. Each entry is a pair of strings,
|
A list off component DAPM widget. Each entry is a pair of strings,
|
||||||
the first being the widget type, the second being the widget name
|
the first being the widget type, the second being the widget name
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 3
|
||||||
|
description:
|
||||||
|
Base PLL clocks of audio susbsytem, used to configure base clock
|
||||||
|
frequencies for different audio use-cases.
|
||||||
|
|
||||||
patternProperties:
|
patternProperties:
|
||||||
"^dai-link-[0-9]+$":
|
"^dai-link-[0-9]+$":
|
||||||
type: object
|
type: object
|
||||||
|
@ -27,6 +27,13 @@ properties:
|
|||||||
A list off component DAPM widget. Each entry is a pair of strings,
|
A list off component DAPM widget. Each entry is a pair of strings,
|
||||||
the first being the widget type, the second being the widget name
|
the first being the widget type, the second being the widget name
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 3
|
||||||
|
description:
|
||||||
|
Base PLL clocks of audio susbsytem, used to configure base clock
|
||||||
|
frequencies for different audio use-cases.
|
||||||
|
|
||||||
patternProperties:
|
patternProperties:
|
||||||
"^dai-link-[0-9]+$":
|
"^dai-link-[0-9]+$":
|
||||||
type: object
|
type: object
|
||||||
|
101
Documentation/devicetree/bindings/sound/cirrus,cs4271.yaml
Normal file
101
Documentation/devicetree/bindings/sound/cirrus,cs4271.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/cirrus,cs4271.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Cirrus Logic CS4271 audio CODEC
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||||
|
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||||
|
|
||||||
|
description:
|
||||||
|
The CS4271 is a stereo audio codec. This device supports both the I2C
|
||||||
|
and the SPI bus.
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: dai-common.yaml#
|
||||||
|
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: cirrus,cs4271
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
spi-cpha: true
|
||||||
|
|
||||||
|
spi-cpol: true
|
||||||
|
|
||||||
|
'#sound-dai-cells':
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
reset-gpios:
|
||||||
|
description:
|
||||||
|
This pin will be deasserted before communication to the codec starts.
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
va-supply:
|
||||||
|
description: Analog power supply.
|
||||||
|
|
||||||
|
vd-supply:
|
||||||
|
description: Digital power supply.
|
||||||
|
|
||||||
|
vl-supply:
|
||||||
|
description: Serial Control Port power supply.
|
||||||
|
|
||||||
|
port:
|
||||||
|
$ref: audio-graph-port.yaml#
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
cirrus,amuteb-eq-bmutec:
|
||||||
|
description:
|
||||||
|
When given, the Codec's AMUTEB=BMUTEC flag is enabled.
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
cirrus,enable-soft-reset:
|
||||||
|
description: |
|
||||||
|
The CS4271 requires its LRCLK and MCLK to be stable before its RESET
|
||||||
|
line is de-asserted. That also means that clocks cannot be changed
|
||||||
|
without putting the chip back into hardware reset, which also requires
|
||||||
|
a complete re-initialization of all registers.
|
||||||
|
|
||||||
|
One (undocumented) workaround is to assert and de-assert the PDN bit
|
||||||
|
in the MODE2 register. This workaround can be enabled with this DT
|
||||||
|
property.
|
||||||
|
|
||||||
|
Note that this is not needed in case the clocks are stable
|
||||||
|
throughout the entire runtime of the codec.
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
spi {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
codec@0 {
|
||||||
|
compatible = "cirrus,cs4271";
|
||||||
|
reg = <0>;
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
spi-max-frequency = <6000000>;
|
||||||
|
spi-cpol;
|
||||||
|
spi-cpha;
|
||||||
|
reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
|
||||||
|
port {
|
||||||
|
endpoint {
|
||||||
|
remote-endpoint = <&i2s_ep>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
@ -1,57 +0,0 @@
|
|||||||
Cirrus Logic CS4271 DT bindings
|
|
||||||
|
|
||||||
This driver supports both the I2C and the SPI bus.
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
|
|
||||||
- compatible: "cirrus,cs4271"
|
|
||||||
|
|
||||||
For required properties on SPI, please consult
|
|
||||||
Documentation/devicetree/bindings/spi/spi-bus.txt
|
|
||||||
|
|
||||||
Required properties on I2C:
|
|
||||||
|
|
||||||
- reg: the i2c address
|
|
||||||
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
|
|
||||||
- reset-gpio: a GPIO spec to define which pin is connected to the chip's
|
|
||||||
!RESET pin
|
|
||||||
- cirrus,amuteb-eq-bmutec: When given, the Codec's AMUTEB=BMUTEC flag
|
|
||||||
is enabled.
|
|
||||||
- cirrus,enable-soft-reset:
|
|
||||||
The CS4271 requires its LRCLK and MCLK to be stable before its RESET
|
|
||||||
line is de-asserted. That also means that clocks cannot be changed
|
|
||||||
without putting the chip back into hardware reset, which also requires
|
|
||||||
a complete re-initialization of all registers.
|
|
||||||
|
|
||||||
One (undocumented) workaround is to assert and de-assert the PDN bit
|
|
||||||
in the MODE2 register. This workaround can be enabled with this DT
|
|
||||||
property.
|
|
||||||
|
|
||||||
Note that this is not needed in case the clocks are stable
|
|
||||||
throughout the entire runtime of the codec.
|
|
||||||
|
|
||||||
- vd-supply: Digital power
|
|
||||||
- vl-supply: Logic power
|
|
||||||
- va-supply: Analog Power
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
codec_i2c: cs4271@10 {
|
|
||||||
compatible = "cirrus,cs4271";
|
|
||||||
reg = <0x10>;
|
|
||||||
reset-gpio = <&gpio 23 0>;
|
|
||||||
vd-supply = <&vdd_3v3_reg>;
|
|
||||||
vl-supply = <&vdd_3v3_reg>;
|
|
||||||
va-supply = <&vdd_3v3_reg>;
|
|
||||||
};
|
|
||||||
|
|
||||||
codec_spi: cs4271@0 {
|
|
||||||
compatible = "cirrus,cs4271";
|
|
||||||
reg = <0x0>;
|
|
||||||
reset-gpio = <&gpio 23 0>;
|
|
||||||
spi-max-frequency = <6000000>;
|
|
||||||
};
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
|||||||
Dialog Semiconductor DA7212/DA7213 Audio Codec bindings
|
|
||||||
|
|
||||||
======
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible : Should be "dlg,da7212" or "dlg,da7213"
|
|
||||||
- reg: Specifies the I2C slave address
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
- clocks : phandle and clock specifier for codec MCLK.
|
|
||||||
- clock-names : Clock name string for 'clocks' attribute, should be "mclk".
|
|
||||||
|
|
||||||
- dlg,micbias1-lvl : Voltage (mV) for Mic Bias 1
|
|
||||||
[<1600>, <2200>, <2500>, <3000>]
|
|
||||||
- dlg,micbias2-lvl : Voltage (mV) for Mic Bias 2
|
|
||||||
[<1600>, <2200>, <2500>, <3000>]
|
|
||||||
- dlg,dmic-data-sel : DMIC channel select based on clock edge.
|
|
||||||
["lrise_rfall", "lfall_rrise"]
|
|
||||||
- dlg,dmic-samplephase : When to sample audio from DMIC.
|
|
||||||
["on_clkedge", "between_clkedge"]
|
|
||||||
- dlg,dmic-clkrate : DMIC clock frequency (Hz).
|
|
||||||
[<1500000>, <3000000>]
|
|
||||||
|
|
||||||
- VDDA-supply : Regulator phandle for Analogue power supply
|
|
||||||
- VDDMIC-supply : Regulator phandle for Mic Bias
|
|
||||||
- VDDIO-supply : Regulator phandle for I/O power supply
|
|
||||||
|
|
||||||
======
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
codec_i2c: da7213@1a {
|
|
||||||
compatible = "dlg,da7213";
|
|
||||||
reg = <0x1a>;
|
|
||||||
|
|
||||||
clocks = <&clks 201>;
|
|
||||||
clock-names = "mclk";
|
|
||||||
|
|
||||||
dlg,micbias1-lvl = <2500>;
|
|
||||||
dlg,micbias2-lvl = <2500>;
|
|
||||||
|
|
||||||
dlg,dmic-data-sel = "lrise_rfall";
|
|
||||||
dlg,dmic-samplephase = "between_clkedge";
|
|
||||||
dlg,dmic-clkrate = <3000000>;
|
|
||||||
};
|
|
103
Documentation/devicetree/bindings/sound/dlg,da7213.yaml
Normal file
103
Documentation/devicetree/bindings/sound/dlg,da7213.yaml
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/sound/dlg,da7213.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Dialog Semiconductor DA7212/DA7213 Audio Codec
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Support Opensource <support.opensource@diasemi.com>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: dai-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- dlg,da7212
|
||||||
|
- dlg,da7213
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
const: mclk
|
||||||
|
|
||||||
|
"#sound-dai-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
dlg,micbias1-lvl:
|
||||||
|
description: Voltage (mV) for Mic Bias 1
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
enum: [ 1600, 2200, 2500, 3000 ]
|
||||||
|
|
||||||
|
dlg,micbias2-lvl:
|
||||||
|
description: Voltage (mV) for Mic Bias 2
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
enum: [ 1600, 2200, 2500, 3000 ]
|
||||||
|
|
||||||
|
dlg,dmic-data-sel:
|
||||||
|
description: DMIC channel select based on clock edge
|
||||||
|
enum: [ lrise_rfall, lfall_rrise ]
|
||||||
|
|
||||||
|
dlg,dmic-samplephase:
|
||||||
|
description: When to sample audio from DMIC
|
||||||
|
enum: [ on_clkedge, between_clkedge ]
|
||||||
|
|
||||||
|
dlg,dmic-clkrate:
|
||||||
|
description: DMIC clock frequency (Hz)
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
enum: [ 1500000, 3000000 ]
|
||||||
|
|
||||||
|
VDDA-supply:
|
||||||
|
description: Analogue power supply
|
||||||
|
|
||||||
|
VDDIO-supply:
|
||||||
|
description: I/O power supply
|
||||||
|
|
||||||
|
VDDMIC-supply:
|
||||||
|
description: Mic Bias
|
||||||
|
|
||||||
|
VDDSP-supply:
|
||||||
|
description: Speaker supply
|
||||||
|
|
||||||
|
ports:
|
||||||
|
$ref: audio-graph-port.yaml#/definitions/ports
|
||||||
|
|
||||||
|
port:
|
||||||
|
$ref: audio-graph-port.yaml#
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
i2c {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
codec@1a {
|
||||||
|
compatible = "dlg,da7213";
|
||||||
|
reg = <0x1a>;
|
||||||
|
|
||||||
|
clocks = <&clks 201>;
|
||||||
|
clock-names = "mclk";
|
||||||
|
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
|
||||||
|
dlg,micbias1-lvl = <2500>;
|
||||||
|
dlg,micbias2-lvl = <2500>;
|
||||||
|
|
||||||
|
dlg,dmic-data-sel = "lrise_rfall";
|
||||||
|
dlg,dmic-samplephase = "between_clkedge";
|
||||||
|
dlg,dmic-clkrate = <3000000>;
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,111 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/sound/fsl,imx-audio-es8328.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Freescale i.MX audio complex with ES8328 codec
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Shawn Guo <shawnguo@kernel.org>
|
||||||
|
- Sascha Hauer <s.hauer@pengutronix.de>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: sound-card-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: fsl,imx-audio-es8328
|
||||||
|
|
||||||
|
model:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/string
|
||||||
|
description: The user-visible name of this sound complex
|
||||||
|
|
||||||
|
ssi-controller:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle
|
||||||
|
description: The phandle of the i.MX SSI controller
|
||||||
|
|
||||||
|
jack-gpio:
|
||||||
|
description: Optional GPIO for headphone jack
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
audio-amp-supply:
|
||||||
|
description: Power regulator for speaker amps
|
||||||
|
|
||||||
|
audio-codec:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle
|
||||||
|
description: The phandle to the ES8328 audio codec
|
||||||
|
|
||||||
|
audio-routing:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||||
|
description: |
|
||||||
|
A list of the connections between audio components. Each entry
|
||||||
|
is a pair of strings, the first being the connection's sink, the second
|
||||||
|
being the connection's source. Valid names could be power supplies,
|
||||||
|
ES8328 pins, and the jacks on the board:
|
||||||
|
|
||||||
|
Power supplies:
|
||||||
|
* audio-amp
|
||||||
|
|
||||||
|
ES8328 pins:
|
||||||
|
* LOUT1
|
||||||
|
* LOUT2
|
||||||
|
* ROUT1
|
||||||
|
* ROUT2
|
||||||
|
* LINPUT1
|
||||||
|
* LINPUT2
|
||||||
|
* RINPUT1
|
||||||
|
* RINPUT2
|
||||||
|
* Mic PGA
|
||||||
|
|
||||||
|
Board connectors:
|
||||||
|
* Headphone
|
||||||
|
* Speaker
|
||||||
|
* Mic Jack
|
||||||
|
|
||||||
|
mux-int-port:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
description: The internal port of the i.MX audio muxer (AUDMUX)
|
||||||
|
enum: [1, 2, 7]
|
||||||
|
default: 1
|
||||||
|
|
||||||
|
mux-ext-port:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
description: The external port of the i.MX audio muxer (AUDMIX)
|
||||||
|
enum: [3, 4, 5, 6]
|
||||||
|
default: 3
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- model
|
||||||
|
- ssi-controller
|
||||||
|
- jack-gpio
|
||||||
|
- audio-amp-supply
|
||||||
|
- audio-codec
|
||||||
|
- audio-routing
|
||||||
|
- mux-int-port
|
||||||
|
- mux-ext-port
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
sound {
|
||||||
|
compatible = "fsl,imx-audio-es8328";
|
||||||
|
model = "imx-audio-es8328";
|
||||||
|
ssi-controller = <&ssi1>;
|
||||||
|
audio-codec = <&codec>;
|
||||||
|
jack-gpio = <&gpio5 15 0>;
|
||||||
|
audio-amp-supply = <®_audio_amp>;
|
||||||
|
audio-routing =
|
||||||
|
"Speaker", "LOUT2",
|
||||||
|
"Speaker", "ROUT2",
|
||||||
|
"Speaker", "audio-amp",
|
||||||
|
"Headphone", "ROUT1",
|
||||||
|
"Headphone", "LOUT1",
|
||||||
|
"LINPUT1", "Mic Jack",
|
||||||
|
"RINPUT1", "Mic Jack",
|
||||||
|
"Mic Jack", "Mic Bias";
|
||||||
|
mux-int-port = <1>;
|
||||||
|
mux-ext-port = <3>;
|
||||||
|
};
|
83
Documentation/devicetree/bindings/sound/fsl,saif.yaml
Normal file
83
Documentation/devicetree/bindings/sound/fsl,saif.yaml
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/sound/fsl,saif.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Freescale MXS Serial Audio Interface (SAIF)
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Lukasz Majewski <lukma@denx.de>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: dai-common.yaml#
|
||||||
|
|
||||||
|
description:
|
||||||
|
The SAIF is based on I2S module that is used to communicate with audio codecs,
|
||||||
|
but only with half-duplex manner (i.e. it can either transmit or receive PCM
|
||||||
|
audio).
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: fsl,imx28-saif
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
"#sound-dai-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
dmas:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
dma-names:
|
||||||
|
const: rx-tx
|
||||||
|
|
||||||
|
"#clock-cells":
|
||||||
|
description: Configure the I2S device as MCLK clock provider.
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
fsl,saif-master:
|
||||||
|
description: Indicate that saif is a slave and its phandle points to master
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- "#sound-dai-cells"
|
||||||
|
- interrupts
|
||||||
|
- dmas
|
||||||
|
- dma-names
|
||||||
|
- clocks
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
saif0: saif@80042000 {
|
||||||
|
compatible = "fsl,imx28-saif";
|
||||||
|
reg = <0x80042000 2000>;
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
interrupts = <59>;
|
||||||
|
dmas = <&dma_apbx 4>;
|
||||||
|
dma-names = "rx-tx";
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clocks = <&clks 53>;
|
||||||
|
};
|
||||||
|
- |
|
||||||
|
saif1: saif@80046000 {
|
||||||
|
compatible = "fsl,imx28-saif";
|
||||||
|
reg = <0x80046000 2000>;
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
interrupts = <58>;
|
||||||
|
dmas = <&dma_apbx 5>;
|
||||||
|
dma-names = "rx-tx";
|
||||||
|
clocks = <&clks 53>;
|
||||||
|
fsl,saif-master = <&saif0>;
|
||||||
|
};
|
@ -1,60 +0,0 @@
|
|||||||
Freescale i.MX audio complex with ES8328 codec
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible : "fsl,imx-audio-es8328"
|
|
||||||
- model : The user-visible name of this sound complex
|
|
||||||
- ssi-controller : The phandle of the i.MX SSI controller
|
|
||||||
- jack-gpio : Optional GPIO for headphone jack
|
|
||||||
- audio-amp-supply : Power regulator for speaker amps
|
|
||||||
- audio-codec : The phandle of the ES8328 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, ES8328
|
|
||||||
pins, and the jacks on the board:
|
|
||||||
|
|
||||||
Power supplies:
|
|
||||||
* audio-amp
|
|
||||||
|
|
||||||
ES8328 pins:
|
|
||||||
* LOUT1
|
|
||||||
* LOUT2
|
|
||||||
* ROUT1
|
|
||||||
* ROUT2
|
|
||||||
* LINPUT1
|
|
||||||
* LINPUT2
|
|
||||||
* RINPUT1
|
|
||||||
* RINPUT2
|
|
||||||
* Mic PGA
|
|
||||||
|
|
||||||
Board connectors:
|
|
||||||
* Headphone
|
|
||||||
* Speaker
|
|
||||||
* Mic Jack
|
|
||||||
- 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 (AUDMIX)
|
|
||||||
|
|
||||||
Note: The AUDMUX port numbering should start at 1, which is consistent with
|
|
||||||
hardware manual.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
sound {
|
|
||||||
compatible = "fsl,imx-audio-es8328";
|
|
||||||
model = "imx-audio-es8328";
|
|
||||||
ssi-controller = <&ssi1>;
|
|
||||||
audio-codec = <&codec>;
|
|
||||||
jack-gpio = <&gpio5 15 0>;
|
|
||||||
audio-amp-supply = <®_audio_amp>;
|
|
||||||
audio-routing =
|
|
||||||
"Speaker", "LOUT2",
|
|
||||||
"Speaker", "ROUT2",
|
|
||||||
"Speaker", "audio-amp",
|
|
||||||
"Headphone", "ROUT1",
|
|
||||||
"Headphone", "LOUT1",
|
|
||||||
"LINPUT1", "Mic Jack",
|
|
||||||
"RINPUT1", "Mic Jack",
|
|
||||||
"Mic Jack", "Mic Bias";
|
|
||||||
mux-int-port = <1>;
|
|
||||||
mux-ext-port = <3>;
|
|
||||||
};
|
|
130
Documentation/devicetree/bindings/sound/mediatek,mt8365-afe.yaml
Normal file
130
Documentation/devicetree/bindings/sound/mediatek,mt8365-afe.yaml
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/sound/mediatek,mt8365-afe.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: MediaTek Audio Front End PCM controller for MT8365
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Alexandre Mergnat <amergnat@baylibre.com>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: mediatek,mt8365-afe-pcm
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
"#sound-dai-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: 26M clock
|
||||||
|
- description: mux for audio clock
|
||||||
|
- description: audio i2s0 mck
|
||||||
|
- description: audio i2s1 mck
|
||||||
|
- description: audio i2s2 mck
|
||||||
|
- description: audio i2s3 mck
|
||||||
|
- description: engen 1 clock
|
||||||
|
- description: engen 2 clock
|
||||||
|
- description: audio 1 clock
|
||||||
|
- description: audio 2 clock
|
||||||
|
- description: mux for i2s0
|
||||||
|
- description: mux for i2s1
|
||||||
|
- description: mux for i2s2
|
||||||
|
- description: mux for i2s3
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: top_clk26m_clk
|
||||||
|
- const: top_audio_sel
|
||||||
|
- const: audio_i2s0_m
|
||||||
|
- const: audio_i2s1_m
|
||||||
|
- const: audio_i2s2_m
|
||||||
|
- const: audio_i2s3_m
|
||||||
|
- const: engen1
|
||||||
|
- const: engen2
|
||||||
|
- const: aud1
|
||||||
|
- const: aud2
|
||||||
|
- const: i2s0_m_sel
|
||||||
|
- const: i2s1_m_sel
|
||||||
|
- const: i2s2_m_sel
|
||||||
|
- const: i2s3_m_sel
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
mediatek,dmic-mode:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
description:
|
||||||
|
Indicates how many data pins are used to transmit two channels of PDM
|
||||||
|
signal. 1 means two wires, 0 means one wire. Default value is 0.
|
||||||
|
enum:
|
||||||
|
- 0 # one wire
|
||||||
|
- 1 # two wires
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- clocks
|
||||||
|
- clock-names
|
||||||
|
- interrupts
|
||||||
|
- power-domains
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/clock/mediatek,mt8365-clk.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
#include <dt-bindings/power/mediatek,mt8365-power.h>
|
||||||
|
|
||||||
|
soc {
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
|
||||||
|
audio-controller@11220000 {
|
||||||
|
compatible = "mediatek,mt8365-afe-pcm";
|
||||||
|
reg = <0 0x11220000 0 0x1000>;
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
clocks = <&clk26m>,
|
||||||
|
<&topckgen CLK_TOP_AUDIO_SEL>,
|
||||||
|
<&topckgen CLK_TOP_AUD_I2S0_M>,
|
||||||
|
<&topckgen CLK_TOP_AUD_I2S1_M>,
|
||||||
|
<&topckgen CLK_TOP_AUD_I2S2_M>,
|
||||||
|
<&topckgen CLK_TOP_AUD_I2S3_M>,
|
||||||
|
<&topckgen CLK_TOP_AUD_ENGEN1_SEL>,
|
||||||
|
<&topckgen CLK_TOP_AUD_ENGEN2_SEL>,
|
||||||
|
<&topckgen CLK_TOP_AUD_1_SEL>,
|
||||||
|
<&topckgen CLK_TOP_AUD_2_SEL>,
|
||||||
|
<&topckgen CLK_TOP_APLL_I2S0_SEL>,
|
||||||
|
<&topckgen CLK_TOP_APLL_I2S1_SEL>,
|
||||||
|
<&topckgen CLK_TOP_APLL_I2S2_SEL>,
|
||||||
|
<&topckgen CLK_TOP_APLL_I2S3_SEL>;
|
||||||
|
clock-names = "top_clk26m_clk",
|
||||||
|
"top_audio_sel",
|
||||||
|
"audio_i2s0_m",
|
||||||
|
"audio_i2s1_m",
|
||||||
|
"audio_i2s2_m",
|
||||||
|
"audio_i2s3_m",
|
||||||
|
"engen1",
|
||||||
|
"engen2",
|
||||||
|
"aud1",
|
||||||
|
"aud2",
|
||||||
|
"i2s0_m_sel",
|
||||||
|
"i2s1_m_sel",
|
||||||
|
"i2s2_m_sel",
|
||||||
|
"i2s3_m_sel";
|
||||||
|
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_LOW>;
|
||||||
|
power-domains = <&spm MT8365_POWER_DOMAIN_AUDIO>;
|
||||||
|
mediatek,dmic-mode = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
@ -0,0 +1,107 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/sound/mediatek,mt8365-mt6357.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: MediaTek MT8365 ASoC sound card
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Alexandre Mergnat <amergnat@baylibre.com>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: mediatek,mt8365-mt6357
|
||||||
|
|
||||||
|
pinctrl-names:
|
||||||
|
minItems: 1
|
||||||
|
items:
|
||||||
|
- const: default
|
||||||
|
- const: dmic
|
||||||
|
- const: miso_off
|
||||||
|
- const: miso_on
|
||||||
|
- const: mosi_off
|
||||||
|
- const: mosi_on
|
||||||
|
|
||||||
|
mediatek,platform:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle
|
||||||
|
description: The phandle of MT8365 ASoC platform.
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
"^dai-link-[0-9]+$":
|
||||||
|
type: object
|
||||||
|
description:
|
||||||
|
Container for dai-link level properties and CODEC sub-nodes.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
codec:
|
||||||
|
type: object
|
||||||
|
description: Holds subnode which indicates codec dai.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
sound-dai:
|
||||||
|
maxItems: 1
|
||||||
|
description: phandle of the codec DAI
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
link-name:
|
||||||
|
description: Indicates dai-link name and PCM stream name
|
||||||
|
enum:
|
||||||
|
- I2S_IN_BE
|
||||||
|
- I2S_OUT_BE
|
||||||
|
- PCM1_BE
|
||||||
|
- PDM1_BE
|
||||||
|
- PDM2_BE
|
||||||
|
- PDM3_BE
|
||||||
|
- PDM4_BE
|
||||||
|
- SPDIF_IN_BE
|
||||||
|
- SPDIF_OUT_BE
|
||||||
|
- TDM_IN_BE
|
||||||
|
- TDM_OUT_BE
|
||||||
|
|
||||||
|
sound-dai:
|
||||||
|
maxItems: 1
|
||||||
|
description: phandle of the CPU DAI
|
||||||
|
|
||||||
|
required:
|
||||||
|
- link-name
|
||||||
|
- sound-dai
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- pinctrl-names
|
||||||
|
- mediatek,platform
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
sound {
|
||||||
|
compatible = "mediatek,mt8365-mt6357";
|
||||||
|
pinctrl-names = "default",
|
||||||
|
"dmic",
|
||||||
|
"miso_off",
|
||||||
|
"miso_on",
|
||||||
|
"mosi_off",
|
||||||
|
"mosi_on";
|
||||||
|
pinctrl-0 = <&aud_default_pins>;
|
||||||
|
pinctrl-1 = <&aud_dmic_pins>;
|
||||||
|
pinctrl-2 = <&aud_miso_off_pins>;
|
||||||
|
pinctrl-3 = <&aud_miso_on_pins>;
|
||||||
|
pinctrl-4 = <&aud_mosi_off_pins>;
|
||||||
|
pinctrl-5 = <&aud_mosi_on_pins>;
|
||||||
|
mediatek,platform = <&afe>;
|
||||||
|
|
||||||
|
/* hdmi interface */
|
||||||
|
dai-link-0 {
|
||||||
|
link-name = "I2S_OUT_BE";
|
||||||
|
sound-dai = <&afe>;
|
||||||
|
|
||||||
|
codec {
|
||||||
|
sound-dai = <&it66121hdmitx>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@ -13,6 +13,9 @@ description:
|
|||||||
The Microchip Sony/Philips Digital Interface Receiver is a serial port
|
The Microchip Sony/Philips Digital Interface Receiver is a serial port
|
||||||
compliant with the IEC-60958 standard.
|
compliant with the IEC-60958 standard.
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: dai-common.yaml#
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
"#sound-dai-cells":
|
"#sound-dai-cells":
|
||||||
const: 0
|
const: 0
|
||||||
@ -53,7 +56,7 @@ required:
|
|||||||
- dmas
|
- dmas
|
||||||
- dma-names
|
- dma-names
|
||||||
|
|
||||||
additionalProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
* Freescale MXS Serial Audio Interface (SAIF)
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible: Should be "fsl,<chip>-saif"
|
|
||||||
- reg: Should contain registers location and length
|
|
||||||
- interrupts: Should contain ERROR interrupt number
|
|
||||||
- dmas: DMA specifier, consisting of a phandle to DMA controller node
|
|
||||||
and SAIF DMA channel ID.
|
|
||||||
Refer to dma.txt and fsl-mxs-dma.txt for details.
|
|
||||||
- dma-names: Must be "rx-tx".
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
- fsl,saif-master: phandle to the master SAIF. It's only required for
|
|
||||||
the slave SAIF.
|
|
||||||
|
|
||||||
Note: Each SAIF controller should have an alias correctly numbered
|
|
||||||
in "aliases" node.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
aliases {
|
|
||||||
saif0 = &saif0;
|
|
||||||
saif1 = &saif1;
|
|
||||||
};
|
|
||||||
|
|
||||||
saif0: saif@80042000 {
|
|
||||||
compatible = "fsl,imx28-saif";
|
|
||||||
reg = <0x80042000 2000>;
|
|
||||||
interrupts = <59>;
|
|
||||||
dmas = <&dma_apbx 4>;
|
|
||||||
dma-names = "rx-tx";
|
|
||||||
};
|
|
||||||
|
|
||||||
saif1: saif@80046000 {
|
|
||||||
compatible = "fsl,imx28-saif";
|
|
||||||
reg = <0x80046000 2000>;
|
|
||||||
interrupts = <58>;
|
|
||||||
dmas = <&dma_apbx 5>;
|
|
||||||
dma-names = "rx-tx";
|
|
||||||
fsl,saif-master = <&saif0>;
|
|
||||||
};
|
|
@ -1,53 +0,0 @@
|
|||||||
PCM512x and TAS575x audio CODECs/amplifiers
|
|
||||||
|
|
||||||
These devices support both I2C and SPI (configured with pin strapping
|
|
||||||
on the board). The TAS575x devices only support I2C.
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
|
|
||||||
- compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141",
|
|
||||||
"ti,pcm5142", "ti,pcm5242", "ti,tas5754" or "ti,tas5756"
|
|
||||||
|
|
||||||
- reg : the I2C address of the device for I2C, the chip select
|
|
||||||
number for SPI.
|
|
||||||
|
|
||||||
- AVDD-supply, DVDD-supply, and CPVDD-supply : power supplies for the
|
|
||||||
device, as covered in bindings/regulator/regulator.txt
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
|
|
||||||
- clocks : A clock specifier for the clock connected as SCLK. If this
|
|
||||||
is absent the device will be configured to clock from BCLK. If pll-in
|
|
||||||
and pll-out are specified in addition to a clock, the device is
|
|
||||||
configured to accept clock input on a specified gpio pin.
|
|
||||||
|
|
||||||
- pll-in, pll-out : gpio pins used to connect the pll using <1>
|
|
||||||
through <6>. The device will be configured for clock input on the
|
|
||||||
given pll-in pin and PLL output on the given pll-out pin. An
|
|
||||||
external connection from the pll-out pin to the SCLK pin is assumed.
|
|
||||||
Caution: the TAS-desvices only support gpios 1,2 and 3
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
pcm5122: pcm5122@4c {
|
|
||||||
compatible = "ti,pcm5122";
|
|
||||||
reg = <0x4c>;
|
|
||||||
|
|
||||||
AVDD-supply = <®_3v3_analog>;
|
|
||||||
DVDD-supply = <®_1v8>;
|
|
||||||
CPVDD-supply = <®_3v3>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
pcm5142: pcm5142@4c {
|
|
||||||
compatible = "ti,pcm5142";
|
|
||||||
reg = <0x4c>;
|
|
||||||
|
|
||||||
AVDD-supply = <®_3v3_analog>;
|
|
||||||
DVDD-supply = <®_1v8>;
|
|
||||||
CPVDD-supply = <®_3v3>;
|
|
||||||
|
|
||||||
clocks = <&sck>;
|
|
||||||
pll-in = <3>;
|
|
||||||
pll-out = <6>;
|
|
||||||
};
|
|
@ -0,0 +1,205 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/sound/qcom,apq8016-sbc-sndcard.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Qualcomm APQ8016 and similar sound cards
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||||
|
- Stephan Gerhold <stephan@gerhold.net>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- qcom,apq8016-sbc-sndcard
|
||||||
|
- qcom,msm8916-qdsp6-sndcard
|
||||||
|
|
||||||
|
reg:
|
||||||
|
items:
|
||||||
|
- description: Microphone I/O mux register address
|
||||||
|
- description: Speaker I/O mux register address
|
||||||
|
|
||||||
|
reg-names:
|
||||||
|
items:
|
||||||
|
- const: mic-iomux
|
||||||
|
- const: spkr-iomux
|
||||||
|
|
||||||
|
audio-routing:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||||
|
description:
|
||||||
|
A list of the connections between audio components. Each entry is a
|
||||||
|
pair of strings, the first being the connection's sink, the second
|
||||||
|
being the connection's source. Valid names could be power supplies,
|
||||||
|
MicBias of codec and the jacks on the board.
|
||||||
|
|
||||||
|
aux-devs:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||||
|
description: |
|
||||||
|
List of phandles pointing to auxiliary devices, such
|
||||||
|
as amplifiers, to be added to the sound card.
|
||||||
|
|
||||||
|
model:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/string
|
||||||
|
description: User visible long sound card name
|
||||||
|
|
||||||
|
pin-switches:
|
||||||
|
description: List of widget names for which pin switches should be created.
|
||||||
|
$ref: /schemas/types.yaml#/definitions/string-array
|
||||||
|
|
||||||
|
widgets:
|
||||||
|
description: User specified audio sound widgets.
|
||||||
|
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
".*-dai-link$":
|
||||||
|
description:
|
||||||
|
Each subnode represents a dai link. Subnodes of each dai links would be
|
||||||
|
cpu/codec dais.
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
properties:
|
||||||
|
link-name:
|
||||||
|
description: Indicates dai-link name and PCM stream name.
|
||||||
|
$ref: /schemas/types.yaml#/definitions/string
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
cpu:
|
||||||
|
description: Holds subnode which indicates cpu dai.
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
properties:
|
||||||
|
sound-dai:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
platform:
|
||||||
|
description: Holds subnode which indicates platform dai.
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
properties:
|
||||||
|
sound-dai:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
codec:
|
||||||
|
description: Holds subnode which indicates codec dai.
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
properties:
|
||||||
|
sound-dai:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 8
|
||||||
|
|
||||||
|
required:
|
||||||
|
- link-name
|
||||||
|
- cpu
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- reg-names
|
||||||
|
- model
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/sound/qcom,lpass.h>
|
||||||
|
sound@7702000 {
|
||||||
|
compatible = "qcom,apq8016-sbc-sndcard";
|
||||||
|
reg = <0x07702000 0x4>, <0x07702004 0x4>;
|
||||||
|
reg-names = "mic-iomux", "spkr-iomux";
|
||||||
|
|
||||||
|
model = "DB410c";
|
||||||
|
audio-routing =
|
||||||
|
"AMIC2", "MIC BIAS Internal2",
|
||||||
|
"AMIC3", "MIC BIAS External1";
|
||||||
|
|
||||||
|
pinctrl-0 = <&cdc_pdm_lines_act &ext_sec_tlmm_lines_act &ext_mclk_tlmm_lines_act>;
|
||||||
|
pinctrl-1 = <&cdc_pdm_lines_sus &ext_sec_tlmm_lines_sus &ext_mclk_tlmm_lines_sus>;
|
||||||
|
pinctrl-names = "default", "sleep";
|
||||||
|
|
||||||
|
quaternary-dai-link {
|
||||||
|
link-name = "ADV7533";
|
||||||
|
cpu {
|
||||||
|
sound-dai = <&lpass MI2S_QUATERNARY>;
|
||||||
|
};
|
||||||
|
codec {
|
||||||
|
sound-dai = <&adv_bridge 0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
primary-dai-link {
|
||||||
|
link-name = "WCD";
|
||||||
|
cpu {
|
||||||
|
sound-dai = <&lpass MI2S_PRIMARY>;
|
||||||
|
};
|
||||||
|
codec {
|
||||||
|
sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
tertiary-dai-link {
|
||||||
|
link-name = "WCD-Capture";
|
||||||
|
cpu {
|
||||||
|
sound-dai = <&lpass MI2S_TERTIARY>;
|
||||||
|
};
|
||||||
|
codec {
|
||||||
|
sound-dai = <&lpass_codec 1>, <&wcd_codec 1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/sound/qcom,q6afe.h>
|
||||||
|
#include <dt-bindings/sound/qcom,q6asm.h>
|
||||||
|
sound@7702000 {
|
||||||
|
compatible = "qcom,msm8916-qdsp6-sndcard";
|
||||||
|
reg = <0x07702000 0x4>, <0x07702004 0x4>;
|
||||||
|
reg-names = "mic-iomux", "spkr-iomux";
|
||||||
|
|
||||||
|
model = "msm8916";
|
||||||
|
widgets =
|
||||||
|
"Speaker", "Speaker",
|
||||||
|
"Headphone", "Headphones";
|
||||||
|
pin-switches = "Speaker";
|
||||||
|
audio-routing =
|
||||||
|
"Speaker", "Speaker Amp OUT",
|
||||||
|
"Speaker Amp IN", "HPH_R",
|
||||||
|
"Headphones", "HPH_L",
|
||||||
|
"Headphones", "HPH_R",
|
||||||
|
"AMIC1", "MIC BIAS Internal1",
|
||||||
|
"AMIC2", "MIC BIAS Internal2",
|
||||||
|
"AMIC3", "MIC BIAS Internal3";
|
||||||
|
aux-devs = <&speaker_amp>;
|
||||||
|
|
||||||
|
pinctrl-names = "default", "sleep";
|
||||||
|
pinctrl-0 = <&cdc_pdm_lines_act>;
|
||||||
|
pinctrl-1 = <&cdc_pdm_lines_sus>;
|
||||||
|
|
||||||
|
mm1-dai-link {
|
||||||
|
link-name = "MultiMedia1";
|
||||||
|
cpu {
|
||||||
|
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
primary-dai-link {
|
||||||
|
link-name = "Primary MI2S";
|
||||||
|
cpu {
|
||||||
|
sound-dai = <&q6afedai PRIMARY_MI2S_RX>;
|
||||||
|
};
|
||||||
|
platform {
|
||||||
|
sound-dai = <&q6routing>;
|
||||||
|
};
|
||||||
|
codec {
|
||||||
|
sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@ -64,6 +64,7 @@ allOf:
|
|||||||
compatible:
|
compatible:
|
||||||
enum:
|
enum:
|
||||||
- qcom,sc7280-lpass-wsa-macro
|
- qcom,sc7280-lpass-wsa-macro
|
||||||
|
- qcom,sm8250-lpass-wsa-macro
|
||||||
- qcom,sm8450-lpass-wsa-macro
|
- qcom,sm8450-lpass-wsa-macro
|
||||||
- qcom,sc8280xp-lpass-wsa-macro
|
- qcom,sc8280xp-lpass-wsa-macro
|
||||||
then:
|
then:
|
||||||
@ -79,24 +80,6 @@ allOf:
|
|||||||
- const: dcodec
|
- const: dcodec
|
||||||
- const: fsgen
|
- const: fsgen
|
||||||
|
|
||||||
- if:
|
|
||||||
properties:
|
|
||||||
compatible:
|
|
||||||
enum:
|
|
||||||
- qcom,sm8250-lpass-wsa-macro
|
|
||||||
then:
|
|
||||||
properties:
|
|
||||||
clocks:
|
|
||||||
minItems: 6
|
|
||||||
clock-names:
|
|
||||||
items:
|
|
||||||
- const: mclk
|
|
||||||
- const: npl
|
|
||||||
- const: macro
|
|
||||||
- const: dcodec
|
|
||||||
- const: va
|
|
||||||
- const: fsgen
|
|
||||||
|
|
||||||
- if:
|
- if:
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
@ -130,8 +113,7 @@ examples:
|
|||||||
<&audiocc 0>,
|
<&audiocc 0>,
|
||||||
<&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
<&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
||||||
<&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
<&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
||||||
<&aoncc LPASS_CDC_VA_MCLK>,
|
|
||||||
<&vamacro>;
|
<&vamacro>;
|
||||||
clock-names = "mclk", "npl", "macro", "dcodec", "va", "fsgen";
|
clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
|
||||||
clock-output-names = "mclk";
|
clock-output-names = "mclk";
|
||||||
};
|
};
|
||||||
|
@ -27,9 +27,7 @@ properties:
|
|||||||
- qcom,sm8650-sndcard
|
- qcom,sm8650-sndcard
|
||||||
- const: qcom,sm8450-sndcard
|
- const: qcom,sm8450-sndcard
|
||||||
- enum:
|
- enum:
|
||||||
- qcom,apq8016-sbc-sndcard
|
|
||||||
- qcom,apq8096-sndcard
|
- qcom,apq8096-sndcard
|
||||||
- qcom,msm8916-qdsp6-sndcard
|
|
||||||
- qcom,qcm6490-idp-sndcard
|
- qcom,qcm6490-idp-sndcard
|
||||||
- qcom,qcs6490-rb3gen2-sndcard
|
- qcom,qcs6490-rb3gen2-sndcard
|
||||||
- qcom,qrb5165-rb5-sndcard
|
- qcom,qrb5165-rb5-sndcard
|
||||||
@ -58,18 +56,6 @@ properties:
|
|||||||
$ref: /schemas/types.yaml#/definitions/string
|
$ref: /schemas/types.yaml#/definitions/string
|
||||||
description: User visible long sound card name
|
description: User visible long sound card name
|
||||||
|
|
||||||
pin-switches:
|
|
||||||
description: List of widget names for which pin switches should be created.
|
|
||||||
$ref: /schemas/types.yaml#/definitions/string-array
|
|
||||||
|
|
||||||
widgets:
|
|
||||||
description: User specified audio sound widgets.
|
|
||||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
|
||||||
|
|
||||||
# Only valid for some compatibles (see allOf if below)
|
|
||||||
reg: true
|
|
||||||
reg-names: true
|
|
||||||
|
|
||||||
patternProperties:
|
patternProperties:
|
||||||
".*-dai-link$":
|
".*-dai-link$":
|
||||||
description:
|
description:
|
||||||
@ -122,34 +108,6 @@ required:
|
|||||||
- compatible
|
- compatible
|
||||||
- model
|
- model
|
||||||
|
|
||||||
allOf:
|
|
||||||
- if:
|
|
||||||
properties:
|
|
||||||
compatible:
|
|
||||||
contains:
|
|
||||||
enum:
|
|
||||||
- qcom,apq8016-sbc-sndcard
|
|
||||||
- qcom,msm8916-qdsp6-sndcard
|
|
||||||
then:
|
|
||||||
properties:
|
|
||||||
reg:
|
|
||||||
items:
|
|
||||||
- description: Microphone I/O mux register address
|
|
||||||
- description: Speaker I/O mux register address
|
|
||||||
reg-names:
|
|
||||||
items:
|
|
||||||
- const: mic-iomux
|
|
||||||
- const: spkr-iomux
|
|
||||||
required:
|
|
||||||
- compatible
|
|
||||||
- model
|
|
||||||
- reg
|
|
||||||
- reg-names
|
|
||||||
else:
|
|
||||||
properties:
|
|
||||||
reg: false
|
|
||||||
reg-names: false
|
|
||||||
|
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
@ -231,98 +189,3 @@ examples:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
- |
|
|
||||||
#include <dt-bindings/sound/qcom,lpass.h>
|
|
||||||
sound@7702000 {
|
|
||||||
compatible = "qcom,apq8016-sbc-sndcard";
|
|
||||||
reg = <0x07702000 0x4>, <0x07702004 0x4>;
|
|
||||||
reg-names = "mic-iomux", "spkr-iomux";
|
|
||||||
|
|
||||||
model = "DB410c";
|
|
||||||
audio-routing =
|
|
||||||
"AMIC2", "MIC BIAS Internal2",
|
|
||||||
"AMIC3", "MIC BIAS External1";
|
|
||||||
|
|
||||||
pinctrl-0 = <&cdc_pdm_lines_act &ext_sec_tlmm_lines_act &ext_mclk_tlmm_lines_act>;
|
|
||||||
pinctrl-1 = <&cdc_pdm_lines_sus &ext_sec_tlmm_lines_sus &ext_mclk_tlmm_lines_sus>;
|
|
||||||
pinctrl-names = "default", "sleep";
|
|
||||||
|
|
||||||
quaternary-dai-link {
|
|
||||||
link-name = "ADV7533";
|
|
||||||
cpu {
|
|
||||||
sound-dai = <&lpass MI2S_QUATERNARY>;
|
|
||||||
};
|
|
||||||
codec {
|
|
||||||
sound-dai = <&adv_bridge 0>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
primary-dai-link {
|
|
||||||
link-name = "WCD";
|
|
||||||
cpu {
|
|
||||||
sound-dai = <&lpass MI2S_PRIMARY>;
|
|
||||||
};
|
|
||||||
codec {
|
|
||||||
sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
tertiary-dai-link {
|
|
||||||
link-name = "WCD-Capture";
|
|
||||||
cpu {
|
|
||||||
sound-dai = <&lpass MI2S_TERTIARY>;
|
|
||||||
};
|
|
||||||
codec {
|
|
||||||
sound-dai = <&lpass_codec 1>, <&wcd_codec 1>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
- |
|
|
||||||
#include <dt-bindings/sound/qcom,q6afe.h>
|
|
||||||
#include <dt-bindings/sound/qcom,q6asm.h>
|
|
||||||
sound@7702000 {
|
|
||||||
compatible = "qcom,msm8916-qdsp6-sndcard";
|
|
||||||
reg = <0x07702000 0x4>, <0x07702004 0x4>;
|
|
||||||
reg-names = "mic-iomux", "spkr-iomux";
|
|
||||||
|
|
||||||
model = "msm8916";
|
|
||||||
widgets =
|
|
||||||
"Speaker", "Speaker",
|
|
||||||
"Headphone", "Headphones";
|
|
||||||
pin-switches = "Speaker";
|
|
||||||
audio-routing =
|
|
||||||
"Speaker", "Speaker Amp OUT",
|
|
||||||
"Speaker Amp IN", "HPH_R",
|
|
||||||
"Headphones", "HPH_L",
|
|
||||||
"Headphones", "HPH_R",
|
|
||||||
"AMIC1", "MIC BIAS Internal1",
|
|
||||||
"AMIC2", "MIC BIAS Internal2",
|
|
||||||
"AMIC3", "MIC BIAS Internal3";
|
|
||||||
aux-devs = <&speaker_amp>;
|
|
||||||
|
|
||||||
pinctrl-names = "default", "sleep";
|
|
||||||
pinctrl-0 = <&cdc_pdm_lines_act>;
|
|
||||||
pinctrl-1 = <&cdc_pdm_lines_sus>;
|
|
||||||
|
|
||||||
mm1-dai-link {
|
|
||||||
link-name = "MultiMedia1";
|
|
||||||
cpu {
|
|
||||||
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
primary-dai-link {
|
|
||||||
link-name = "Primary MI2S";
|
|
||||||
cpu {
|
|
||||||
sound-dai = <&q6afedai PRIMARY_MI2S_RX>;
|
|
||||||
};
|
|
||||||
platform {
|
|
||||||
sound-dai = <&q6routing>;
|
|
||||||
};
|
|
||||||
codec {
|
|
||||||
sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
@ -30,6 +30,18 @@ properties:
|
|||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: Master clock to the CODEC
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: mclk
|
||||||
|
|
||||||
|
port:
|
||||||
|
$ref: audio-graph-port.yaml#
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
@ -112,6 +112,12 @@ properties:
|
|||||||
description: List of necessary clock names.
|
description: List of necessary clock names.
|
||||||
# details are defined below
|
# details are defined below
|
||||||
|
|
||||||
|
post-init-providers:
|
||||||
|
description: At least if rsnd is using DPCM connection on Audio-Graph-Card2,
|
||||||
|
fw_devlink might doesn't have enough information to break the cycle. rsnd
|
||||||
|
driver will not be probed in such case. Same problem might occur with
|
||||||
|
Multi-CPU/Codec or Codec2Codec.
|
||||||
|
|
||||||
# ports is below
|
# ports is below
|
||||||
port:
|
port:
|
||||||
$ref: audio-graph-port.yaml#/definitions/port-base
|
$ref: audio-graph-port.yaml#/definitions/port-base
|
||||||
|
@ -87,6 +87,10 @@ properties:
|
|||||||
'#sound-dai-cells':
|
'#sound-dai-cells':
|
||||||
const: 0
|
const: 0
|
||||||
|
|
||||||
|
port:
|
||||||
|
$ref: audio-graph-port.yaml#/definitions/port-base
|
||||||
|
description: Connection to controller providing I2S signals
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
@ -27,11 +27,6 @@ properties:
|
|||||||
- const: samsung,odroid-xu4-audio
|
- const: samsung,odroid-xu4-audio
|
||||||
deprecated: true
|
deprecated: true
|
||||||
|
|
||||||
assigned-clock-parents: true
|
|
||||||
assigned-clock-rates: true
|
|
||||||
assigned-clocks: true
|
|
||||||
clocks: true
|
|
||||||
|
|
||||||
cpu:
|
cpu:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
101
Documentation/devicetree/bindings/sound/ti,pcm512x.yaml
Normal file
101
Documentation/devicetree/bindings/sound/ti,pcm512x.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/ti,pcm512x.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: PCM512x and TAS575x audio CODECs/amplifiers
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Animesh Agarwal <animeshagarwal28@gmail.com>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: dai-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- ti,pcm5121
|
||||||
|
- ti,pcm5122
|
||||||
|
- ti,pcm5141
|
||||||
|
- ti,pcm5142
|
||||||
|
- ti,pcm5242
|
||||||
|
- ti,tas5754
|
||||||
|
- ti,tas5756
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
AVDD-supply: true
|
||||||
|
|
||||||
|
DVDD-supply: true
|
||||||
|
|
||||||
|
CPVDD-supply: true
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
maxItems: 1
|
||||||
|
description: A clock specifier for the clock connected as SCLK. If this is
|
||||||
|
absent the device will be configured to clock from BCLK. If pll-in and
|
||||||
|
pll-out are specified in addition to a clock, the device is configured to
|
||||||
|
accept clock input on a specified gpio pin.
|
||||||
|
|
||||||
|
'#sound-dai-cells':
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
pll-in:
|
||||||
|
description: GPIO pin used to connect the pll using <1> through <6>. The
|
||||||
|
device will be configured for clock input on the given pll-in pin.
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
minimum: 1
|
||||||
|
maximum: 6
|
||||||
|
|
||||||
|
pll-out:
|
||||||
|
description: GPIO pin used to connect the pll using <1> through <6>. The
|
||||||
|
device will be configured for PLL output on the given pll-out pin. An
|
||||||
|
external connection from the pll-out pin to the SCLK pin is assumed.
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
minimum: 1
|
||||||
|
maximum: 6
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- AVDD-supply
|
||||||
|
- DVDD-supply
|
||||||
|
- CPVDD-supply
|
||||||
|
|
||||||
|
if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- ti,tas5754
|
||||||
|
- ti,tas5756
|
||||||
|
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
pll-in:
|
||||||
|
maximum: 3
|
||||||
|
|
||||||
|
pll-out:
|
||||||
|
maximum: 3
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
i2c {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
codec@4c {
|
||||||
|
compatible = "ti,pcm5142";
|
||||||
|
reg = <0x4c>;
|
||||||
|
AVDD-supply = <®_3v3_analog>;
|
||||||
|
DVDD-supply = <®_1v8>;
|
||||||
|
CPVDD-supply = <®_3v3>;
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
clocks = <&sck>;
|
||||||
|
pll-in = <3>;
|
||||||
|
pll-out = <6>;
|
||||||
|
};
|
||||||
|
};
|
127
Documentation/devicetree/bindings/sound/ti,tlv320dac3100.yaml
Normal file
127
Documentation/devicetree/bindings/sound/ti,tlv320dac3100.yaml
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/sound/ti,tlv320dac3100.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Texas Instruments - tlv320aic31xx Codec module
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Shenghao Ding <shenghao-ding@ti.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
CODEC output pins:
|
||||||
|
* HPL
|
||||||
|
* HPR
|
||||||
|
* SPL, devices with stereo speaker amp
|
||||||
|
* SPR, devices with stereo speaker amp
|
||||||
|
* SPK, devices with mono speaker amp
|
||||||
|
* MICBIAS
|
||||||
|
|
||||||
|
CODEC input pins:
|
||||||
|
* MIC1LP, devices with ADC
|
||||||
|
* MIC1RP, devices with ADC
|
||||||
|
* MIC1LM, devices with ADC
|
||||||
|
* AIN1, devices without ADC
|
||||||
|
* AIN2, devices without ADC
|
||||||
|
|
||||||
|
The pins can be used in referring sound node's audio-routing property.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- ti,tlv320aic310x # - Generic TLV320AIC31xx with mono speaker amp
|
||||||
|
- ti,tlv320aic311x # - Generic TLV320AIC31xx with stereo speaker amp
|
||||||
|
- ti,tlv320aic3100 # - TLV320AIC3100 (mono speaker amp, no MiniDSP)
|
||||||
|
- ti,tlv320aic3110 # - TLV320AIC3110 (stereo speaker amp, no MiniDSP)
|
||||||
|
- ti,tlv320aic3120 # - TLV320AIC3120 (mono speaker amp, MiniDSP)
|
||||||
|
- ti,tlv320aic3111 # - TLV320AIC3111 (stereo speaker amp, MiniDSP)
|
||||||
|
- ti,tlv320dac3100 # - TLV320DAC3100 (no ADC, mono speaker amp, no MiniDSP)
|
||||||
|
- ti,tlv320dac3101 # - TLV320DAC3101 (no ADC, stereo speaker amp, no MiniDSP)
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
'#sound-dai-cells':
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
HPVDD-supply: true
|
||||||
|
|
||||||
|
SPRVDD-supply: true
|
||||||
|
|
||||||
|
SPLVDD-supply: true
|
||||||
|
|
||||||
|
AVDD-supply: true
|
||||||
|
|
||||||
|
IOVDD-supply: true
|
||||||
|
|
||||||
|
DVDD-supply: true
|
||||||
|
|
||||||
|
reset-gpios:
|
||||||
|
description: GPIO specification for the active low RESET input.
|
||||||
|
|
||||||
|
ai31xx-micbias-vg:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
default: 1
|
||||||
|
enum: [1, 2, 3]
|
||||||
|
description: |
|
||||||
|
MicBias Voltage setting
|
||||||
|
1 or MICBIAS_2_0V - MICBIAS output is powered to 2.0V
|
||||||
|
2 or MICBIAS_2_5V - MICBIAS output is powered to 2.5V
|
||||||
|
3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD
|
||||||
|
|
||||||
|
ai31xx-ocmv:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
enum: [0, 1, 2, 3]
|
||||||
|
description: |
|
||||||
|
output common-mode voltage setting
|
||||||
|
0 - 1.35V,
|
||||||
|
1 - 1.5V,
|
||||||
|
2 - 1.65V,
|
||||||
|
3 - 1.8V
|
||||||
|
|
||||||
|
gpio-reset:
|
||||||
|
description: gpio pin number used for codec reset
|
||||||
|
deprecated: true
|
||||||
|
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- HPVDD-supply
|
||||||
|
- SPRVDD-supply
|
||||||
|
- SPLVDD-supply
|
||||||
|
- AVDD-supply
|
||||||
|
- IOVDD-supply
|
||||||
|
- DVDD-supply
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: dai-common.yaml#
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include <dt-bindings/sound/tlv320aic31xx.h>
|
||||||
|
|
||||||
|
i2c {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
sound@18 {
|
||||||
|
compatible = "ti,tlv320aic311x";
|
||||||
|
reg = <0x18>;
|
||||||
|
|
||||||
|
ai31xx-micbias-vg = <MICBIAS_2_0V>;
|
||||||
|
reset-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
|
||||||
|
|
||||||
|
HPVDD-supply = <®ulator>;
|
||||||
|
SPRVDD-supply = <®ulator>;
|
||||||
|
SPLVDD-supply = <®ulator>;
|
||||||
|
AVDD-supply = <®ulator>;
|
||||||
|
IOVDD-supply = <®ulator>;
|
||||||
|
DVDD-supply = <®ulator>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
55
Documentation/devicetree/bindings/sound/ti,tpa6130a2.yaml
Normal file
55
Documentation/devicetree/bindings/sound/ti,tpa6130a2.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,tpa6130a2.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Texas Instruments - tpa6130a2 Codec module
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Sebastian Reichel <sre@kernel.org>
|
||||||
|
|
||||||
|
description:
|
||||||
|
Stereo, analog input headphone amplifier
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- ti,tpa6130a2
|
||||||
|
- ti,tpa6140a2
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
Vdd-supply:
|
||||||
|
description: power supply regulator
|
||||||
|
|
||||||
|
power-gpio:
|
||||||
|
description: gpio pin to power the device
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- Vdd-supply
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: dai-common.yaml#
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
i2c {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
amplifier@60 {
|
||||||
|
compatible = "ti,tpa6130a2";
|
||||||
|
reg = <0x60>;
|
||||||
|
Vdd-supply = <&vmmc2>;
|
||||||
|
power-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -1,77 +0,0 @@
|
|||||||
Texas Instruments - tlv320aic31xx Codec module
|
|
||||||
|
|
||||||
The tlv320aic31xx serial control bus communicates through I2C protocols
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
|
|
||||||
- compatible - "string" - One of:
|
|
||||||
"ti,tlv320aic310x" - Generic TLV320AIC31xx with mono speaker amp
|
|
||||||
"ti,tlv320aic311x" - Generic TLV320AIC31xx with stereo speaker amp
|
|
||||||
"ti,tlv320aic3100" - TLV320AIC3100 (mono speaker amp, no MiniDSP)
|
|
||||||
"ti,tlv320aic3110" - TLV320AIC3110 (stereo speaker amp, no MiniDSP)
|
|
||||||
"ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP)
|
|
||||||
"ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP)
|
|
||||||
"ti,tlv320dac3100" - TLV320DAC3100 (no ADC, mono speaker amp, no MiniDSP)
|
|
||||||
"ti,tlv320dac3101" - TLV320DAC3101 (no ADC, stereo speaker amp, no MiniDSP)
|
|
||||||
|
|
||||||
- reg - <int> - I2C slave address
|
|
||||||
- HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply,
|
|
||||||
DVDD-supply : power supplies for the device as covered in
|
|
||||||
Documentation/devicetree/bindings/regulator/regulator.txt
|
|
||||||
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
|
|
||||||
- reset-gpios - GPIO specification for the active low RESET input.
|
|
||||||
- ai31xx-micbias-vg - MicBias Voltage setting
|
|
||||||
1 or MICBIAS_2_0V - MICBIAS output is powered to 2.0V
|
|
||||||
2 or MICBIAS_2_5V - MICBIAS output is powered to 2.5V
|
|
||||||
3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD
|
|
||||||
If this node is not mentioned or if the value is unknown, then
|
|
||||||
micbias is set to 2.0V.
|
|
||||||
- ai31xx-ocmv - output common-mode voltage setting
|
|
||||||
0 - 1.35V,
|
|
||||||
1 - 1.5V,
|
|
||||||
2 - 1.65V,
|
|
||||||
3 - 1.8V
|
|
||||||
|
|
||||||
Deprecated properties:
|
|
||||||
|
|
||||||
- gpio-reset - gpio pin number used for codec reset
|
|
||||||
|
|
||||||
CODEC output pins:
|
|
||||||
* HPL
|
|
||||||
* HPR
|
|
||||||
* SPL, devices with stereo speaker amp
|
|
||||||
* SPR, devices with stereo speaker amp
|
|
||||||
* SPK, devices with mono speaker amp
|
|
||||||
* MICBIAS
|
|
||||||
|
|
||||||
CODEC input pins:
|
|
||||||
* MIC1LP, devices with ADC
|
|
||||||
* MIC1RP, devices with ADC
|
|
||||||
* MIC1LM, devices with ADC
|
|
||||||
* AIN1, devices without ADC
|
|
||||||
* AIN2, devices without ADC
|
|
||||||
|
|
||||||
The pins can be used in referring sound node's audio-routing property.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
|
||||||
#include <dt-bindings/sound/tlv320aic31xx.h>
|
|
||||||
|
|
||||||
tlv320aic31xx: tlv320aic31xx@18 {
|
|
||||||
compatible = "ti,tlv320aic311x";
|
|
||||||
reg = <0x18>;
|
|
||||||
|
|
||||||
ai31xx-micbias-vg = <MICBIAS_OFF>;
|
|
||||||
|
|
||||||
reset-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
|
|
||||||
|
|
||||||
HPVDD-supply = <®ulator>;
|
|
||||||
SPRVDD-supply = <®ulator>;
|
|
||||||
SPLVDD-supply = <®ulator>;
|
|
||||||
AVDD-supply = <®ulator>;
|
|
||||||
IOVDD-supply = <®ulator>;
|
|
||||||
DVDD-supply = <®ulator>;
|
|
||||||
};
|
|
@ -1,27 +0,0 @@
|
|||||||
Texas Instruments - tpa6130a2 Codec module
|
|
||||||
|
|
||||||
The tpa6130a2 serial control bus communicates through I2C protocols
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
|
|
||||||
- compatible - "string" - One of:
|
|
||||||
"ti,tpa6130a2" - TPA6130A2
|
|
||||||
"ti,tpa6140a2" - TPA6140A2
|
|
||||||
|
|
||||||
|
|
||||||
- reg - <int> - I2C slave address
|
|
||||||
|
|
||||||
- Vdd-supply - <phandle> - power supply regulator
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
|
|
||||||
- power-gpio - gpio pin to power the device
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
tpa6130a2: tpa6130a2@60 {
|
|
||||||
compatible = "ti,tpa6130a2";
|
|
||||||
reg = <0x60>;
|
|
||||||
Vdd-supply = <&vmmc2>;
|
|
||||||
power-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
|
|
||||||
};
|
|
@ -1059,6 +1059,9 @@ power_save
|
|||||||
Automatic power-saving timeout (in second, 0 = disable)
|
Automatic power-saving timeout (in second, 0 = disable)
|
||||||
power_save_controller
|
power_save_controller
|
||||||
Reset HD-audio controller in power-saving mode (default = on)
|
Reset HD-audio controller in power-saving mode (default = on)
|
||||||
|
pm_blacklist
|
||||||
|
Enable / disable power-management deny-list (default = look up PM
|
||||||
|
deny-list, 0 = skip PM deny-list, 1 = force to turn off runtime PM)
|
||||||
align_buffer_size
|
align_buffer_size
|
||||||
Force rounding of buffer/period sizes to multiples of 128 bytes.
|
Force rounding of buffer/period sizes to multiples of 128 bytes.
|
||||||
This is more efficient in terms of memory access but isn't
|
This is more efficient in terms of memory access but isn't
|
||||||
|
@ -321,12 +321,6 @@ Kernel Configuration
|
|||||||
--------------------
|
--------------------
|
||||||
In general, I recommend you to enable the sound debug option,
|
In general, I recommend you to enable the sound debug option,
|
||||||
``CONFIG_SND_DEBUG=y``, no matter whether you are debugging or not.
|
``CONFIG_SND_DEBUG=y``, no matter whether you are debugging or not.
|
||||||
This enables snd_printd() macro and others, and you'll get additional
|
|
||||||
kernel messages at probing.
|
|
||||||
|
|
||||||
In addition, you can enable ``CONFIG_SND_DEBUG_VERBOSE=y``. But this
|
|
||||||
will give you far more messages. Thus turn this on only when you are
|
|
||||||
sure to want it.
|
|
||||||
|
|
||||||
Don't forget to turn on the appropriate ``CONFIG_SND_HDA_CODEC_*``
|
Don't forget to turn on the appropriate ``CONFIG_SND_HDA_CODEC_*``
|
||||||
options. Note that each of them corresponds to the codec chip, not
|
options. Note that each of them corresponds to the codec chip, not
|
||||||
|
@ -13,6 +13,7 @@ Sound Subsystem Documentation
|
|||||||
alsa-configuration
|
alsa-configuration
|
||||||
hd-audio/index
|
hd-audio/index
|
||||||
cards/index
|
cards/index
|
||||||
|
utimers
|
||||||
|
|
||||||
.. only:: subproject and html
|
.. only:: subproject and html
|
||||||
|
|
||||||
|
@ -4030,31 +4030,6 @@ located in the new subdirectory, sound/pci/xyz.
|
|||||||
Useful Functions
|
Useful Functions
|
||||||
================
|
================
|
||||||
|
|
||||||
:c:func:`snd_printk()` and friends
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
.. note:: This subsection describes a few helper functions for
|
|
||||||
decorating a bit more on the standard :c:func:`printk()` & co.
|
|
||||||
However, in general, the use of such helpers is no longer recommended.
|
|
||||||
If possible, try to stick with the standard functions like
|
|
||||||
:c:func:`dev_err()` or :c:func:`pr_err()`.
|
|
||||||
|
|
||||||
ALSA provides a verbose version of the :c:func:`printk()` function.
|
|
||||||
If a kernel config ``CONFIG_SND_VERBOSE_PRINTK`` is set, this function
|
|
||||||
prints the given message together with the file name and the line of the
|
|
||||||
caller. The ``KERN_XXX`` prefix is processed as well as the original
|
|
||||||
:c:func:`printk()` does, so it's recommended to add this prefix,
|
|
||||||
e.g. snd_printk(KERN_ERR "Oh my, sorry, it's extremely bad!\\n");
|
|
||||||
|
|
||||||
There are also :c:func:`printk()`'s for debugging.
|
|
||||||
:c:func:`snd_printd()` can be used for general debugging purposes.
|
|
||||||
If ``CONFIG_SND_DEBUG`` is set, this function is compiled, and works
|
|
||||||
just like :c:func:`snd_printk()`. If the ALSA is compiled without
|
|
||||||
the debugging flag, it's ignored.
|
|
||||||
|
|
||||||
:c:func:`snd_printdd()` is compiled in only when
|
|
||||||
``CONFIG_SND_DEBUG_VERBOSE`` is set.
|
|
||||||
|
|
||||||
:c:func:`snd_BUG()`
|
:c:func:`snd_BUG()`
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
126
Documentation/sound/utimers.rst
Normal file
126
Documentation/sound/utimers.rst
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
.. SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
=======================
|
||||||
|
Userspace-driven timers
|
||||||
|
=======================
|
||||||
|
|
||||||
|
:Author: Ivan Orlov <ivan.orlov0322@gmail.com>
|
||||||
|
|
||||||
|
Preface
|
||||||
|
=======
|
||||||
|
|
||||||
|
This document describes the userspace-driven timers: virtual ALSA timers
|
||||||
|
which could be created and controlled by userspace applications using
|
||||||
|
IOCTL calls. Such timers could be useful when synchronizing audio
|
||||||
|
stream with timer sources which we don't have ALSA timers exported for
|
||||||
|
(e.g. PTP clocks), and when synchronizing the audio stream going through
|
||||||
|
two virtual sound devices using ``snd-aloop`` (for instance, when
|
||||||
|
we have a network application sending frames to one snd-aloop device,
|
||||||
|
and another sound application listening on the other end of snd-aloop).
|
||||||
|
|
||||||
|
Enabling userspace-driven timers
|
||||||
|
================================
|
||||||
|
|
||||||
|
The userspace-driven timers could be enabled in the kernel using the
|
||||||
|
``CONFIG_SND_UTIMER`` configuration option. It depends on the
|
||||||
|
``CONFIG_SND_TIMER`` option, so it also should be enabled.
|
||||||
|
|
||||||
|
Userspace-driven timers API
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Userspace application can create a userspace-driven ALSA timer by
|
||||||
|
executing the ``SNDRV_TIMER_IOCTL_CREATE`` ioctl call on the
|
||||||
|
``/dev/snd/timer`` device file descriptor. The ``snd_timer_uinfo``
|
||||||
|
structure should be passed as an ioctl argument:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct snd_timer_uinfo {
|
||||||
|
__u64 resolution;
|
||||||
|
int fd;
|
||||||
|
unsigned int id;
|
||||||
|
unsigned char reserved[16];
|
||||||
|
}
|
||||||
|
|
||||||
|
The ``resolution`` field sets the desired resolution in nanoseconds for
|
||||||
|
the virtual timer. ``resolution`` field simply provides an information
|
||||||
|
about the virtual timer, but does not affect the timing itself. ``id``
|
||||||
|
field gets overwritten by the ioctl, and the identifier you get in this
|
||||||
|
field after the call can be used as a timer subdevice number when
|
||||||
|
passing the timer to ``snd-aloop`` kernel module or other userspace
|
||||||
|
applications. There could be up to 128 userspace-driven timers in the
|
||||||
|
system at one moment of time, thus the id value ranges from 0 to 127.
|
||||||
|
|
||||||
|
Besides from overwriting the ``snd_timer_uinfo`` struct, ioctl stores
|
||||||
|
a timer file descriptor, which can be used to trigger the timer, in the
|
||||||
|
``fd`` field of the ``snd_timer_uinfo`` struct. Allocation of a file
|
||||||
|
descriptor for the timer guarantees that the timer can only be triggered
|
||||||
|
by the process which created it. The timer then can be triggered with
|
||||||
|
``SNDRV_TIMER_IOCTL_TRIGGER`` ioctl call on the timer file descriptor.
|
||||||
|
|
||||||
|
So, the example code for creating and triggering the timer would be:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
static struct snd_timer_uinfo utimer_info = {
|
||||||
|
/* Timer is going to tick (presumably) every 1000000 ns */
|
||||||
|
.resolution = 1000000ULL,
|
||||||
|
.id = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
int timer_device_fd = open("/dev/snd/timer", O_RDWR | O_CLOEXEC);
|
||||||
|
|
||||||
|
if (ioctl(timer_device_fd, SNDRV_TIMER_IOCTL_CREATE, &utimer_info)) {
|
||||||
|
perror("Failed to create the timer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we want to trigger the timer. Callbacks of all of the
|
||||||
|
* timer instances binded to this timer will be executed after
|
||||||
|
* this call.
|
||||||
|
*/
|
||||||
|
ioctl(utimer_info.fd, SNDRV_TIMER_IOCTL_TRIGGER, NULL);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
/* Now, destroy the timer */
|
||||||
|
close(timer_info.fd);
|
||||||
|
|
||||||
|
|
||||||
|
More detailed example of creating and ticking the timer could be found
|
||||||
|
in the utimer ALSA selftest.
|
||||||
|
|
||||||
|
Userspace-driven timers and snd-aloop
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Userspace-driven timers could be easily used with ``snd-aloop`` module
|
||||||
|
when synchronizing two sound applications on both ends of the virtual
|
||||||
|
sound loopback. For instance, if one of the applications receives sound
|
||||||
|
frames from network and sends them to snd-aloop pcm device, and another
|
||||||
|
application listens for frames on the other snd-aloop pcm device, it
|
||||||
|
makes sense that the ALSA middle layer should initiate a data
|
||||||
|
transaction when the new period of data is received through network, but
|
||||||
|
not when the certain amount of jiffies elapses. Userspace-driven ALSA
|
||||||
|
timers could be used to achieve this.
|
||||||
|
|
||||||
|
To use userspace-driven ALSA timer as a timer source of snd-aloop, pass
|
||||||
|
the following string as the snd-aloop ``timer_source`` parameter:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# modprobe snd-aloop timer_source="-1.4.<utimer_id>"
|
||||||
|
|
||||||
|
Where ``utimer_id`` is the id of the timer you created with
|
||||||
|
``SNDRV_TIMER_IOCTL_CREATE``, and ``4`` is the number of
|
||||||
|
userspace-driven timers device (``SNDRV_TIMER_GLOBAL_UDRIVEN``).
|
||||||
|
|
||||||
|
``resolution`` for the userspace-driven ALSA timer used with snd-aloop
|
||||||
|
should be calculated as ``1000000000ULL / frame_rate * period_size`` as
|
||||||
|
the timer is going to tick every time a new period of frames is ready.
|
||||||
|
|
||||||
|
After that, each time you trigger the timer with
|
||||||
|
``SNDRV_TIMER_IOCTL_TRIGGER`` the new period of data will be transferred
|
||||||
|
from one snd-aloop device to another.
|
@ -6542,6 +6542,7 @@ F: Documentation/devicetree/bindings/regulator/da92*.txt
|
|||||||
F: Documentation/devicetree/bindings/regulator/dlg,da9*.yaml
|
F: Documentation/devicetree/bindings/regulator/dlg,da9*.yaml
|
||||||
F: Documentation/devicetree/bindings/regulator/dlg,slg51000.yaml
|
F: Documentation/devicetree/bindings/regulator/dlg,slg51000.yaml
|
||||||
F: Documentation/devicetree/bindings/sound/da[79]*.txt
|
F: Documentation/devicetree/bindings/sound/da[79]*.txt
|
||||||
|
F: Documentation/devicetree/bindings/sound/dlg,da7213.yaml
|
||||||
F: Documentation/devicetree/bindings/thermal/dlg,da9062-thermal.yaml
|
F: Documentation/devicetree/bindings/thermal/dlg,da9062-thermal.yaml
|
||||||
F: Documentation/devicetree/bindings/watchdog/dlg,da9062-watchdog.yaml
|
F: Documentation/devicetree/bindings/watchdog/dlg,da9062-watchdog.yaml
|
||||||
F: Documentation/hwmon/da90??.rst
|
F: Documentation/hwmon/da90??.rst
|
||||||
@ -22725,12 +22726,11 @@ F: Documentation/devicetree/bindings/sound/tas2552.txt
|
|||||||
F: Documentation/devicetree/bindings/sound/ti,tas2562.yaml
|
F: Documentation/devicetree/bindings/sound/ti,tas2562.yaml
|
||||||
F: Documentation/devicetree/bindings/sound/ti,tas2770.yaml
|
F: Documentation/devicetree/bindings/sound/ti,tas2770.yaml
|
||||||
F: Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
|
F: Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
|
||||||
|
F: Documentation/devicetree/bindings/sound/ti,tpa6130a2.yaml
|
||||||
F: Documentation/devicetree/bindings/sound/ti,pcm1681.yaml
|
F: Documentation/devicetree/bindings/sound/ti,pcm1681.yaml
|
||||||
F: Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml
|
F: Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml
|
||||||
F: Documentation/devicetree/bindings/sound/ti,tlv320*.yaml
|
F: Documentation/devicetree/bindings/sound/ti,tlv320*.yaml
|
||||||
F: Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml
|
F: Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml
|
||||||
F: Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
|
|
||||||
F: Documentation/devicetree/bindings/sound/tpa6130a2.txt
|
|
||||||
F: include/sound/tas2*.h
|
F: include/sound/tas2*.h
|
||||||
F: include/sound/tlv320*.h
|
F: include/sound/tlv320*.h
|
||||||
F: include/sound/tpa6130a2-plat.h
|
F: include/sound/tpa6130a2-plat.h
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
#include <drm/bridge/dw_hdmi.h>
|
#include <drm/bridge/dw_hdmi.h>
|
||||||
#include <drm/drm_edid.h>
|
#include <drm/drm_edid.h>
|
||||||
|
|
||||||
@ -388,15 +389,36 @@ static int dw_hdmi_close(struct snd_pcm_substream *substream)
|
|||||||
|
|
||||||
static int dw_hdmi_hw_free(struct snd_pcm_substream *substream)
|
static int dw_hdmi_hw_free(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
return snd_pcm_lib_free_vmalloc_buffer(substream);
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
|
||||||
|
vfree(runtime->dma_area);
|
||||||
|
runtime->dma_area = NULL;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dw_hdmi_hw_params(struct snd_pcm_substream *substream,
|
static int dw_hdmi_hw_params(struct snd_pcm_substream *substream,
|
||||||
struct snd_pcm_hw_params *params)
|
struct snd_pcm_hw_params *params)
|
||||||
{
|
{
|
||||||
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
size_t size = params_buffer_bytes(params);
|
||||||
|
|
||||||
/* Allocate the PCM runtime buffer, which is exposed to userspace. */
|
/* Allocate the PCM runtime buffer, which is exposed to userspace. */
|
||||||
return snd_pcm_lib_alloc_vmalloc_buffer(substream,
|
if (runtime->dma_area) {
|
||||||
params_buffer_bytes(params));
|
if (runtime->dma_bytes >= size)
|
||||||
|
return 0; /* already large enough */
|
||||||
|
vfree(runtime->dma_area);
|
||||||
|
}
|
||||||
|
runtime->dma_area = vzalloc(size);
|
||||||
|
if (!runtime->dma_area)
|
||||||
|
return -ENOMEM;
|
||||||
|
runtime->dma_bytes = size;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct page *dw_hdmi_get_page(struct snd_pcm_substream *substream,
|
||||||
|
unsigned long offset)
|
||||||
|
{
|
||||||
|
return vmalloc_to_page(substream->runtime->dma_area + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dw_hdmi_prepare(struct snd_pcm_substream *substream)
|
static int dw_hdmi_prepare(struct snd_pcm_substream *substream)
|
||||||
@ -515,7 +537,7 @@ static const struct snd_pcm_ops snd_dw_hdmi_ops = {
|
|||||||
.prepare = dw_hdmi_prepare,
|
.prepare = dw_hdmi_prepare,
|
||||||
.trigger = dw_hdmi_trigger,
|
.trigger = dw_hdmi_trigger,
|
||||||
.pointer = dw_hdmi_pointer,
|
.pointer = dw_hdmi_pointer,
|
||||||
.page = snd_pcm_lib_get_vmalloc_page,
|
.page = dw_hdmi_get_page,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int snd_dw_hdmi_probe(struct platform_device *pdev)
|
static int snd_dw_hdmi_probe(struct platform_device *pdev)
|
||||||
|
@ -222,6 +222,13 @@ static inline bool sdw_intel_sync_check_cmdsync_unlocked(struct sdw_intel *sdw)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int sdw_intel_get_link_count(struct sdw_intel *sdw)
|
||||||
|
{
|
||||||
|
if (SDW_INTEL_CHECK_OPS(sdw, get_link_count))
|
||||||
|
return SDW_INTEL_OPS(sdw, get_link_count)(sdw);
|
||||||
|
return 4; /* default on older generations */
|
||||||
|
}
|
||||||
|
|
||||||
/* common bus management */
|
/* common bus management */
|
||||||
int intel_start_bus(struct sdw_intel *sdw);
|
int intel_start_bus(struct sdw_intel *sdw);
|
||||||
int intel_start_bus_after_reset(struct sdw_intel *sdw);
|
int intel_start_bus_after_reset(struct sdw_intel *sdw);
|
||||||
|
@ -706,10 +706,30 @@ static void intel_program_sdi(struct sdw_intel *sdw, int dev_num)
|
|||||||
__func__, sdw->instance, dev_num);
|
__func__, sdw->instance, dev_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int intel_get_link_count(struct sdw_intel *sdw)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = hdac_bus_eml_get_count(sdw->link_res->hbus, true, AZX_REG_ML_LEPTR_ID_SDW);
|
||||||
|
if (!ret) {
|
||||||
|
dev_err(sdw->cdns.dev, "%s: could not retrieve link count\n", __func__);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret > SDW_INTEL_MAX_LINKS) {
|
||||||
|
dev_err(sdw->cdns.dev, "%s: link count %d exceed max %d\n", __func__, ret, SDW_INTEL_MAX_LINKS);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
const struct sdw_intel_hw_ops sdw_intel_lnl_hw_ops = {
|
const struct sdw_intel_hw_ops sdw_intel_lnl_hw_ops = {
|
||||||
.debugfs_init = intel_ace2x_debugfs_init,
|
.debugfs_init = intel_ace2x_debugfs_init,
|
||||||
.debugfs_exit = intel_ace2x_debugfs_exit,
|
.debugfs_exit = intel_ace2x_debugfs_exit,
|
||||||
|
|
||||||
|
.get_link_count = intel_get_link_count,
|
||||||
|
|
||||||
.register_dai = intel_register_dai,
|
.register_dai = intel_register_dai,
|
||||||
|
|
||||||
.check_clock_stop = intel_check_clock_stop,
|
.check_clock_stop = intel_check_clock_stop,
|
||||||
|
@ -317,6 +317,20 @@ static int intel_link_probe(struct auxiliary_device *auxdev,
|
|||||||
bus->link_id = auxdev->id;
|
bus->link_id = auxdev->id;
|
||||||
bus->clk_stop_timeout = 1;
|
bus->clk_stop_timeout = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* paranoia check: make sure ACPI-reported number of links is aligned with
|
||||||
|
* hardware capabilities.
|
||||||
|
*/
|
||||||
|
ret = sdw_intel_get_link_count(sdw);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "%s: sdw_intel_get_link_count failed: %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (ret <= sdw->instance) {
|
||||||
|
dev_err(dev, "%s: invalid link id %d, link count %d\n", __func__, auxdev->id, ret);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
sdw_cdns_probe(cdns);
|
sdw_cdns_probe(cdns);
|
||||||
|
|
||||||
/* Set ops */
|
/* Set ops */
|
||||||
|
@ -388,6 +388,7 @@ struct sdw_intel;
|
|||||||
/* struct intel_sdw_hw_ops - SoundWire ops for Intel platforms.
|
/* struct intel_sdw_hw_ops - SoundWire ops for Intel platforms.
|
||||||
* @debugfs_init: initialize all debugfs capabilities
|
* @debugfs_init: initialize all debugfs capabilities
|
||||||
* @debugfs_exit: close and cleanup debugfs capabilities
|
* @debugfs_exit: close and cleanup debugfs capabilities
|
||||||
|
* @get_link_count: fetch link count from hardware registers
|
||||||
* @register_dai: read all PDI information and register DAIs
|
* @register_dai: read all PDI information and register DAIs
|
||||||
* @check_clock_stop: throw error message if clock is not stopped.
|
* @check_clock_stop: throw error message if clock is not stopped.
|
||||||
* @start_bus: normal start
|
* @start_bus: normal start
|
||||||
@ -412,6 +413,8 @@ struct sdw_intel_hw_ops {
|
|||||||
void (*debugfs_init)(struct sdw_intel *sdw);
|
void (*debugfs_init)(struct sdw_intel *sdw);
|
||||||
void (*debugfs_exit)(struct sdw_intel *sdw);
|
void (*debugfs_exit)(struct sdw_intel *sdw);
|
||||||
|
|
||||||
|
int (*get_link_count)(struct sdw_intel *sdw);
|
||||||
|
|
||||||
int (*register_dai)(struct sdw_intel *sdw);
|
int (*register_dai)(struct sdw_intel *sdw);
|
||||||
|
|
||||||
void (*check_clock_stop)(struct sdw_intel *sdw);
|
void (*check_clock_stop)(struct sdw_intel *sdw);
|
||||||
@ -447,4 +450,9 @@ extern const struct sdw_intel_hw_ops sdw_intel_lnl_hw_ops;
|
|||||||
|
|
||||||
#define SDW_INTEL_DEV_NUM_IDA_MIN 6
|
#define SDW_INTEL_DEV_NUM_IDA_MIN 6
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Max number of links supported in hardware
|
||||||
|
*/
|
||||||
|
#define SDW_INTEL_MAX_LINKS 5
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
#define ACI_SET_EQ7 0x46 /* ... to Treble */
|
#define ACI_SET_EQ7 0x46 /* ... to Treble */
|
||||||
|
|
||||||
struct snd_miro_aci {
|
struct snd_miro_aci {
|
||||||
|
struct snd_card *card;
|
||||||
unsigned long aci_port;
|
unsigned long aci_port;
|
||||||
int aci_vendor;
|
int aci_vendor;
|
||||||
int aci_product;
|
int aci_product;
|
||||||
|
@ -110,18 +110,22 @@
|
|||||||
#define IEC958_AES2_CON_SOURCE_UNSPEC (0<<0) /* unspecified */
|
#define IEC958_AES2_CON_SOURCE_UNSPEC (0<<0) /* unspecified */
|
||||||
#define IEC958_AES2_CON_CHANNEL (15<<4) /* mask - channel number */
|
#define IEC958_AES2_CON_CHANNEL (15<<4) /* mask - channel number */
|
||||||
#define IEC958_AES2_CON_CHANNEL_UNSPEC (0<<4) /* unspecified */
|
#define IEC958_AES2_CON_CHANNEL_UNSPEC (0<<4) /* unspecified */
|
||||||
#define IEC958_AES3_CON_FS (15<<0) /* mask - sample frequency */
|
#define IEC958_AES3_CON_FS ((1<<7) | (15<<0)) /* mask - sample frequency */
|
||||||
#define IEC958_AES3_CON_FS_44100 (0<<0) /* 44.1kHz */
|
#define IEC958_AES3_CON_FS_44100 (0<<0) /* 44.1kHz */
|
||||||
#define IEC958_AES3_CON_FS_NOTID (1<<0) /* non indicated */
|
#define IEC958_AES3_CON_FS_NOTID (1<<0) /* non indicated */
|
||||||
#define IEC958_AES3_CON_FS_48000 (2<<0) /* 48kHz */
|
#define IEC958_AES3_CON_FS_48000 (2<<0) /* 48kHz */
|
||||||
#define IEC958_AES3_CON_FS_32000 (3<<0) /* 32kHz */
|
#define IEC958_AES3_CON_FS_32000 (3<<0) /* 32kHz */
|
||||||
#define IEC958_AES3_CON_FS_22050 (4<<0) /* 22.05kHz */
|
#define IEC958_AES3_CON_FS_22050 (4<<0) /* 22.05kHz */
|
||||||
|
#define IEC958_AES3_CON_FS_384000 (5<<0) /* 384kHz */
|
||||||
#define IEC958_AES3_CON_FS_24000 (6<<0) /* 24kHz */
|
#define IEC958_AES3_CON_FS_24000 (6<<0) /* 24kHz */
|
||||||
#define IEC958_AES3_CON_FS_88200 (8<<0) /* 88.2kHz */
|
#define IEC958_AES3_CON_FS_88200 (8<<0) /* 88.2kHz */
|
||||||
#define IEC958_AES3_CON_FS_768000 (9<<0) /* 768kHz */
|
#define IEC958_AES3_CON_FS_768000 (9<<0) /* 768kHz */
|
||||||
#define IEC958_AES3_CON_FS_96000 (10<<0) /* 96kHz */
|
#define IEC958_AES3_CON_FS_96000 (10<<0) /* 96kHz */
|
||||||
#define IEC958_AES3_CON_FS_176400 (12<<0) /* 176.4kHz */
|
#define IEC958_AES3_CON_FS_176400 (12<<0) /* 176.4kHz */
|
||||||
|
#define IEC958_AES3_CON_FS_352400 (13<<0) /* 352.4kHz */
|
||||||
#define IEC958_AES3_CON_FS_192000 (14<<0) /* 192kHz */
|
#define IEC958_AES3_CON_FS_192000 (14<<0) /* 192kHz */
|
||||||
|
#define IEC958_AES3_CON_FS_128000 ((1<<7) | (11<<0)) /* 128kHz */
|
||||||
|
#define IEC958_AES3_CON_FS_705600 ((1<<7) | (13<<0)) /* 705.6kHz */
|
||||||
#define IEC958_AES3_CON_CLOCK (3<<4) /* mask - clock accuracy */
|
#define IEC958_AES3_CON_CLOCK (3<<4) /* mask - clock accuracy */
|
||||||
#define IEC958_AES3_CON_CLOCK_1000PPM (0<<4) /* 1000 ppm */
|
#define IEC958_AES3_CON_CLOCK_1000PPM (0<<4) /* 1000 ppm */
|
||||||
#define IEC958_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */
|
#define IEC958_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */
|
||||||
|
@ -81,7 +81,7 @@ struct snd_kcontrol {
|
|||||||
unsigned long private_value;
|
unsigned long private_value;
|
||||||
void *private_data;
|
void *private_data;
|
||||||
void (*private_free)(struct snd_kcontrol *kcontrol);
|
void (*private_free)(struct snd_kcontrol *kcontrol);
|
||||||
struct snd_kcontrol_volatile vd[]; /* volatile data */
|
struct snd_kcontrol_volatile vd[] __counted_by(count); /* volatile data */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list)
|
#define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list)
|
||||||
@ -140,9 +140,7 @@ int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
|
|||||||
int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
|
int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
|
||||||
void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl, const char *name);
|
void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl, const char *name);
|
||||||
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active);
|
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active);
|
||||||
struct snd_kcontrol *snd_ctl_find_numid_locked(struct snd_card *card, unsigned int numid);
|
|
||||||
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid);
|
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid);
|
||||||
struct snd_kcontrol *snd_ctl_find_id_locked(struct snd_card *card, const struct snd_ctl_elem_id *id);
|
|
||||||
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, const struct snd_ctl_elem_id *id);
|
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, const struct snd_ctl_elem_id *id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,29 +165,6 @@ snd_ctl_find_id_mixer(struct snd_card *card, const char *name)
|
|||||||
return snd_ctl_find_id(card, &id);
|
return snd_ctl_find_id(card, &id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* snd_ctl_find_id_mixer_locked - find the control instance with the given name string
|
|
||||||
* @card: the card instance
|
|
||||||
* @name: the name string
|
|
||||||
*
|
|
||||||
* Finds the control instance with the given name and
|
|
||||||
* @SNDRV_CTL_ELEM_IFACE_MIXER. Other fields are set to zero.
|
|
||||||
*
|
|
||||||
* This is merely a wrapper to snd_ctl_find_id_locked().
|
|
||||||
* The caller must down card->controls_rwsem before calling this function.
|
|
||||||
*
|
|
||||||
* Return: The pointer of the instance if found, or %NULL if not.
|
|
||||||
*/
|
|
||||||
static inline struct snd_kcontrol *
|
|
||||||
snd_ctl_find_id_mixer_locked(struct snd_card *card, const char *name)
|
|
||||||
{
|
|
||||||
struct snd_ctl_elem_id id = {};
|
|
||||||
|
|
||||||
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
|
||||||
strscpy(id.name, name, sizeof(id.name));
|
|
||||||
return snd_ctl_find_id_locked(card, &id);
|
|
||||||
}
|
|
||||||
|
|
||||||
int snd_ctl_create(struct snd_card *card);
|
int snd_ctl_create(struct snd_card *card);
|
||||||
|
|
||||||
int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
|
int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
|
||||||
|
@ -99,7 +99,7 @@ struct snd_card {
|
|||||||
struct device *ctl_dev; /* control device */
|
struct device *ctl_dev; /* control device */
|
||||||
unsigned int last_numid; /* last used numeric ID */
|
unsigned int last_numid; /* last used numeric ID */
|
||||||
struct rw_semaphore controls_rwsem; /* controls lock (list and values) */
|
struct rw_semaphore controls_rwsem; /* controls lock (list and values) */
|
||||||
rwlock_t ctl_files_rwlock; /* ctl_files list lock */
|
rwlock_t controls_rwlock; /* lock for lookup and ctl_files list */
|
||||||
int controls_count; /* count of all controls */
|
int controls_count; /* count of all controls */
|
||||||
size_t user_ctl_alloc_size; // current memory allocation by user controls.
|
size_t user_ctl_alloc_size; // current memory allocation by user controls.
|
||||||
struct list_head controls; /* all controls for this card */
|
struct list_head controls; /* all controls for this card */
|
||||||
@ -345,45 +345,7 @@ void release_and_free_resource(struct resource *res);
|
|||||||
|
|
||||||
/* --- */
|
/* --- */
|
||||||
|
|
||||||
/* sound printk debug levels */
|
|
||||||
enum {
|
|
||||||
SND_PR_ALWAYS,
|
|
||||||
SND_PR_DEBUG,
|
|
||||||
SND_PR_VERBOSE,
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK)
|
|
||||||
__printf(4, 5)
|
|
||||||
void __snd_printk(unsigned int level, const char *file, int line,
|
|
||||||
const char *format, ...);
|
|
||||||
#else
|
|
||||||
#define __snd_printk(level, file, line, format, ...) \
|
|
||||||
printk(format, ##__VA_ARGS__)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* snd_printk - printk wrapper
|
|
||||||
* @fmt: format string
|
|
||||||
*
|
|
||||||
* Works like printk() but prints the file and the line of the caller
|
|
||||||
* when configured with CONFIG_SND_VERBOSE_PRINTK.
|
|
||||||
*/
|
|
||||||
#define snd_printk(fmt, ...) \
|
|
||||||
__snd_printk(0, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#ifdef CONFIG_SND_DEBUG
|
#ifdef CONFIG_SND_DEBUG
|
||||||
/**
|
|
||||||
* snd_printd - debug printk
|
|
||||||
* @fmt: format string
|
|
||||||
*
|
|
||||||
* Works like snd_printk() for debugging purposes.
|
|
||||||
* Ignored when CONFIG_SND_DEBUG is not set.
|
|
||||||
*/
|
|
||||||
#define snd_printd(fmt, ...) \
|
|
||||||
__snd_printk(1, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
|
||||||
#define _snd_printd(level, fmt, ...) \
|
|
||||||
__snd_printk(level, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_BUG - give a BUG warning message and stack trace
|
* snd_BUG - give a BUG warning message and stack trace
|
||||||
*
|
*
|
||||||
@ -392,12 +354,6 @@ void __snd_printk(unsigned int level, const char *file, int line,
|
|||||||
*/
|
*/
|
||||||
#define snd_BUG() WARN(1, "BUG?\n")
|
#define snd_BUG() WARN(1, "BUG?\n")
|
||||||
|
|
||||||
/**
|
|
||||||
* snd_printd_ratelimit - Suppress high rates of output when
|
|
||||||
* CONFIG_SND_DEBUG is enabled.
|
|
||||||
*/
|
|
||||||
#define snd_printd_ratelimit() printk_ratelimit()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_BUG_ON - debugging check macro
|
* snd_BUG_ON - debugging check macro
|
||||||
* @cond: condition to evaluate
|
* @cond: condition to evaluate
|
||||||
@ -409,11 +365,6 @@ void __snd_printk(unsigned int level, const char *file, int line,
|
|||||||
|
|
||||||
#else /* !CONFIG_SND_DEBUG */
|
#else /* !CONFIG_SND_DEBUG */
|
||||||
|
|
||||||
__printf(1, 2)
|
|
||||||
static inline void snd_printd(const char *format, ...) {}
|
|
||||||
__printf(2, 3)
|
|
||||||
static inline void _snd_printd(int level, const char *format, ...) {}
|
|
||||||
|
|
||||||
#define snd_BUG() do { } while (0)
|
#define snd_BUG() do { } while (0)
|
||||||
|
|
||||||
#define snd_BUG_ON(condition) ({ \
|
#define snd_BUG_ON(condition) ({ \
|
||||||
@ -421,26 +372,8 @@ static inline void _snd_printd(int level, const char *format, ...) {}
|
|||||||
unlikely(__ret_warn_on); \
|
unlikely(__ret_warn_on); \
|
||||||
})
|
})
|
||||||
|
|
||||||
static inline bool snd_printd_ratelimit(void) { return false; }
|
|
||||||
|
|
||||||
#endif /* CONFIG_SND_DEBUG */
|
#endif /* CONFIG_SND_DEBUG */
|
||||||
|
|
||||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
|
||||||
/**
|
|
||||||
* snd_printdd - debug printk
|
|
||||||
* @format: format string
|
|
||||||
*
|
|
||||||
* Works like snd_printk() for debugging purposes.
|
|
||||||
* Ignored when CONFIG_SND_DEBUG_VERBOSE is not set.
|
|
||||||
*/
|
|
||||||
#define snd_printdd(format, ...) \
|
|
||||||
__snd_printk(2, __FILE__, __LINE__, format, ##__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
__printf(1, 2)
|
|
||||||
static inline void snd_printdd(const char *format, ...) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */
|
#define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */
|
||||||
|
|
||||||
/* for easier backward-porting */
|
/* for easier backward-porting */
|
||||||
|
@ -282,9 +282,9 @@ static inline bool cs35l56_is_otp_register(unsigned int reg)
|
|||||||
return (reg >> 16) == 3;
|
return (reg >> 16) == 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct regmap_config cs35l56_regmap_i2c;
|
extern const struct regmap_config cs35l56_regmap_i2c;
|
||||||
extern struct regmap_config cs35l56_regmap_spi;
|
extern const struct regmap_config cs35l56_regmap_spi;
|
||||||
extern struct regmap_config cs35l56_regmap_sdw;
|
extern const struct regmap_config cs35l56_regmap_sdw;
|
||||||
|
|
||||||
extern const struct cirrus_amp_cal_controls cs35l56_calibration_controls;
|
extern const struct cirrus_amp_cal_controls cs35l56_calibration_controls;
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#define ES1688_HW_UNDEF 0x0003
|
#define ES1688_HW_UNDEF 0x0003
|
||||||
|
|
||||||
struct snd_es1688 {
|
struct snd_es1688 {
|
||||||
|
struct snd_card *card;
|
||||||
unsigned long port; /* port of ESS chip */
|
unsigned long port; /* port of ESS chip */
|
||||||
struct resource *res_port;
|
struct resource *res_port;
|
||||||
unsigned long mpu_port; /* MPU-401 port of ESS chip */
|
unsigned long mpu_port; /* MPU-401 port of ESS chip */
|
||||||
|
@ -42,17 +42,12 @@ struct snd_dma_device {
|
|||||||
#define SNDRV_DMA_TYPE_NONCONTIG 8 /* non-coherent SG buffer */
|
#define SNDRV_DMA_TYPE_NONCONTIG 8 /* non-coherent SG buffer */
|
||||||
#define SNDRV_DMA_TYPE_NONCOHERENT 9 /* non-coherent buffer */
|
#define SNDRV_DMA_TYPE_NONCOHERENT 9 /* non-coherent buffer */
|
||||||
#ifdef CONFIG_SND_DMA_SGBUF
|
#ifdef CONFIG_SND_DMA_SGBUF
|
||||||
#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_NONCONTIG
|
#define SNDRV_DMA_TYPE_DEV_SG 3 /* S/G pages */
|
||||||
#define SNDRV_DMA_TYPE_DEV_WC_SG 6 /* SG write-combined */
|
#define SNDRV_DMA_TYPE_DEV_WC_SG 6 /* SG write-combined */
|
||||||
#else
|
#else
|
||||||
#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */
|
#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */
|
||||||
#define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC
|
#define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC
|
||||||
#endif
|
#endif
|
||||||
/* fallback types, don't use those directly */
|
|
||||||
#ifdef CONFIG_SND_DMA_SGBUF
|
|
||||||
#define SNDRV_DMA_TYPE_DEV_SG_FALLBACK 10
|
|
||||||
#define SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK 11
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* info for buffer allocation
|
* info for buffer allocation
|
||||||
|
@ -123,6 +123,10 @@ struct snd_pcm_ops {
|
|||||||
#define SNDRV_PCM_RATE_384000 (1U<<14) /* 384000Hz */
|
#define SNDRV_PCM_RATE_384000 (1U<<14) /* 384000Hz */
|
||||||
#define SNDRV_PCM_RATE_705600 (1U<<15) /* 705600Hz */
|
#define SNDRV_PCM_RATE_705600 (1U<<15) /* 705600Hz */
|
||||||
#define SNDRV_PCM_RATE_768000 (1U<<16) /* 768000Hz */
|
#define SNDRV_PCM_RATE_768000 (1U<<16) /* 768000Hz */
|
||||||
|
/* extended rates since 6.12 */
|
||||||
|
#define SNDRV_PCM_RATE_12000 (1U<<17) /* 12000Hz */
|
||||||
|
#define SNDRV_PCM_RATE_24000 (1U<<18) /* 24000Hz */
|
||||||
|
#define SNDRV_PCM_RATE_128000 (1U<<19) /* 128000Hz */
|
||||||
|
|
||||||
#define SNDRV_PCM_RATE_CONTINUOUS (1U<<30) /* continuous range */
|
#define SNDRV_PCM_RATE_CONTINUOUS (1U<<30) /* continuous range */
|
||||||
#define SNDRV_PCM_RATE_KNOT (1U<<31) /* supports more non-continuous rates */
|
#define SNDRV_PCM_RATE_KNOT (1U<<31) /* supports more non-continuous rates */
|
||||||
@ -498,6 +502,9 @@ struct snd_pcm_substream {
|
|||||||
/* misc flags */
|
/* misc flags */
|
||||||
unsigned int hw_opened: 1;
|
unsigned int hw_opened: 1;
|
||||||
unsigned int managed_buffer_alloc:1;
|
unsigned int managed_buffer_alloc:1;
|
||||||
|
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
||||||
|
unsigned int xrun_counter; /* number of times xrun happens */
|
||||||
|
#endif /* CONFIG_SND_PCM_XRUN_DEBUG */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0)
|
#define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0)
|
||||||
@ -1355,48 +1362,6 @@ snd_pcm_set_fixed_buffer_all(struct snd_pcm *pcm, int type,
|
|||||||
return snd_pcm_set_managed_buffer_all(pcm, type, data, size, 0);
|
return snd_pcm_set_managed_buffer_all(pcm, type, data, size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
|
|
||||||
size_t size, gfp_t gfp_flags);
|
|
||||||
int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream);
|
|
||||||
struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
|
|
||||||
unsigned long offset);
|
|
||||||
/**
|
|
||||||
* snd_pcm_lib_alloc_vmalloc_buffer - allocate virtual DMA buffer
|
|
||||||
* @substream: the substream to allocate the buffer to
|
|
||||||
* @size: the requested buffer size, in bytes
|
|
||||||
*
|
|
||||||
* Allocates the PCM substream buffer using vmalloc(), i.e., the memory is
|
|
||||||
* contiguous in kernel virtual space, but not in physical memory. Use this
|
|
||||||
* if the buffer is accessed by kernel code but not by device DMA.
|
|
||||||
*
|
|
||||||
* Return: 1 if the buffer was changed, 0 if not changed, or a negative error
|
|
||||||
* code.
|
|
||||||
*/
|
|
||||||
static inline int snd_pcm_lib_alloc_vmalloc_buffer
|
|
||||||
(struct snd_pcm_substream *substream, size_t size)
|
|
||||||
{
|
|
||||||
return _snd_pcm_lib_alloc_vmalloc_buffer(substream, size,
|
|
||||||
GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* snd_pcm_lib_alloc_vmalloc_32_buffer - allocate 32-bit-addressable buffer
|
|
||||||
* @substream: the substream to allocate the buffer to
|
|
||||||
* @size: the requested buffer size, in bytes
|
|
||||||
*
|
|
||||||
* This function works like snd_pcm_lib_alloc_vmalloc_buffer(), but uses
|
|
||||||
* vmalloc_32(), i.e., the pages are allocated from 32-bit-addressable memory.
|
|
||||||
*
|
|
||||||
* Return: 1 if the buffer was changed, 0 if not changed, or a negative error
|
|
||||||
* code.
|
|
||||||
*/
|
|
||||||
static inline int snd_pcm_lib_alloc_vmalloc_32_buffer
|
|
||||||
(struct snd_pcm_substream *substream, size_t size)
|
|
||||||
{
|
|
||||||
return _snd_pcm_lib_alloc_vmalloc_buffer(substream, size,
|
|
||||||
GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define snd_pcm_get_dma_buf(substream) ((substream)->runtime->dma_buffer_p)
|
#define snd_pcm_get_dma_buf(substream) ((substream)->runtime->dma_buffer_p)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,10 +86,6 @@ static inline size_t snd_seq_event_packet_size(struct snd_seq_event *ev)
|
|||||||
/* interface for OSS emulation */
|
/* interface for OSS emulation */
|
||||||
int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo);
|
int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo);
|
||||||
|
|
||||||
/* port callback routines */
|
|
||||||
void snd_port_init_callback(struct snd_seq_port_callback *p);
|
|
||||||
struct snd_seq_port_callback *snd_port_alloc_callback(void);
|
|
||||||
|
|
||||||
/* port attach/detach */
|
/* port attach/detach */
|
||||||
int snd_seq_event_port_attach(int client, struct snd_seq_port_callback *pcbp,
|
int snd_seq_event_port_attach(int client, struct snd_seq_port_callback *pcbp,
|
||||||
int cap, int type, int midi_channels, int midi_voices, char *portname);
|
int cap, int type, int midi_channels, int midi_voices, char *portname);
|
||||||
|
@ -137,8 +137,4 @@ extern int snd_wavefront_fx_ioctl (struct snd_hwdep *,
|
|||||||
extern int snd_wavefront_fx_open (struct snd_hwdep *, struct file *);
|
extern int snd_wavefront_fx_open (struct snd_hwdep *, struct file *);
|
||||||
extern int snd_wavefront_fx_release (struct snd_hwdep *, struct file *);
|
extern int snd_wavefront_fx_release (struct snd_hwdep *, struct file *);
|
||||||
|
|
||||||
/* prefix in all snd_printk() delivered messages */
|
|
||||||
|
|
||||||
#define LOGNAME "WaveFront: "
|
|
||||||
|
|
||||||
#endif /* __SOUND_SND_WAVEFRONT_H__ */
|
#endif /* __SOUND_SND_WAVEFRONT_H__ */
|
||||||
|
@ -33,6 +33,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[];
|
|||||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[];
|
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[];
|
||||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_machines[];
|
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_machines[];
|
||||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[];
|
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[];
|
||||||
|
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_machines[];
|
||||||
|
|
||||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[];
|
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[];
|
||||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[];
|
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[];
|
||||||
@ -44,6 +45,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[];
|
|||||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[];
|
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[];
|
||||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[];
|
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[];
|
||||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[];
|
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[];
|
||||||
|
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* generic table used for HDA codec-based platforms, possibly with
|
* generic table used for HDA codec-based platforms, possibly with
|
||||||
|
@ -62,7 +62,6 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
|
|||||||
* @platform: string used for HDAudio codec support
|
* @platform: string used for HDAudio codec support
|
||||||
* @codec_mask: used for HDAudio support
|
* @codec_mask: used for HDAudio support
|
||||||
* @dmic_num: number of SoC- or chipset-attached PDM digital microphones
|
* @dmic_num: number of SoC- or chipset-attached PDM digital microphones
|
||||||
* @common_hdmi_codec_drv: use commom HDAudio HDMI codec driver
|
|
||||||
* @link_mask: SoundWire links enabled on the board
|
* @link_mask: SoundWire links enabled on the board
|
||||||
* @links: array of SoundWire link _ADR descriptors, null terminated
|
* @links: array of SoundWire link _ADR descriptors, null terminated
|
||||||
* @i2s_link_mask: I2S/TDM links enabled on the board
|
* @i2s_link_mask: I2S/TDM links enabled on the board
|
||||||
@ -70,15 +69,16 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
|
|||||||
* @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode
|
* @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode
|
||||||
* @subsystem_vendor: optional PCI SSID vendor value
|
* @subsystem_vendor: optional PCI SSID vendor value
|
||||||
* @subsystem_device: optional PCI SSID device value
|
* @subsystem_device: optional PCI SSID device value
|
||||||
|
* @subsystem_rev: optional PCI SSID revision value
|
||||||
* @subsystem_id_set: true if a value has been written to
|
* @subsystem_id_set: true if a value has been written to
|
||||||
* subsystem_vendor and subsystem_device.
|
* subsystem_vendor and subsystem_device.
|
||||||
|
* @bt_link_mask: BT offload link enabled on the board
|
||||||
*/
|
*/
|
||||||
struct snd_soc_acpi_mach_params {
|
struct snd_soc_acpi_mach_params {
|
||||||
u32 acpi_ipc_irq_index;
|
u32 acpi_ipc_irq_index;
|
||||||
const char *platform;
|
const char *platform;
|
||||||
u32 codec_mask;
|
u32 codec_mask;
|
||||||
u32 dmic_num;
|
u32 dmic_num;
|
||||||
bool common_hdmi_codec_drv;
|
|
||||||
u32 link_mask;
|
u32 link_mask;
|
||||||
const struct snd_soc_acpi_link_adr *links;
|
const struct snd_soc_acpi_link_adr *links;
|
||||||
u32 i2s_link_mask;
|
u32 i2s_link_mask;
|
||||||
@ -86,7 +86,9 @@ struct snd_soc_acpi_mach_params {
|
|||||||
struct snd_soc_dai_driver *dai_drivers;
|
struct snd_soc_dai_driver *dai_drivers;
|
||||||
unsigned short subsystem_vendor;
|
unsigned short subsystem_vendor;
|
||||||
unsigned short subsystem_device;
|
unsigned short subsystem_device;
|
||||||
|
unsigned short subsystem_rev;
|
||||||
bool subsystem_id_set;
|
bool subsystem_id_set;
|
||||||
|
u32 bt_link_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,8 +30,6 @@ static inline void snd_soc_card_mutex_unlock(struct snd_soc_card *card)
|
|||||||
|
|
||||||
struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
|
struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
|
||||||
const char *name);
|
const char *name);
|
||||||
struct snd_kcontrol *snd_soc_card_get_kcontrol_locked(struct snd_soc_card *soc_card,
|
|
||||||
const char *name);
|
|
||||||
int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
|
int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
|
||||||
struct snd_soc_jack *jack);
|
struct snd_soc_jack *jack);
|
||||||
int snd_soc_card_jack_new_pins(struct snd_soc_card *card, const char *id,
|
int snd_soc_card_jack_new_pins(struct snd_soc_card *card, const char *id,
|
||||||
|
@ -464,9 +464,6 @@ int snd_soc_component_force_enable_pin_unlocked(
|
|||||||
/* component controls */
|
/* component controls */
|
||||||
struct snd_kcontrol *snd_soc_component_get_kcontrol(struct snd_soc_component *component,
|
struct snd_kcontrol *snd_soc_component_get_kcontrol(struct snd_soc_component *component,
|
||||||
const char * const ctl);
|
const char * const ctl);
|
||||||
struct snd_kcontrol *
|
|
||||||
snd_soc_component_get_kcontrol_locked(struct snd_soc_component *component,
|
|
||||||
const char * const ctl);
|
|
||||||
int snd_soc_component_notify_control(struct snd_soc_component *component,
|
int snd_soc_component_notify_control(struct snd_soc_component *component,
|
||||||
const char * const ctl);
|
const char * const ctl);
|
||||||
|
|
||||||
|
@ -219,7 +219,6 @@ void snd_soc_dai_resume(struct snd_soc_dai *dai);
|
|||||||
int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
|
int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
|
||||||
struct snd_soc_pcm_runtime *rtd, int num);
|
struct snd_soc_pcm_runtime *rtd, int num);
|
||||||
bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int stream);
|
bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int stream);
|
||||||
void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link);
|
|
||||||
void snd_soc_dai_action(struct snd_soc_dai *dai,
|
void snd_soc_dai_action(struct snd_soc_dai *dai,
|
||||||
int stream, int action);
|
int stream, int action);
|
||||||
static inline void snd_soc_dai_activate(struct snd_soc_dai *dai,
|
static inline void snd_soc_dai_activate(struct snd_soc_dai *dai,
|
||||||
@ -240,8 +239,6 @@ int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd);
|
|||||||
int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream);
|
int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream);
|
||||||
int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
int rollback);
|
int rollback);
|
||||||
int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
|
|
||||||
int cmd);
|
|
||||||
void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
|
void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
|
||||||
snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay);
|
snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay);
|
||||||
|
|
||||||
@ -345,8 +342,7 @@ struct snd_soc_dai_ops {
|
|||||||
*/
|
*/
|
||||||
int (*trigger)(struct snd_pcm_substream *, int,
|
int (*trigger)(struct snd_pcm_substream *, int,
|
||||||
struct snd_soc_dai *);
|
struct snd_soc_dai *);
|
||||||
int (*bespoke_trigger)(struct snd_pcm_substream *, int,
|
|
||||||
struct snd_soc_dai *);
|
|
||||||
/*
|
/*
|
||||||
* For hardware based FIFO caused delay reporting.
|
* For hardware based FIFO caused delay reporting.
|
||||||
* Optional.
|
* Optional.
|
||||||
|
@ -58,7 +58,6 @@ enum snd_soc_dpcm_state {
|
|||||||
enum snd_soc_dpcm_trigger {
|
enum snd_soc_dpcm_trigger {
|
||||||
SND_SOC_DPCM_TRIGGER_PRE = 0,
|
SND_SOC_DPCM_TRIGGER_PRE = 0,
|
||||||
SND_SOC_DPCM_TRIGGER_POST,
|
SND_SOC_DPCM_TRIGGER_POST,
|
||||||
SND_SOC_DPCM_TRIGGER_BESPOKE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -114,24 +113,6 @@ struct snd_soc_dpcm_runtime {
|
|||||||
#define for_each_dpcm_be_rollback(fe, stream, _dpcm) \
|
#define for_each_dpcm_be_rollback(fe, stream, _dpcm) \
|
||||||
list_for_each_entry_continue_reverse(_dpcm, &(fe)->dpcm[stream].be_clients, list_be)
|
list_for_each_entry_continue_reverse(_dpcm, &(fe)->dpcm[stream].be_clients, list_be)
|
||||||
|
|
||||||
/* can this BE stop and free */
|
|
||||||
int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
|
|
||||||
struct snd_soc_pcm_runtime *be, int stream);
|
|
||||||
|
|
||||||
/* can this BE perform a hw_params() */
|
|
||||||
int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
|
|
||||||
struct snd_soc_pcm_runtime *be, int stream);
|
|
||||||
|
|
||||||
/* can this BE perform prepare */
|
|
||||||
int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
|
|
||||||
struct snd_soc_pcm_runtime *be, int stream);
|
|
||||||
|
|
||||||
/* is the current PCM operation for this FE ? */
|
|
||||||
int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
|
|
||||||
|
|
||||||
/* is the current PCM operation for this BE ? */
|
|
||||||
int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
|
|
||||||
struct snd_soc_pcm_runtime *be, int stream);
|
|
||||||
|
|
||||||
/* get the substream for this BE */
|
/* get the substream for this BE */
|
||||||
struct snd_pcm_substream *
|
struct snd_pcm_substream *
|
||||||
|
@ -815,6 +815,7 @@ struct snd_soc_dai_link {
|
|||||||
/* This DAI link can route to other DAI links at runtime (Frontend)*/
|
/* This DAI link can route to other DAI links at runtime (Frontend)*/
|
||||||
unsigned int dynamic:1;
|
unsigned int dynamic:1;
|
||||||
|
|
||||||
|
/* REMOVE ME */
|
||||||
/* DPCM capture and Playback support */
|
/* DPCM capture and Playback support */
|
||||||
unsigned int dpcm_capture:1;
|
unsigned int dpcm_capture:1;
|
||||||
unsigned int dpcm_playback:1;
|
unsigned int dpcm_playback:1;
|
||||||
@ -1206,11 +1207,11 @@ struct snd_soc_pcm_runtime {
|
|||||||
/* bit field */
|
/* bit field */
|
||||||
unsigned int pop_wait:1;
|
unsigned int pop_wait:1;
|
||||||
unsigned int fe_compr:1; /* for Dynamic PCM */
|
unsigned int fe_compr:1; /* for Dynamic PCM */
|
||||||
|
unsigned int initialized:1;
|
||||||
|
|
||||||
bool initialized;
|
/* CPU/Codec/Platform */
|
||||||
|
|
||||||
int num_components;
|
int num_components;
|
||||||
struct snd_soc_component *components[]; /* CPU/Codec/Platform */
|
struct snd_soc_component *components[] __counted_by(num_components);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* see soc_new_pcm_runtime() */
|
/* see soc_new_pcm_runtime() */
|
||||||
|
247
include/sound/soc_sdw_utils.h
Normal file
247
include/sound/soc_sdw_utils.h
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* This file incorporates work covered by the following copyright notice:
|
||||||
|
* Copyright (c) 2020 Intel Corporation
|
||||||
|
* Copyright(c) 2024 Advanced Micro Devices, Inc.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOC_SDW_UTILS_H
|
||||||
|
#define SOC_SDW_UTILS_H
|
||||||
|
|
||||||
|
#include <sound/soc.h>
|
||||||
|
#include <sound/soc-acpi.h>
|
||||||
|
|
||||||
|
#define SOC_SDW_MAX_DAI_NUM 8
|
||||||
|
#define SOC_SDW_MAX_NO_PROPS 2
|
||||||
|
#define SOC_SDW_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
|
||||||
|
|
||||||
|
/* If a CODEC has an optional speaker output, this quirk will enable it */
|
||||||
|
#define SOC_SDW_CODEC_SPKR BIT(15)
|
||||||
|
/*
|
||||||
|
* If the CODEC has additional devices attached directly to it.
|
||||||
|
*
|
||||||
|
* For the cs42l43:
|
||||||
|
* - 0 - No speaker output
|
||||||
|
* - SOC_SDW_CODEC_SPKR - CODEC internal speaker
|
||||||
|
* - SOC_SDW_SIDECAR_AMPS - 2x Sidecar amplifiers + CODEC internal speaker
|
||||||
|
* - SOC_SDW_CODEC_SPKR | SOF_SIDECAR_AMPS - Not currently supported
|
||||||
|
*/
|
||||||
|
#define SOC_SDW_SIDECAR_AMPS BIT(16)
|
||||||
|
|
||||||
|
#define SOC_SDW_UNUSED_DAI_ID -1
|
||||||
|
#define SOC_SDW_JACK_OUT_DAI_ID 0
|
||||||
|
#define SOC_SDW_JACK_IN_DAI_ID 1
|
||||||
|
#define SOC_SDW_AMP_OUT_DAI_ID 2
|
||||||
|
#define SOC_SDW_AMP_IN_DAI_ID 3
|
||||||
|
#define SOC_SDW_DMIC_DAI_ID 4
|
||||||
|
|
||||||
|
#define SOC_SDW_DAI_TYPE_JACK 0
|
||||||
|
#define SOC_SDW_DAI_TYPE_AMP 1
|
||||||
|
#define SOC_SDW_DAI_TYPE_MIC 2
|
||||||
|
|
||||||
|
struct asoc_sdw_codec_info;
|
||||||
|
|
||||||
|
struct asoc_sdw_dai_info {
|
||||||
|
const bool direction[2]; /* playback & capture support */
|
||||||
|
const char *dai_name;
|
||||||
|
const int dai_type;
|
||||||
|
const int dailink[2]; /* dailink id for each direction */
|
||||||
|
const struct snd_kcontrol_new *controls;
|
||||||
|
const int num_controls;
|
||||||
|
const struct snd_soc_dapm_widget *widgets;
|
||||||
|
const int num_widgets;
|
||||||
|
int (*init)(struct snd_soc_card *card,
|
||||||
|
struct snd_soc_dai_link *dai_links,
|
||||||
|
struct asoc_sdw_codec_info *info,
|
||||||
|
bool playback);
|
||||||
|
int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||||
|
int (*rtd_init)(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
bool rtd_init_done; /* Indicate that the rtd_init callback is done */
|
||||||
|
unsigned long quirk;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct asoc_sdw_codec_info {
|
||||||
|
const int part_id;
|
||||||
|
const int version_id;
|
||||||
|
const char *codec_name;
|
||||||
|
int amp_num;
|
||||||
|
const u8 acpi_id[ACPI_ID_LEN];
|
||||||
|
const bool ignore_internal_dmic;
|
||||||
|
const struct snd_soc_ops *ops;
|
||||||
|
struct asoc_sdw_dai_info dais[SOC_SDW_MAX_DAI_NUM];
|
||||||
|
const int dai_num;
|
||||||
|
|
||||||
|
int (*codec_card_late_probe)(struct snd_soc_card *card);
|
||||||
|
|
||||||
|
int (*count_sidecar)(struct snd_soc_card *card,
|
||||||
|
int *num_dais, int *num_devs);
|
||||||
|
int (*add_sidecar)(struct snd_soc_card *card,
|
||||||
|
struct snd_soc_dai_link **dai_links,
|
||||||
|
struct snd_soc_codec_conf **codec_conf);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct asoc_sdw_mc_private {
|
||||||
|
struct snd_soc_card card;
|
||||||
|
struct snd_soc_jack sdw_headset;
|
||||||
|
struct device *headset_codec_dev; /* only one headset per card */
|
||||||
|
struct device *amp_dev1, *amp_dev2;
|
||||||
|
bool append_dai_type;
|
||||||
|
bool ignore_internal_dmic;
|
||||||
|
void *private;
|
||||||
|
unsigned long mc_quirk;
|
||||||
|
int codec_info_list_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct asoc_sdw_endpoint {
|
||||||
|
struct list_head list;
|
||||||
|
|
||||||
|
u32 link_mask;
|
||||||
|
const char *codec_name;
|
||||||
|
const char *name_prefix;
|
||||||
|
bool include_sidecar;
|
||||||
|
|
||||||
|
struct asoc_sdw_codec_info *codec_info;
|
||||||
|
const struct asoc_sdw_dai_info *dai_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct asoc_sdw_dailink {
|
||||||
|
bool initialised;
|
||||||
|
|
||||||
|
u8 group_id;
|
||||||
|
u32 link_mask[SNDRV_PCM_STREAM_LAST + 1];
|
||||||
|
int num_devs[SNDRV_PCM_STREAM_LAST + 1];
|
||||||
|
struct list_head endpoints;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct asoc_sdw_codec_info codec_info_list[];
|
||||||
|
int asoc_sdw_get_codec_info_list_count(void);
|
||||||
|
|
||||||
|
int asoc_sdw_startup(struct snd_pcm_substream *substream);
|
||||||
|
int asoc_sdw_prepare(struct snd_pcm_substream *substream);
|
||||||
|
int asoc_sdw_prepare(struct snd_pcm_substream *substream);
|
||||||
|
int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd);
|
||||||
|
int asoc_sdw_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params);
|
||||||
|
int asoc_sdw_hw_free(struct snd_pcm_substream *substream);
|
||||||
|
void asoc_sdw_shutdown(struct snd_pcm_substream *substream);
|
||||||
|
|
||||||
|
const char *asoc_sdw_get_codec_name(struct device *dev,
|
||||||
|
const struct asoc_sdw_codec_info *codec_info,
|
||||||
|
const struct snd_soc_acpi_link_adr *adr_link,
|
||||||
|
int adr_index);
|
||||||
|
|
||||||
|
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr);
|
||||||
|
|
||||||
|
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_acpi(const u8 *acpi_id);
|
||||||
|
|
||||||
|
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_dai(const char *dai_name,
|
||||||
|
int *dai_index);
|
||||||
|
|
||||||
|
struct snd_soc_dai_link *asoc_sdw_mc_find_codec_dai_used(struct snd_soc_card *card,
|
||||||
|
const char *dai_name);
|
||||||
|
|
||||||
|
void asoc_sdw_mc_dailink_exit_loop(struct snd_soc_card *card);
|
||||||
|
|
||||||
|
int asoc_sdw_card_late_probe(struct snd_soc_card *card);
|
||||||
|
|
||||||
|
void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
|
||||||
|
int *be_id, char *name, int playback, int capture,
|
||||||
|
struct snd_soc_dai_link_component *cpus, int cpus_num,
|
||||||
|
struct snd_soc_dai_link_component *platform_component,
|
||||||
|
int num_platforms, struct snd_soc_dai_link_component *codecs,
|
||||||
|
int codecs_num, int (*init)(struct snd_soc_pcm_runtime *rtd),
|
||||||
|
const struct snd_soc_ops *ops);
|
||||||
|
|
||||||
|
int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
|
||||||
|
int *be_id, char *name, int playback, int capture,
|
||||||
|
const char *cpu_dai_name, const char *platform_comp_name,
|
||||||
|
int num_platforms, const char *codec_name,
|
||||||
|
const char *codec_dai_name,
|
||||||
|
int (*init)(struct snd_soc_pcm_runtime *rtd),
|
||||||
|
const struct snd_soc_ops *ops);
|
||||||
|
|
||||||
|
int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends);
|
||||||
|
|
||||||
|
struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks,
|
||||||
|
const struct snd_soc_acpi_endpoint *new);
|
||||||
|
|
||||||
|
int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
|
||||||
|
struct asoc_sdw_dailink *soc_dais,
|
||||||
|
struct asoc_sdw_endpoint *soc_ends,
|
||||||
|
int *num_devs);
|
||||||
|
|
||||||
|
int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd);
|
||||||
|
|
||||||
|
/* DMIC support */
|
||||||
|
int asoc_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd);
|
||||||
|
|
||||||
|
/* RT711 support */
|
||||||
|
int asoc_sdw_rt711_init(struct snd_soc_card *card,
|
||||||
|
struct snd_soc_dai_link *dai_links,
|
||||||
|
struct asoc_sdw_codec_info *info,
|
||||||
|
bool playback);
|
||||||
|
int asoc_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||||
|
|
||||||
|
/* RT711-SDCA support */
|
||||||
|
int asoc_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
|
||||||
|
struct snd_soc_dai_link *dai_links,
|
||||||
|
struct asoc_sdw_codec_info *info,
|
||||||
|
bool playback);
|
||||||
|
int asoc_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||||
|
|
||||||
|
/* RT1308 I2S support */
|
||||||
|
extern const struct snd_soc_ops soc_sdw_rt1308_i2s_ops;
|
||||||
|
|
||||||
|
/* generic amp support */
|
||||||
|
int asoc_sdw_rt_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_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||||
|
|
||||||
|
/* CS42L43 support */
|
||||||
|
int asoc_sdw_cs42l43_spk_init(struct snd_soc_card *card,
|
||||||
|
struct snd_soc_dai_link *dai_links,
|
||||||
|
struct asoc_sdw_codec_info *info,
|
||||||
|
bool playback);
|
||||||
|
|
||||||
|
/* CS AMP support */
|
||||||
|
int asoc_sdw_bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
|
||||||
|
int *num_dais, int *num_devs);
|
||||||
|
int asoc_sdw_bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
|
||||||
|
struct snd_soc_dai_link **dai_links,
|
||||||
|
struct snd_soc_codec_conf **codec_conf);
|
||||||
|
int asoc_sdw_bridge_cs35l56_spk_init(struct snd_soc_card *card,
|
||||||
|
struct snd_soc_dai_link *dai_links,
|
||||||
|
struct asoc_sdw_codec_info *info,
|
||||||
|
bool playback);
|
||||||
|
|
||||||
|
int asoc_sdw_cs_amp_init(struct snd_soc_card *card,
|
||||||
|
struct snd_soc_dai_link *dai_links,
|
||||||
|
struct asoc_sdw_codec_info *info,
|
||||||
|
bool playback);
|
||||||
|
|
||||||
|
/* MAXIM codec support */
|
||||||
|
int asoc_sdw_maxim_init(struct snd_soc_card *card,
|
||||||
|
struct snd_soc_dai_link *dai_links,
|
||||||
|
struct asoc_sdw_codec_info *info,
|
||||||
|
bool playback);
|
||||||
|
|
||||||
|
/* dai_link init callbacks */
|
||||||
|
int asoc_sdw_rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
int asoc_sdw_rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
int asoc_sdw_rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
int asoc_sdw_rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
int asoc_sdw_rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
int asoc_sdw_rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
int asoc_sdw_rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
int asoc_sdw_rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
int asoc_sdw_cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
int asoc_sdw_cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||||
|
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);
|
||||||
|
|
||||||
|
#endif
|
@ -86,9 +86,11 @@ struct snd_sf_list {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Prototypes for soundfont.c */
|
/* Prototypes for soundfont.c */
|
||||||
int snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data,
|
int snd_soundfont_load(struct snd_card *card,
|
||||||
|
struct snd_sf_list *sflist, const void __user *data,
|
||||||
long count, int client);
|
long count, int client);
|
||||||
int snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
|
int snd_soundfont_load_guspatch(struct snd_card *card,
|
||||||
|
struct snd_sf_list *sflist, const char __user *data,
|
||||||
long count);
|
long count);
|
||||||
int snd_soundfont_close_check(struct snd_sf_list *sflist, int client);
|
int snd_soundfont_close_check(struct snd_sf_list *sflist, int client);
|
||||||
|
|
||||||
|
279
include/sound/tas2563-tlv.h
Normal file
279
include/sound/tas2563-tlv.h
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
//
|
||||||
|
// ALSA SoC Texas Instruments TAS2563 Audio Smart Amplifier
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 - 2024 Texas Instruments Incorporated
|
||||||
|
// https://www.ti.com
|
||||||
|
//
|
||||||
|
// The TAS2563 driver implements a flexible and configurable
|
||||||
|
// algo coefficient setting for one, two, or even multiple
|
||||||
|
// TAS2563 chips.
|
||||||
|
//
|
||||||
|
// Author: Shenghao Ding <shenghao-ding@ti.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __TAS2563_TLV_H__
|
||||||
|
#define __TAS2563_TLV_H__
|
||||||
|
|
||||||
|
static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2563_dvc_tlv, -12150, 50, 1);
|
||||||
|
|
||||||
|
/* pow(10, db/20) * pow(2,30) */
|
||||||
|
static const __maybe_unused unsigned char tas2563_dvc_table[][4] = {
|
||||||
|
{ 0X00, 0X00, 0X00, 0X00 }, /* -121.5db */
|
||||||
|
{ 0X00, 0X00, 0X03, 0XBC }, /* -121.0db */
|
||||||
|
{ 0X00, 0X00, 0X03, 0XF5 }, /* -120.5db */
|
||||||
|
{ 0X00, 0X00, 0X04, 0X31 }, /* -120.0db */
|
||||||
|
{ 0X00, 0X00, 0X04, 0X71 }, /* -119.5db */
|
||||||
|
{ 0X00, 0X00, 0X04, 0XB4 }, /* -119.0db */
|
||||||
|
{ 0X00, 0X00, 0X04, 0XFC }, /* -118.5db */
|
||||||
|
{ 0X00, 0X00, 0X05, 0X47 }, /* -118.0db */
|
||||||
|
{ 0X00, 0X00, 0X05, 0X97 }, /* -117.5db */
|
||||||
|
{ 0X00, 0X00, 0X05, 0XEC }, /* -117.0db */
|
||||||
|
{ 0X00, 0X00, 0X06, 0X46 }, /* -116.5db */
|
||||||
|
{ 0X00, 0X00, 0X06, 0XA5 }, /* -116.0db */
|
||||||
|
{ 0X00, 0X00, 0X07, 0X0A }, /* -115.5db */
|
||||||
|
{ 0X00, 0X00, 0X07, 0X75 }, /* -115.0db */
|
||||||
|
{ 0X00, 0X00, 0X07, 0XE6 }, /* -114.5db */
|
||||||
|
{ 0X00, 0X00, 0X08, 0X5E }, /* -114.0db */
|
||||||
|
{ 0X00, 0X00, 0X08, 0XDD }, /* -113.5db */
|
||||||
|
{ 0X00, 0X00, 0X09, 0X63 }, /* -113.0db */
|
||||||
|
{ 0X00, 0X00, 0X09, 0XF2 }, /* -112.5db */
|
||||||
|
{ 0X00, 0X00, 0X0A, 0X89 }, /* -112.0db */
|
||||||
|
{ 0X00, 0X00, 0X0B, 0X28 }, /* -111.5db */
|
||||||
|
{ 0X00, 0X00, 0X0B, 0XD2 }, /* -111.0db */
|
||||||
|
{ 0X00, 0X00, 0X0C, 0X85 }, /* -110.5db */
|
||||||
|
{ 0X00, 0X00, 0X0D, 0X43 }, /* -110.0db */
|
||||||
|
{ 0X00, 0X00, 0X0E, 0X0C }, /* -109.5db */
|
||||||
|
{ 0X00, 0X00, 0X0E, 0XE1 }, /* -109.0db */
|
||||||
|
{ 0X00, 0X00, 0X0F, 0XC3 }, /* -108.5db */
|
||||||
|
{ 0X00, 0X00, 0X10, 0XB2 }, /* -108.0db */
|
||||||
|
{ 0X00, 0X00, 0X11, 0XAF }, /* -107.5db */
|
||||||
|
{ 0X00, 0X00, 0X12, 0XBC }, /* -107.0db */
|
||||||
|
{ 0X00, 0X00, 0X13, 0XD8 }, /* -106.5db */
|
||||||
|
{ 0X00, 0X00, 0X15, 0X05 }, /* -106.0db */
|
||||||
|
{ 0X00, 0X00, 0X16, 0X44 }, /* -105.5db */
|
||||||
|
{ 0X00, 0X00, 0X17, 0X96 }, /* -105.0db */
|
||||||
|
{ 0X00, 0X00, 0X18, 0XFB }, /* -104.5db */
|
||||||
|
{ 0X00, 0X00, 0X1A, 0X76 }, /* -104.0db */
|
||||||
|
{ 0X00, 0X00, 0X1C, 0X08 }, /* -103.5db */
|
||||||
|
{ 0X00, 0X00, 0X1D, 0XB1 }, /* -103.0db */
|
||||||
|
{ 0X00, 0X00, 0X1F, 0X73 }, /* -102.5db */
|
||||||
|
{ 0X00, 0X00, 0X21, 0X51 }, /* -102.0db */
|
||||||
|
{ 0X00, 0X00, 0X23, 0X4A }, /* -101.5db */
|
||||||
|
{ 0X00, 0X00, 0X25, 0X61 }, /* -101.0db */
|
||||||
|
{ 0X00, 0X00, 0X27, 0X98 }, /* -100.5db */
|
||||||
|
{ 0X00, 0X00, 0X29, 0XF1 }, /* -100.0db */
|
||||||
|
{ 0X00, 0X00, 0X2C, 0X6D }, /* -99.5db */
|
||||||
|
{ 0X00, 0X00, 0X2F, 0X0F }, /* -99.0db */
|
||||||
|
{ 0X00, 0X00, 0X31, 0XD9 }, /* -98.5db */
|
||||||
|
{ 0X00, 0X00, 0X34, 0XCD }, /* -98.0db */
|
||||||
|
{ 0X00, 0X00, 0X37, 0XEE }, /* -97.5db */
|
||||||
|
{ 0X00, 0X00, 0X3B, 0X3F }, /* -97.0db */
|
||||||
|
{ 0X00, 0X00, 0X3E, 0XC1 }, /* -96.5db */
|
||||||
|
{ 0X00, 0X00, 0X42, 0X79 }, /* -96.0db */
|
||||||
|
{ 0X00, 0X00, 0X46, 0X6A }, /* -95.5db */
|
||||||
|
{ 0X00, 0X00, 0X4A, 0X96 }, /* -95.0db */
|
||||||
|
{ 0X00, 0X00, 0X4F, 0X01 }, /* -94.5db */
|
||||||
|
{ 0X00, 0X00, 0X53, 0XAF }, /* -94.0db */
|
||||||
|
{ 0X00, 0X00, 0X58, 0XA5 }, /* -93.5db */
|
||||||
|
{ 0X00, 0X00, 0X5D, 0XE6 }, /* -93.0db */
|
||||||
|
{ 0X00, 0X00, 0X63, 0X76 }, /* -92.5db */
|
||||||
|
{ 0X00, 0X00, 0X69, 0X5B }, /* -92.0db */
|
||||||
|
{ 0X00, 0X00, 0X6F, 0X99 }, /* -91.5db */
|
||||||
|
{ 0X00, 0X00, 0X76, 0X36 }, /* -91.0db */
|
||||||
|
{ 0X00, 0X00, 0X7D, 0X37 }, /* -90.5db */
|
||||||
|
{ 0X00, 0X00, 0X84, 0XA2 }, /* -90.0db */
|
||||||
|
{ 0X00, 0X00, 0X8C, 0X7E }, /* -89.5db */
|
||||||
|
{ 0X00, 0X00, 0X94, 0XD1 }, /* -89.0db */
|
||||||
|
{ 0X00, 0X00, 0X9D, 0XA3 }, /* -88.5db */
|
||||||
|
{ 0X00, 0X00, 0XA6, 0XFA }, /* -88.0db */
|
||||||
|
{ 0X00, 0X00, 0XB0, 0XDF }, /* -87.5db */
|
||||||
|
{ 0X00, 0X00, 0XBB, 0X5A }, /* -87.0db */
|
||||||
|
{ 0X00, 0X00, 0XC6, 0X74 }, /* -86.5db */
|
||||||
|
{ 0X00, 0X00, 0XD2, 0X36 }, /* -86.0db */
|
||||||
|
{ 0X00, 0X00, 0XDE, 0XAB }, /* -85.5db */
|
||||||
|
{ 0X00, 0X00, 0XEB, 0XDC }, /* -85.0db */
|
||||||
|
{ 0X00, 0X00, 0XF9, 0XD6 }, /* -84.5db */
|
||||||
|
{ 0X00, 0X01, 0X08, 0XA4 }, /* -84.0db */
|
||||||
|
{ 0X00, 0X01, 0X18, 0X52 }, /* -83.5db */
|
||||||
|
{ 0X00, 0X01, 0X28, 0XEF }, /* -83.0db */
|
||||||
|
{ 0X00, 0X01, 0X3A, 0X87 }, /* -82.5db */
|
||||||
|
{ 0X00, 0X01, 0X4D, 0X2A }, /* -82.0db */
|
||||||
|
{ 0X00, 0X01, 0X60, 0XE8 }, /* -81.5db */
|
||||||
|
{ 0X00, 0X01, 0X75, 0XD1 }, /* -81.0db */
|
||||||
|
{ 0X00, 0X01, 0X8B, 0XF7 }, /* -80.5db */
|
||||||
|
{ 0X00, 0X01, 0XA3, 0X6E }, /* -80.0db */
|
||||||
|
{ 0X00, 0X01, 0XBC, 0X48 }, /* -79.5db */
|
||||||
|
{ 0X00, 0X01, 0XD6, 0X9B }, /* -79.0db */
|
||||||
|
{ 0X00, 0X01, 0XF2, 0X7E }, /* -78.5db */
|
||||||
|
{ 0X00, 0X02, 0X10, 0X08 }, /* -78.0db */
|
||||||
|
{ 0X00, 0X02, 0X2F, 0X51 }, /* -77.5db */
|
||||||
|
{ 0X00, 0X02, 0X50, 0X76 }, /* -77.0db */
|
||||||
|
{ 0X00, 0X02, 0X73, 0X91 }, /* -76.5db */
|
||||||
|
{ 0X00, 0X02, 0X98, 0XC0 }, /* -76.0db */
|
||||||
|
{ 0X00, 0X02, 0XC0, 0X24 }, /* -75.5db */
|
||||||
|
{ 0X00, 0X02, 0XE9, 0XDD }, /* -75.0db */
|
||||||
|
{ 0X00, 0X03, 0X16, 0X0F }, /* -74.5db */
|
||||||
|
{ 0X00, 0X03, 0X44, 0XDF }, /* -74.0db */
|
||||||
|
{ 0X00, 0X03, 0X76, 0X76 }, /* -73.5db */
|
||||||
|
{ 0X00, 0X03, 0XAA, 0XFC }, /* -73.0db */
|
||||||
|
{ 0X00, 0X03, 0XE2, 0XA0 }, /* -72.5db */
|
||||||
|
{ 0X00, 0X04, 0X1D, 0X8F }, /* -72.0db */
|
||||||
|
{ 0X00, 0X04, 0X5B, 0XFD }, /* -71.5db */
|
||||||
|
{ 0X00, 0X04, 0X9E, 0X1D }, /* -71.0db */
|
||||||
|
{ 0X00, 0X04, 0XE4, 0X29 }, /* -70.5db */
|
||||||
|
{ 0X00, 0X05, 0X2E, 0X5A }, /* -70.0db */
|
||||||
|
{ 0X00, 0X05, 0X7C, 0XF2 }, /* -69.5db */
|
||||||
|
{ 0X00, 0X05, 0XD0, 0X31 }, /* -69.0db */
|
||||||
|
{ 0X00, 0X06, 0X28, 0X60 }, /* -68.5db */
|
||||||
|
{ 0X00, 0X06, 0X85, 0XC8 }, /* -68.0db */
|
||||||
|
{ 0X00, 0X06, 0XE8, 0XB9 }, /* -67.5db */
|
||||||
|
{ 0X00, 0X07, 0X51, 0X86 }, /* -67.0db */
|
||||||
|
{ 0X00, 0X07, 0XC0, 0X8A }, /* -66.5db */
|
||||||
|
{ 0X00, 0X08, 0X36, 0X21 }, /* -66.0db */
|
||||||
|
{ 0X00, 0X08, 0XB2, 0XB0 }, /* -65.5db */
|
||||||
|
{ 0X00, 0X09, 0X36, 0XA1 }, /* -65.0db */
|
||||||
|
{ 0X00, 0X09, 0XC2, 0X63 }, /* -64.5db */
|
||||||
|
{ 0X00, 0X0A, 0X56, 0X6D }, /* -64.0db */
|
||||||
|
{ 0X00, 0X0A, 0XF3, 0X3C }, /* -63.5db */
|
||||||
|
{ 0X00, 0X0B, 0X99, 0X56 }, /* -63.0db */
|
||||||
|
{ 0X00, 0X0C, 0X49, 0X48 }, /* -62.5db */
|
||||||
|
{ 0X00, 0X0D, 0X03, 0XA7 }, /* -62.0db */
|
||||||
|
{ 0X00, 0X0D, 0XC9, 0X11 }, /* -61.5db */
|
||||||
|
{ 0X00, 0X0E, 0X9A, 0X2D }, /* -61.0db */
|
||||||
|
{ 0X00, 0X0F, 0X77, 0XAD }, /* -60.5db */
|
||||||
|
{ 0X00, 0X10, 0X62, 0X4D }, /* -60.0db */
|
||||||
|
{ 0X00, 0X11, 0X5A, 0XD5 }, /* -59.5db */
|
||||||
|
{ 0X00, 0X12, 0X62, 0X16 }, /* -59.0db */
|
||||||
|
{ 0X00, 0X13, 0X78, 0XF0 }, /* -58.5db */
|
||||||
|
{ 0X00, 0X14, 0XA0, 0X50 }, /* -58.0db */
|
||||||
|
{ 0X00, 0X15, 0XD9, 0X31 }, /* -57.5db */
|
||||||
|
{ 0X00, 0X17, 0X24, 0X9C }, /* -57.0db */
|
||||||
|
{ 0X00, 0X18, 0X83, 0XAA }, /* -56.5db */
|
||||||
|
{ 0X00, 0X19, 0XF7, 0X86 }, /* -56.0db */
|
||||||
|
{ 0X00, 0X1B, 0X81, 0X6A }, /* -55.5db */
|
||||||
|
{ 0X00, 0X1D, 0X22, 0XA4 }, /* -55.0db */
|
||||||
|
{ 0X00, 0X1E, 0XDC, 0X98 }, /* -54.5db */
|
||||||
|
{ 0X00, 0X20, 0XB0, 0XBC }, /* -54.0db */
|
||||||
|
{ 0X00, 0X22, 0XA0, 0X9D }, /* -53.5db */
|
||||||
|
{ 0X00, 0X24, 0XAD, 0XE0 }, /* -53.0db */
|
||||||
|
{ 0X00, 0X26, 0XDA, 0X43 }, /* -52.5db */
|
||||||
|
{ 0X00, 0X29, 0X27, 0X9D }, /* -52.0db */
|
||||||
|
{ 0X00, 0X2B, 0X97, 0XE3 }, /* -51.5db */
|
||||||
|
{ 0X00, 0X2E, 0X2D, 0X27 }, /* -51.0db */
|
||||||
|
{ 0X00, 0X30, 0XE9, 0X9A }, /* -50.5db */
|
||||||
|
{ 0X00, 0X33, 0XCF, 0X8D }, /* -50.0db */
|
||||||
|
{ 0X00, 0X36, 0XE1, 0X78 }, /* -49.5db */
|
||||||
|
{ 0X00, 0X3A, 0X21, 0XF3 }, /* -49.0db */
|
||||||
|
{ 0X00, 0X3D, 0X93, 0XC3 }, /* -48.5db */
|
||||||
|
{ 0X00, 0X41, 0X39, 0XD3 }, /* -48.0db */
|
||||||
|
{ 0X00, 0X45, 0X17, 0X3B }, /* -47.5db */
|
||||||
|
{ 0X00, 0X49, 0X2F, 0X44 }, /* -47.0db */
|
||||||
|
{ 0X00, 0X4D, 0X85, 0X66 }, /* -46.5db */
|
||||||
|
{ 0X00, 0X52, 0X1D, 0X50 }, /* -46.0db */
|
||||||
|
{ 0X00, 0X56, 0XFA, 0XE8 }, /* -45.5db */
|
||||||
|
{ 0X00, 0X5C, 0X22, 0X4E }, /* -45.0db */
|
||||||
|
{ 0X00, 0X61, 0X97, 0XE1 }, /* -44.5db */
|
||||||
|
{ 0X00, 0X67, 0X60, 0X44 }, /* -44.0db */
|
||||||
|
{ 0X00, 0X6D, 0X80, 0X60 }, /* -43.5db */
|
||||||
|
{ 0X00, 0X73, 0XFD, 0X65 }, /* -43.0db */
|
||||||
|
{ 0X00, 0X7A, 0XDC, 0XD7 }, /* -42.5db */
|
||||||
|
{ 0X00, 0X82, 0X24, 0X8A }, /* -42.0db */
|
||||||
|
{ 0X00, 0X89, 0XDA, 0XAB }, /* -41.5db */
|
||||||
|
{ 0X00, 0X92, 0X05, 0XC6 }, /* -41.0db */
|
||||||
|
{ 0X00, 0X9A, 0XAC, 0XC8 }, /* -40.5db */
|
||||||
|
{ 0X00, 0XA3, 0XD7, 0X0A }, /* -40.0db */
|
||||||
|
{ 0X00, 0XAD, 0X8C, 0X52 }, /* -39.5db */
|
||||||
|
{ 0X00, 0XB7, 0XD4, 0XDD }, /* -39.0db */
|
||||||
|
{ 0X00, 0XC2, 0XB9, 0X65 }, /* -38.5db */
|
||||||
|
{ 0X00, 0XCE, 0X43, 0X28 }, /* -38.0db */
|
||||||
|
{ 0X00, 0XDA, 0X7B, 0XF1 }, /* -37.5db */
|
||||||
|
{ 0X00, 0XE7, 0X6E, 0X1E }, /* -37.0db */
|
||||||
|
{ 0X00, 0XF5, 0X24, 0XAC }, /* -36.5db */
|
||||||
|
{ 0X01, 0X03, 0XAB, 0X3D }, /* -36.0db */
|
||||||
|
{ 0X01, 0X13, 0X0E, 0X24 }, /* -35.5db */
|
||||||
|
{ 0X01, 0X23, 0X5A, 0X71 }, /* -35.0db */
|
||||||
|
{ 0X01, 0X34, 0X9D, 0XF8 }, /* -34.5db */
|
||||||
|
{ 0X01, 0X46, 0XE7, 0X5D }, /* -34.0db */
|
||||||
|
{ 0X01, 0X5A, 0X46, 0X27 }, /* -33.5db */
|
||||||
|
{ 0X01, 0X6E, 0XCA, 0XC5 }, /* -33.0db */
|
||||||
|
{ 0X01, 0X84, 0X86, 0X9F }, /* -32.5db */
|
||||||
|
{ 0X01, 0X9B, 0X8C, 0X27 }, /* -32.0db */
|
||||||
|
{ 0X01, 0XB3, 0XEE, 0XE5 }, /* -31.5db */
|
||||||
|
{ 0X01, 0XCD, 0XC3, 0X8C }, /* -31.0db */
|
||||||
|
{ 0X01, 0XE9, 0X20, 0X05 }, /* -30.5db */
|
||||||
|
{ 0X02, 0X06, 0X1B, 0X89 }, /* -30.0db */
|
||||||
|
{ 0X02, 0X24, 0XCE, 0XB0 }, /* -29.5db */
|
||||||
|
{ 0X02, 0X45, 0X53, 0X85 }, /* -29.0db */
|
||||||
|
{ 0X02, 0X67, 0XC5, 0XA2 }, /* -28.5db */
|
||||||
|
{ 0X02, 0X8C, 0X42, 0X3F }, /* -28.0db */
|
||||||
|
{ 0X02, 0XB2, 0XE8, 0X55 }, /* -27.5db */
|
||||||
|
{ 0X02, 0XDB, 0XD8, 0XAD }, /* -27.0db */
|
||||||
|
{ 0X03, 0X07, 0X36, 0X05 }, /* -26.5db */
|
||||||
|
{ 0X03, 0X35, 0X25, 0X29 }, /* -26.0db */
|
||||||
|
{ 0X03, 0X65, 0XCD, 0X13 }, /* -25.5db */
|
||||||
|
{ 0X03, 0X99, 0X57, 0X0C }, /* -25.0db */
|
||||||
|
{ 0X03, 0XCF, 0XEE, 0XCF }, /* -24.5db */
|
||||||
|
{ 0X04, 0X09, 0XC2, 0XB0 }, /* -24.0db */
|
||||||
|
{ 0X04, 0X47, 0X03, 0XC1 }, /* -23.5db */
|
||||||
|
{ 0X04, 0X87, 0XE5, 0XFB }, /* -23.0db */
|
||||||
|
{ 0X04, 0XCC, 0XA0, 0X6D }, /* -22.5db */
|
||||||
|
{ 0X05, 0X15, 0X6D, 0X68 }, /* -22.0db */
|
||||||
|
{ 0X05, 0X62, 0X8A, 0XB3 }, /* -21.5db */
|
||||||
|
{ 0X05, 0XB4, 0X39, 0XBC }, /* -21.0db */
|
||||||
|
{ 0X06, 0X0A, 0XBF, 0XD4 }, /* -20.5db */
|
||||||
|
{ 0X06, 0X66, 0X66, 0X66 }, /* -20.0db */
|
||||||
|
{ 0X06, 0XC7, 0X7B, 0X36 }, /* -19.5db */
|
||||||
|
{ 0X07, 0X2E, 0X50, 0XA6 }, /* -19.0db */
|
||||||
|
{ 0X07, 0X9B, 0X3D, 0XF6 }, /* -18.5db */
|
||||||
|
{ 0X08, 0X0E, 0X9F, 0X96 }, /* -18.0db */
|
||||||
|
{ 0X08, 0X88, 0XD7, 0X6D }, /* -17.5db */
|
||||||
|
{ 0X09, 0X0A, 0X4D, 0X2F }, /* -17.0db */
|
||||||
|
{ 0X09, 0X93, 0X6E, 0XB8 }, /* -16.5db */
|
||||||
|
{ 0X0A, 0X24, 0XB0, 0X62 }, /* -16.0db */
|
||||||
|
{ 0X0A, 0XBE, 0X8D, 0X70 }, /* -15.5db */
|
||||||
|
{ 0X0B, 0X61, 0X88, 0X71 }, /* -15.0db */
|
||||||
|
{ 0X0C, 0X0E, 0X2B, 0XB0 }, /* -14.5db */
|
||||||
|
{ 0X0C, 0XC5, 0X09, 0XAB }, /* -14.0db */
|
||||||
|
{ 0X0D, 0X86, 0XBD, 0X8D }, /* -13.5db */
|
||||||
|
{ 0X0E, 0X53, 0XEB, 0XB3 }, /* -13.0db */
|
||||||
|
{ 0X0F, 0X2D, 0X42, 0X38 }, /* -12.5db */
|
||||||
|
{ 0X10, 0X13, 0X79, 0X87 }, /* -12.0db */
|
||||||
|
{ 0X11, 0X07, 0X54, 0XF9 }, /* -11.5db */
|
||||||
|
{ 0X12, 0X09, 0XA3, 0X7A }, /* -11.0db */
|
||||||
|
{ 0X13, 0X1B, 0X40, 0X39 }, /* -10.5db */
|
||||||
|
{ 0X14, 0X3D, 0X13, 0X62 }, /* -10.0db */
|
||||||
|
{ 0X15, 0X70, 0X12, 0XE1 }, /* -9.5db */
|
||||||
|
{ 0X16, 0XB5, 0X43, 0X37 }, /* -9.0db */
|
||||||
|
{ 0X18, 0X0D, 0XB8, 0X54 }, /* -8.5db */
|
||||||
|
{ 0X19, 0X7A, 0X96, 0X7F }, /* -8.0db */
|
||||||
|
{ 0X1A, 0XFD, 0X13, 0X54 }, /* -7.5db */
|
||||||
|
{ 0X1C, 0X96, 0X76, 0XC6 }, /* -7.0db */
|
||||||
|
{ 0X1E, 0X48, 0X1C, 0X37 }, /* -6.5db */
|
||||||
|
{ 0X20, 0X13, 0X73, 0X9E }, /* -6.0db */
|
||||||
|
{ 0X21, 0XFA, 0X02, 0XBF }, /* -5.5db */
|
||||||
|
{ 0X23, 0XFD, 0X66, 0X78 }, /* -5.0db */
|
||||||
|
{ 0X26, 0X1F, 0X54, 0X1C }, /* -4.5db */
|
||||||
|
{ 0X28, 0X61, 0X9A, 0XE9 }, /* -4.0db */
|
||||||
|
{ 0X2A, 0XC6, 0X25, 0X91 }, /* -3.5db */
|
||||||
|
{ 0X2D, 0X4E, 0XFB, 0XD5 }, /* -3.0db */
|
||||||
|
{ 0X2F, 0XFE, 0X44, 0X48 }, /* -2.5db */
|
||||||
|
{ 0X32, 0XD6, 0X46, 0X17 }, /* -2.0db */
|
||||||
|
{ 0X35, 0XD9, 0X6B, 0X02 }, /* -1.5db */
|
||||||
|
{ 0X39, 0X0A, 0X41, 0X5F }, /* -1.0db */
|
||||||
|
{ 0X3C, 0X6B, 0X7E, 0X4F }, /* -0.5db */
|
||||||
|
{ 0X40, 0X00, 0X00, 0X00 }, /* 0.0db */
|
||||||
|
{ 0X43, 0XCA, 0XD0, 0X22 }, /* 0.5db */
|
||||||
|
{ 0X47, 0XCF, 0X26, 0X7D }, /* 1.0db */
|
||||||
|
{ 0X4C, 0X10, 0X6B, 0XA5 }, /* 1.5db */
|
||||||
|
{ 0X50, 0X92, 0X3B, 0XE3 }, /* 2.0db */
|
||||||
|
{ 0X55, 0X58, 0X6A, 0X46 }, /* 2.5db */
|
||||||
|
{ 0X5A, 0X67, 0X03, 0XDF }, /* 3.0db */
|
||||||
|
{ 0X5F, 0XC2, 0X53, 0X32 }, /* 3.5db */
|
||||||
|
{ 0X65, 0X6E, 0XE3, 0XDB }, /* 4.0db */
|
||||||
|
{ 0X6B, 0X71, 0X86, 0X68 }, /* 4.5db */
|
||||||
|
{ 0X71, 0XCF, 0X54, 0X71 }, /* 5.0db */
|
||||||
|
{ 0X78, 0X8D, 0XB4, 0XE9 }, /* 5.5db */
|
||||||
|
{ 0X7F, 0XFF, 0XFF, 0XFF }, /* 6.0db */
|
||||||
|
};
|
||||||
|
#endif
|
@ -17,265 +17,5 @@
|
|||||||
|
|
||||||
static const __maybe_unused DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 100, 0);
|
static const __maybe_unused DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 100, 0);
|
||||||
static const __maybe_unused DECLARE_TLV_DB_SCALE(amp_vol_tlv, 1100, 50, 0);
|
static const __maybe_unused DECLARE_TLV_DB_SCALE(amp_vol_tlv, 1100, 50, 0);
|
||||||
static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2563_dvc_tlv, -12150, 50, 1);
|
|
||||||
|
|
||||||
/* pow(10, db/20) * pow(2,30) */
|
|
||||||
static const __maybe_unused unsigned char tas2563_dvc_table[][4] = {
|
|
||||||
{ 0X00, 0X00, 0X00, 0X00 }, /* -121.5db */
|
|
||||||
{ 0X00, 0X00, 0X03, 0XBC }, /* -121.0db */
|
|
||||||
{ 0X00, 0X00, 0X03, 0XF5 }, /* -120.5db */
|
|
||||||
{ 0X00, 0X00, 0X04, 0X31 }, /* -120.0db */
|
|
||||||
{ 0X00, 0X00, 0X04, 0X71 }, /* -119.5db */
|
|
||||||
{ 0X00, 0X00, 0X04, 0XB4 }, /* -119.0db */
|
|
||||||
{ 0X00, 0X00, 0X04, 0XFC }, /* -118.5db */
|
|
||||||
{ 0X00, 0X00, 0X05, 0X47 }, /* -118.0db */
|
|
||||||
{ 0X00, 0X00, 0X05, 0X97 }, /* -117.5db */
|
|
||||||
{ 0X00, 0X00, 0X05, 0XEC }, /* -117.0db */
|
|
||||||
{ 0X00, 0X00, 0X06, 0X46 }, /* -116.5db */
|
|
||||||
{ 0X00, 0X00, 0X06, 0XA5 }, /* -116.0db */
|
|
||||||
{ 0X00, 0X00, 0X07, 0X0A }, /* -115.5db */
|
|
||||||
{ 0X00, 0X00, 0X07, 0X75 }, /* -115.0db */
|
|
||||||
{ 0X00, 0X00, 0X07, 0XE6 }, /* -114.5db */
|
|
||||||
{ 0X00, 0X00, 0X08, 0X5E }, /* -114.0db */
|
|
||||||
{ 0X00, 0X00, 0X08, 0XDD }, /* -113.5db */
|
|
||||||
{ 0X00, 0X00, 0X09, 0X63 }, /* -113.0db */
|
|
||||||
{ 0X00, 0X00, 0X09, 0XF2 }, /* -112.5db */
|
|
||||||
{ 0X00, 0X00, 0X0A, 0X89 }, /* -112.0db */
|
|
||||||
{ 0X00, 0X00, 0X0B, 0X28 }, /* -111.5db */
|
|
||||||
{ 0X00, 0X00, 0X0B, 0XD2 }, /* -111.0db */
|
|
||||||
{ 0X00, 0X00, 0X0C, 0X85 }, /* -110.5db */
|
|
||||||
{ 0X00, 0X00, 0X0D, 0X43 }, /* -110.0db */
|
|
||||||
{ 0X00, 0X00, 0X0E, 0X0C }, /* -109.5db */
|
|
||||||
{ 0X00, 0X00, 0X0E, 0XE1 }, /* -109.0db */
|
|
||||||
{ 0X00, 0X00, 0X0F, 0XC3 }, /* -108.5db */
|
|
||||||
{ 0X00, 0X00, 0X10, 0XB2 }, /* -108.0db */
|
|
||||||
{ 0X00, 0X00, 0X11, 0XAF }, /* -107.5db */
|
|
||||||
{ 0X00, 0X00, 0X12, 0XBC }, /* -107.0db */
|
|
||||||
{ 0X00, 0X00, 0X13, 0XD8 }, /* -106.5db */
|
|
||||||
{ 0X00, 0X00, 0X15, 0X05 }, /* -106.0db */
|
|
||||||
{ 0X00, 0X00, 0X16, 0X44 }, /* -105.5db */
|
|
||||||
{ 0X00, 0X00, 0X17, 0X96 }, /* -105.0db */
|
|
||||||
{ 0X00, 0X00, 0X18, 0XFB }, /* -104.5db */
|
|
||||||
{ 0X00, 0X00, 0X1A, 0X76 }, /* -104.0db */
|
|
||||||
{ 0X00, 0X00, 0X1C, 0X08 }, /* -103.5db */
|
|
||||||
{ 0X00, 0X00, 0X1D, 0XB1 }, /* -103.0db */
|
|
||||||
{ 0X00, 0X00, 0X1F, 0X73 }, /* -102.5db */
|
|
||||||
{ 0X00, 0X00, 0X21, 0X51 }, /* -102.0db */
|
|
||||||
{ 0X00, 0X00, 0X23, 0X4A }, /* -101.5db */
|
|
||||||
{ 0X00, 0X00, 0X25, 0X61 }, /* -101.0db */
|
|
||||||
{ 0X00, 0X00, 0X27, 0X98 }, /* -100.5db */
|
|
||||||
{ 0X00, 0X00, 0X29, 0XF1 }, /* -100.0db */
|
|
||||||
{ 0X00, 0X00, 0X2C, 0X6D }, /* -99.5db */
|
|
||||||
{ 0X00, 0X00, 0X2F, 0X0F }, /* -99.0db */
|
|
||||||
{ 0X00, 0X00, 0X31, 0XD9 }, /* -98.5db */
|
|
||||||
{ 0X00, 0X00, 0X34, 0XCD }, /* -98.0db */
|
|
||||||
{ 0X00, 0X00, 0X37, 0XEE }, /* -97.5db */
|
|
||||||
{ 0X00, 0X00, 0X3B, 0X3F }, /* -97.0db */
|
|
||||||
{ 0X00, 0X00, 0X3E, 0XC1 }, /* -96.5db */
|
|
||||||
{ 0X00, 0X00, 0X42, 0X79 }, /* -96.0db */
|
|
||||||
{ 0X00, 0X00, 0X46, 0X6A }, /* -95.5db */
|
|
||||||
{ 0X00, 0X00, 0X4A, 0X96 }, /* -95.0db */
|
|
||||||
{ 0X00, 0X00, 0X4F, 0X01 }, /* -94.5db */
|
|
||||||
{ 0X00, 0X00, 0X53, 0XAF }, /* -94.0db */
|
|
||||||
{ 0X00, 0X00, 0X58, 0XA5 }, /* -93.5db */
|
|
||||||
{ 0X00, 0X00, 0X5D, 0XE6 }, /* -93.0db */
|
|
||||||
{ 0X00, 0X00, 0X63, 0X76 }, /* -92.5db */
|
|
||||||
{ 0X00, 0X00, 0X69, 0X5B }, /* -92.0db */
|
|
||||||
{ 0X00, 0X00, 0X6F, 0X99 }, /* -91.5db */
|
|
||||||
{ 0X00, 0X00, 0X76, 0X36 }, /* -91.0db */
|
|
||||||
{ 0X00, 0X00, 0X7D, 0X37 }, /* -90.5db */
|
|
||||||
{ 0X00, 0X00, 0X84, 0XA2 }, /* -90.0db */
|
|
||||||
{ 0X00, 0X00, 0X8C, 0X7E }, /* -89.5db */
|
|
||||||
{ 0X00, 0X00, 0X94, 0XD1 }, /* -89.0db */
|
|
||||||
{ 0X00, 0X00, 0X9D, 0XA3 }, /* -88.5db */
|
|
||||||
{ 0X00, 0X00, 0XA6, 0XFA }, /* -88.0db */
|
|
||||||
{ 0X00, 0X00, 0XB0, 0XDF }, /* -87.5db */
|
|
||||||
{ 0X00, 0X00, 0XBB, 0X5A }, /* -87.0db */
|
|
||||||
{ 0X00, 0X00, 0XC6, 0X74 }, /* -86.5db */
|
|
||||||
{ 0X00, 0X00, 0XD2, 0X36 }, /* -86.0db */
|
|
||||||
{ 0X00, 0X00, 0XDE, 0XAB }, /* -85.5db */
|
|
||||||
{ 0X00, 0X00, 0XEB, 0XDC }, /* -85.0db */
|
|
||||||
{ 0X00, 0X00, 0XF9, 0XD6 }, /* -84.5db */
|
|
||||||
{ 0X00, 0X01, 0X08, 0XA4 }, /* -84.0db */
|
|
||||||
{ 0X00, 0X01, 0X18, 0X52 }, /* -83.5db */
|
|
||||||
{ 0X00, 0X01, 0X28, 0XEF }, /* -83.0db */
|
|
||||||
{ 0X00, 0X01, 0X3A, 0X87 }, /* -82.5db */
|
|
||||||
{ 0X00, 0X01, 0X4D, 0X2A }, /* -82.0db */
|
|
||||||
{ 0X00, 0X01, 0X60, 0XE8 }, /* -81.5db */
|
|
||||||
{ 0X00, 0X01, 0X75, 0XD1 }, /* -81.0db */
|
|
||||||
{ 0X00, 0X01, 0X8B, 0XF7 }, /* -80.5db */
|
|
||||||
{ 0X00, 0X01, 0XA3, 0X6E }, /* -80.0db */
|
|
||||||
{ 0X00, 0X01, 0XBC, 0X48 }, /* -79.5db */
|
|
||||||
{ 0X00, 0X01, 0XD6, 0X9B }, /* -79.0db */
|
|
||||||
{ 0X00, 0X01, 0XF2, 0X7E }, /* -78.5db */
|
|
||||||
{ 0X00, 0X02, 0X10, 0X08 }, /* -78.0db */
|
|
||||||
{ 0X00, 0X02, 0X2F, 0X51 }, /* -77.5db */
|
|
||||||
{ 0X00, 0X02, 0X50, 0X76 }, /* -77.0db */
|
|
||||||
{ 0X00, 0X02, 0X73, 0X91 }, /* -76.5db */
|
|
||||||
{ 0X00, 0X02, 0X98, 0XC0 }, /* -76.0db */
|
|
||||||
{ 0X00, 0X02, 0XC0, 0X24 }, /* -75.5db */
|
|
||||||
{ 0X00, 0X02, 0XE9, 0XDD }, /* -75.0db */
|
|
||||||
{ 0X00, 0X03, 0X16, 0X0F }, /* -74.5db */
|
|
||||||
{ 0X00, 0X03, 0X44, 0XDF }, /* -74.0db */
|
|
||||||
{ 0X00, 0X03, 0X76, 0X76 }, /* -73.5db */
|
|
||||||
{ 0X00, 0X03, 0XAA, 0XFC }, /* -73.0db */
|
|
||||||
{ 0X00, 0X03, 0XE2, 0XA0 }, /* -72.5db */
|
|
||||||
{ 0X00, 0X04, 0X1D, 0X8F }, /* -72.0db */
|
|
||||||
{ 0X00, 0X04, 0X5B, 0XFD }, /* -71.5db */
|
|
||||||
{ 0X00, 0X04, 0X9E, 0X1D }, /* -71.0db */
|
|
||||||
{ 0X00, 0X04, 0XE4, 0X29 }, /* -70.5db */
|
|
||||||
{ 0X00, 0X05, 0X2E, 0X5A }, /* -70.0db */
|
|
||||||
{ 0X00, 0X05, 0X7C, 0XF2 }, /* -69.5db */
|
|
||||||
{ 0X00, 0X05, 0XD0, 0X31 }, /* -69.0db */
|
|
||||||
{ 0X00, 0X06, 0X28, 0X60 }, /* -68.5db */
|
|
||||||
{ 0X00, 0X06, 0X85, 0XC8 }, /* -68.0db */
|
|
||||||
{ 0X00, 0X06, 0XE8, 0XB9 }, /* -67.5db */
|
|
||||||
{ 0X00, 0X07, 0X51, 0X86 }, /* -67.0db */
|
|
||||||
{ 0X00, 0X07, 0XC0, 0X8A }, /* -66.5db */
|
|
||||||
{ 0X00, 0X08, 0X36, 0X21 }, /* -66.0db */
|
|
||||||
{ 0X00, 0X08, 0XB2, 0XB0 }, /* -65.5db */
|
|
||||||
{ 0X00, 0X09, 0X36, 0XA1 }, /* -65.0db */
|
|
||||||
{ 0X00, 0X09, 0XC2, 0X63 }, /* -64.5db */
|
|
||||||
{ 0X00, 0X0A, 0X56, 0X6D }, /* -64.0db */
|
|
||||||
{ 0X00, 0X0A, 0XF3, 0X3C }, /* -63.5db */
|
|
||||||
{ 0X00, 0X0B, 0X99, 0X56 }, /* -63.0db */
|
|
||||||
{ 0X00, 0X0C, 0X49, 0X48 }, /* -62.5db */
|
|
||||||
{ 0X00, 0X0D, 0X03, 0XA7 }, /* -62.0db */
|
|
||||||
{ 0X00, 0X0D, 0XC9, 0X11 }, /* -61.5db */
|
|
||||||
{ 0X00, 0X0E, 0X9A, 0X2D }, /* -61.0db */
|
|
||||||
{ 0X00, 0X0F, 0X77, 0XAD }, /* -60.5db */
|
|
||||||
{ 0X00, 0X10, 0X62, 0X4D }, /* -60.0db */
|
|
||||||
{ 0X00, 0X11, 0X5A, 0XD5 }, /* -59.5db */
|
|
||||||
{ 0X00, 0X12, 0X62, 0X16 }, /* -59.0db */
|
|
||||||
{ 0X00, 0X13, 0X78, 0XF0 }, /* -58.5db */
|
|
||||||
{ 0X00, 0X14, 0XA0, 0X50 }, /* -58.0db */
|
|
||||||
{ 0X00, 0X15, 0XD9, 0X31 }, /* -57.5db */
|
|
||||||
{ 0X00, 0X17, 0X24, 0X9C }, /* -57.0db */
|
|
||||||
{ 0X00, 0X18, 0X83, 0XAA }, /* -56.5db */
|
|
||||||
{ 0X00, 0X19, 0XF7, 0X86 }, /* -56.0db */
|
|
||||||
{ 0X00, 0X1B, 0X81, 0X6A }, /* -55.5db */
|
|
||||||
{ 0X00, 0X1D, 0X22, 0XA4 }, /* -55.0db */
|
|
||||||
{ 0X00, 0X1E, 0XDC, 0X98 }, /* -54.5db */
|
|
||||||
{ 0X00, 0X20, 0XB0, 0XBC }, /* -54.0db */
|
|
||||||
{ 0X00, 0X22, 0XA0, 0X9D }, /* -53.5db */
|
|
||||||
{ 0X00, 0X24, 0XAD, 0XE0 }, /* -53.0db */
|
|
||||||
{ 0X00, 0X26, 0XDA, 0X43 }, /* -52.5db */
|
|
||||||
{ 0X00, 0X29, 0X27, 0X9D }, /* -52.0db */
|
|
||||||
{ 0X00, 0X2B, 0X97, 0XE3 }, /* -51.5db */
|
|
||||||
{ 0X00, 0X2E, 0X2D, 0X27 }, /* -51.0db */
|
|
||||||
{ 0X00, 0X30, 0XE9, 0X9A }, /* -50.5db */
|
|
||||||
{ 0X00, 0X33, 0XCF, 0X8D }, /* -50.0db */
|
|
||||||
{ 0X00, 0X36, 0XE1, 0X78 }, /* -49.5db */
|
|
||||||
{ 0X00, 0X3A, 0X21, 0XF3 }, /* -49.0db */
|
|
||||||
{ 0X00, 0X3D, 0X93, 0XC3 }, /* -48.5db */
|
|
||||||
{ 0X00, 0X41, 0X39, 0XD3 }, /* -48.0db */
|
|
||||||
{ 0X00, 0X45, 0X17, 0X3B }, /* -47.5db */
|
|
||||||
{ 0X00, 0X49, 0X2F, 0X44 }, /* -47.0db */
|
|
||||||
{ 0X00, 0X4D, 0X85, 0X66 }, /* -46.5db */
|
|
||||||
{ 0X00, 0X52, 0X1D, 0X50 }, /* -46.0db */
|
|
||||||
{ 0X00, 0X56, 0XFA, 0XE8 }, /* -45.5db */
|
|
||||||
{ 0X00, 0X5C, 0X22, 0X4E }, /* -45.0db */
|
|
||||||
{ 0X00, 0X61, 0X97, 0XE1 }, /* -44.5db */
|
|
||||||
{ 0X00, 0X67, 0X60, 0X44 }, /* -44.0db */
|
|
||||||
{ 0X00, 0X6D, 0X80, 0X60 }, /* -43.5db */
|
|
||||||
{ 0X00, 0X73, 0XFD, 0X65 }, /* -43.0db */
|
|
||||||
{ 0X00, 0X7A, 0XDC, 0XD7 }, /* -42.5db */
|
|
||||||
{ 0X00, 0X82, 0X24, 0X8A }, /* -42.0db */
|
|
||||||
{ 0X00, 0X89, 0XDA, 0XAB }, /* -41.5db */
|
|
||||||
{ 0X00, 0X92, 0X05, 0XC6 }, /* -41.0db */
|
|
||||||
{ 0X00, 0X9A, 0XAC, 0XC8 }, /* -40.5db */
|
|
||||||
{ 0X00, 0XA3, 0XD7, 0X0A }, /* -40.0db */
|
|
||||||
{ 0X00, 0XAD, 0X8C, 0X52 }, /* -39.5db */
|
|
||||||
{ 0X00, 0XB7, 0XD4, 0XDD }, /* -39.0db */
|
|
||||||
{ 0X00, 0XC2, 0XB9, 0X65 }, /* -38.5db */
|
|
||||||
{ 0X00, 0XCE, 0X43, 0X28 }, /* -38.0db */
|
|
||||||
{ 0X00, 0XDA, 0X7B, 0XF1 }, /* -37.5db */
|
|
||||||
{ 0X00, 0XE7, 0X6E, 0X1E }, /* -37.0db */
|
|
||||||
{ 0X00, 0XF5, 0X24, 0XAC }, /* -36.5db */
|
|
||||||
{ 0X01, 0X03, 0XAB, 0X3D }, /* -36.0db */
|
|
||||||
{ 0X01, 0X13, 0X0E, 0X24 }, /* -35.5db */
|
|
||||||
{ 0X01, 0X23, 0X5A, 0X71 }, /* -35.0db */
|
|
||||||
{ 0X01, 0X34, 0X9D, 0XF8 }, /* -34.5db */
|
|
||||||
{ 0X01, 0X46, 0XE7, 0X5D }, /* -34.0db */
|
|
||||||
{ 0X01, 0X5A, 0X46, 0X27 }, /* -33.5db */
|
|
||||||
{ 0X01, 0X6E, 0XCA, 0XC5 }, /* -33.0db */
|
|
||||||
{ 0X01, 0X84, 0X86, 0X9F }, /* -32.5db */
|
|
||||||
{ 0X01, 0X9B, 0X8C, 0X27 }, /* -32.0db */
|
|
||||||
{ 0X01, 0XB3, 0XEE, 0XE5 }, /* -31.5db */
|
|
||||||
{ 0X01, 0XCD, 0XC3, 0X8C }, /* -31.0db */
|
|
||||||
{ 0X01, 0XE9, 0X20, 0X05 }, /* -30.5db */
|
|
||||||
{ 0X02, 0X06, 0X1B, 0X89 }, /* -30.0db */
|
|
||||||
{ 0X02, 0X24, 0XCE, 0XB0 }, /* -29.5db */
|
|
||||||
{ 0X02, 0X45, 0X53, 0X85 }, /* -29.0db */
|
|
||||||
{ 0X02, 0X67, 0XC5, 0XA2 }, /* -28.5db */
|
|
||||||
{ 0X02, 0X8C, 0X42, 0X3F }, /* -28.0db */
|
|
||||||
{ 0X02, 0XB2, 0XE8, 0X55 }, /* -27.5db */
|
|
||||||
{ 0X02, 0XDB, 0XD8, 0XAD }, /* -27.0db */
|
|
||||||
{ 0X03, 0X07, 0X36, 0X05 }, /* -26.5db */
|
|
||||||
{ 0X03, 0X35, 0X25, 0X29 }, /* -26.0db */
|
|
||||||
{ 0X03, 0X65, 0XCD, 0X13 }, /* -25.5db */
|
|
||||||
{ 0X03, 0X99, 0X57, 0X0C }, /* -25.0db */
|
|
||||||
{ 0X03, 0XCF, 0XEE, 0XCF }, /* -24.5db */
|
|
||||||
{ 0X04, 0X09, 0XC2, 0XB0 }, /* -24.0db */
|
|
||||||
{ 0X04, 0X47, 0X03, 0XC1 }, /* -23.5db */
|
|
||||||
{ 0X04, 0X87, 0XE5, 0XFB }, /* -23.0db */
|
|
||||||
{ 0X04, 0XCC, 0XA0, 0X6D }, /* -22.5db */
|
|
||||||
{ 0X05, 0X15, 0X6D, 0X68 }, /* -22.0db */
|
|
||||||
{ 0X05, 0X62, 0X8A, 0XB3 }, /* -21.5db */
|
|
||||||
{ 0X05, 0XB4, 0X39, 0XBC }, /* -21.0db */
|
|
||||||
{ 0X06, 0X0A, 0XBF, 0XD4 }, /* -20.5db */
|
|
||||||
{ 0X06, 0X66, 0X66, 0X66 }, /* -20.0db */
|
|
||||||
{ 0X06, 0XC7, 0X7B, 0X36 }, /* -19.5db */
|
|
||||||
{ 0X07, 0X2E, 0X50, 0XA6 }, /* -19.0db */
|
|
||||||
{ 0X07, 0X9B, 0X3D, 0XF6 }, /* -18.5db */
|
|
||||||
{ 0X08, 0X0E, 0X9F, 0X96 }, /* -18.0db */
|
|
||||||
{ 0X08, 0X88, 0XD7, 0X6D }, /* -17.5db */
|
|
||||||
{ 0X09, 0X0A, 0X4D, 0X2F }, /* -17.0db */
|
|
||||||
{ 0X09, 0X93, 0X6E, 0XB8 }, /* -16.5db */
|
|
||||||
{ 0X0A, 0X24, 0XB0, 0X62 }, /* -16.0db */
|
|
||||||
{ 0X0A, 0XBE, 0X8D, 0X70 }, /* -15.5db */
|
|
||||||
{ 0X0B, 0X61, 0X88, 0X71 }, /* -15.0db */
|
|
||||||
{ 0X0C, 0X0E, 0X2B, 0XB0 }, /* -14.5db */
|
|
||||||
{ 0X0C, 0XC5, 0X09, 0XAB }, /* -14.0db */
|
|
||||||
{ 0X0D, 0X86, 0XBD, 0X8D }, /* -13.5db */
|
|
||||||
{ 0X0E, 0X53, 0XEB, 0XB3 }, /* -13.0db */
|
|
||||||
{ 0X0F, 0X2D, 0X42, 0X38 }, /* -12.5db */
|
|
||||||
{ 0X10, 0X13, 0X79, 0X87 }, /* -12.0db */
|
|
||||||
{ 0X11, 0X07, 0X54, 0XF9 }, /* -11.5db */
|
|
||||||
{ 0X12, 0X09, 0XA3, 0X7A }, /* -11.0db */
|
|
||||||
{ 0X13, 0X1B, 0X40, 0X39 }, /* -10.5db */
|
|
||||||
{ 0X14, 0X3D, 0X13, 0X62 }, /* -10.0db */
|
|
||||||
{ 0X15, 0X70, 0X12, 0XE1 }, /* -9.5db */
|
|
||||||
{ 0X16, 0XB5, 0X43, 0X37 }, /* -9.0db */
|
|
||||||
{ 0X18, 0X0D, 0XB8, 0X54 }, /* -8.5db */
|
|
||||||
{ 0X19, 0X7A, 0X96, 0X7F }, /* -8.0db */
|
|
||||||
{ 0X1A, 0XFD, 0X13, 0X54 }, /* -7.5db */
|
|
||||||
{ 0X1C, 0X96, 0X76, 0XC6 }, /* -7.0db */
|
|
||||||
{ 0X1E, 0X48, 0X1C, 0X37 }, /* -6.5db */
|
|
||||||
{ 0X20, 0X13, 0X73, 0X9E }, /* -6.0db */
|
|
||||||
{ 0X21, 0XFA, 0X02, 0XBF }, /* -5.5db */
|
|
||||||
{ 0X23, 0XFD, 0X66, 0X78 }, /* -5.0db */
|
|
||||||
{ 0X26, 0X1F, 0X54, 0X1C }, /* -4.5db */
|
|
||||||
{ 0X28, 0X61, 0X9A, 0XE9 }, /* -4.0db */
|
|
||||||
{ 0X2A, 0XC6, 0X25, 0X91 }, /* -3.5db */
|
|
||||||
{ 0X2D, 0X4E, 0XFB, 0XD5 }, /* -3.0db */
|
|
||||||
{ 0X2F, 0XFE, 0X44, 0X48 }, /* -2.5db */
|
|
||||||
{ 0X32, 0XD6, 0X46, 0X17 }, /* -2.0db */
|
|
||||||
{ 0X35, 0XD9, 0X6B, 0X02 }, /* -1.5db */
|
|
||||||
{ 0X39, 0X0A, 0X41, 0X5F }, /* -1.0db */
|
|
||||||
{ 0X3C, 0X6B, 0X7E, 0X4F }, /* -0.5db */
|
|
||||||
{ 0X40, 0X00, 0X00, 0X00 }, /* 0.0db */
|
|
||||||
{ 0X43, 0XCA, 0XD0, 0X22 }, /* 0.5db */
|
|
||||||
{ 0X47, 0XCF, 0X26, 0X7D }, /* 1.0db */
|
|
||||||
{ 0X4C, 0X10, 0X6B, 0XA5 }, /* 1.5db */
|
|
||||||
{ 0X50, 0X92, 0X3B, 0XE3 }, /* 2.0db */
|
|
||||||
{ 0X55, 0X58, 0X6A, 0X46 }, /* 2.5db */
|
|
||||||
{ 0X5A, 0X67, 0X03, 0XDF }, /* 3.0db */
|
|
||||||
{ 0X5F, 0XC2, 0X53, 0X32 }, /* 3.5db */
|
|
||||||
{ 0X65, 0X6E, 0XE3, 0XDB }, /* 4.0db */
|
|
||||||
{ 0X6B, 0X71, 0X86, 0X68 }, /* 4.5db */
|
|
||||||
{ 0X71, 0XCF, 0X54, 0X71 }, /* 5.0db */
|
|
||||||
{ 0X78, 0X8D, 0XB4, 0XE9 }, /* 5.5db */
|
|
||||||
{ 0XFF, 0XFF, 0XFF, 0XFF }, /* 6.0db */
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,12 +49,59 @@
|
|||||||
/*I2C Checksum */
|
/*I2C Checksum */
|
||||||
#define TASDEVICE_I2CChecksum TASDEVICE_REG(0x0, 0x0, 0x7E)
|
#define TASDEVICE_I2CChecksum TASDEVICE_REG(0x0, 0x0, 0x7E)
|
||||||
|
|
||||||
|
/* XM_340 */
|
||||||
|
#define TASDEVICE_XM_A1_REG TASDEVICE_REG(0x64, 0x63, 0x3c)
|
||||||
|
/* XM_341 */
|
||||||
|
#define TASDEVICE_XM_A2_REG TASDEVICE_REG(0x64, 0x63, 0x38)
|
||||||
|
|
||||||
/* Volume control */
|
/* Volume control */
|
||||||
#define TAS2563_DVC_LVL TASDEVICE_REG(0x00, 0x02, 0x0C)
|
#define TAS2563_DVC_LVL TASDEVICE_REG(0x00, 0x02, 0x0C)
|
||||||
#define TAS2781_DVC_LVL TASDEVICE_REG(0x0, 0x0, 0x1A)
|
#define TAS2781_DVC_LVL TASDEVICE_REG(0x0, 0x0, 0x1A)
|
||||||
#define TAS2781_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x03)
|
#define TAS2781_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x03)
|
||||||
#define TAS2781_AMP_LEVEL_MASK GENMASK(5, 1)
|
#define TAS2781_AMP_LEVEL_MASK GENMASK(5, 1)
|
||||||
|
|
||||||
|
#define TAS2563_IDLE TASDEVICE_REG(0x00, 0x00, 0x3e)
|
||||||
|
#define TAS2563_PRM_R0_REG TASDEVICE_REG(0x00, 0x0f, 0x34)
|
||||||
|
|
||||||
|
#define TAS2563_RUNTIME_RE_REG_TF TASDEVICE_REG(0x64, 0x02, 0x70)
|
||||||
|
#define TAS2563_RUNTIME_RE_REG TASDEVICE_REG(0x64, 0x02, 0x48)
|
||||||
|
|
||||||
|
#define TAS2563_PRM_ENFF_REG TASDEVICE_REG(0x00, 0x0d, 0x54)
|
||||||
|
#define TAS2563_PRM_DISTCK_REG TASDEVICE_REG(0x00, 0x0d, 0x58)
|
||||||
|
#define TAS2563_PRM_TE_SCTHR_REG TASDEVICE_REG(0x00, 0x0f, 0x60)
|
||||||
|
#define TAS2563_PRM_PLT_FLAG_REG TASDEVICE_REG(0x00, 0x0d, 0x74)
|
||||||
|
#define TAS2563_PRM_SINEGAIN_REG TASDEVICE_REG(0x00, 0x0d, 0x7c)
|
||||||
|
/* prm_Int_B0 */
|
||||||
|
#define TAS2563_TE_TA1_REG TASDEVICE_REG(0x00, 0x10, 0x0c)
|
||||||
|
/* prm_Int_A1 */
|
||||||
|
#define TAS2563_TE_TA1_AT_REG TASDEVICE_REG(0x00, 0x10, 0x10)
|
||||||
|
/* prm_TE_Beta */
|
||||||
|
#define TAS2563_TE_TA2_REG TASDEVICE_REG(0x00, 0x0f, 0x64)
|
||||||
|
/* prm_TE_Beta1 */
|
||||||
|
#define TAS2563_TE_AT_REG TASDEVICE_REG(0x00, 0x0f, 0x68)
|
||||||
|
/* prm_TE_1_Beta1 */
|
||||||
|
#define TAS2563_TE_DT_REG TASDEVICE_REG(0x00, 0x0f, 0x70)
|
||||||
|
|
||||||
|
#define TAS2781_PRM_INT_MASK_REG TASDEVICE_REG(0x00, 0x00, 0x3b)
|
||||||
|
#define TAS2781_PRM_CLK_CFG_REG TASDEVICE_REG(0x00, 0x00, 0x5c)
|
||||||
|
#define TAS2781_PRM_RSVD_REG TASDEVICE_REG(0x00, 0x01, 0x19)
|
||||||
|
#define TAS2781_PRM_TEST_57_REG TASDEVICE_REG(0x00, 0xfd, 0x39)
|
||||||
|
#define TAS2781_PRM_TEST_62_REG TASDEVICE_REG(0x00, 0xfd, 0x3e)
|
||||||
|
#define TAS2781_PRM_PVDD_UVLO_REG TASDEVICE_REG(0x00, 0x00, 0x71)
|
||||||
|
#define TAS2781_PRM_CHNL_0_REG TASDEVICE_REG(0x00, 0x00, 0x03)
|
||||||
|
#define TAS2781_PRM_NG_CFG0_REG TASDEVICE_REG(0x00, 0x00, 0x35)
|
||||||
|
#define TAS2781_PRM_IDLE_CH_DET_REG TASDEVICE_REG(0x00, 0x00, 0x66)
|
||||||
|
#define TAS2781_PRM_PLT_FLAG_REG TASDEVICE_REG(0x00, 0x14, 0x38)
|
||||||
|
#define TAS2781_PRM_SINEGAIN_REG TASDEVICE_REG(0x00, 0x14, 0x40)
|
||||||
|
#define TAS2781_PRM_SINEGAIN2_REG TASDEVICE_REG(0x00, 0x14, 0x44)
|
||||||
|
|
||||||
|
#define TAS2781_TEST_UNLOCK_REG TASDEVICE_REG(0x00, 0xFD, 0x0D)
|
||||||
|
#define TAS2781_TEST_PAGE_UNLOCK 0x0D
|
||||||
|
|
||||||
|
#define TAS2781_RUNTIME_LATCH_RE_REG TASDEVICE_REG(0x00, 0x00, 0x49)
|
||||||
|
#define TAS2781_RUNTIME_RE_REG_TF TASDEVICE_REG(0x64, 0x62, 0x48)
|
||||||
|
#define TAS2781_RUNTIME_RE_REG TASDEVICE_REG(0x64, 0x63, 0x44)
|
||||||
|
|
||||||
#define TASDEVICE_CMD_SING_W 0x1
|
#define TASDEVICE_CMD_SING_W 0x1
|
||||||
#define TASDEVICE_CMD_BURST 0x2
|
#define TASDEVICE_CMD_BURST 0x2
|
||||||
#define TASDEVICE_CMD_DELAY 0x3
|
#define TASDEVICE_CMD_DELAY 0x3
|
||||||
@ -70,7 +117,15 @@ enum device_catlog_id {
|
|||||||
OTHERS
|
OTHERS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bulk_reg_val {
|
||||||
|
int reg;
|
||||||
|
unsigned char val[4];
|
||||||
|
unsigned char val_len;
|
||||||
|
bool is_locked;
|
||||||
|
};
|
||||||
|
|
||||||
struct tasdevice {
|
struct tasdevice {
|
||||||
|
struct bulk_reg_val *cali_data_backup;
|
||||||
struct tasdevice_fw *cali_data_fmw;
|
struct tasdevice_fw *cali_data_fmw;
|
||||||
unsigned int dev_addr;
|
unsigned int dev_addr;
|
||||||
unsigned int err_code;
|
unsigned int err_code;
|
||||||
@ -81,19 +136,23 @@ struct tasdevice {
|
|||||||
bool is_loaderr;
|
bool is_loaderr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tasdevice_irqinfo {
|
struct cali_reg {
|
||||||
int irq_gpio;
|
unsigned int r0_reg;
|
||||||
int irq;
|
unsigned int r0_low_reg;
|
||||||
|
unsigned int invr0_reg;
|
||||||
|
unsigned int pow_reg;
|
||||||
|
unsigned int tlimit_reg;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct calidata {
|
struct calidata {
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
unsigned long total_sz;
|
unsigned long total_sz;
|
||||||
|
struct cali_reg cali_reg_array;
|
||||||
|
unsigned int cali_dat_sz_per_dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tasdevice_priv {
|
struct tasdevice_priv {
|
||||||
struct tasdevice tasdevice[TASDEVICE_MAX_CHANNELS];
|
struct tasdevice tasdevice[TASDEVICE_MAX_CHANNELS];
|
||||||
struct tasdevice_irqinfo irq_info;
|
|
||||||
struct tasdevice_rca rcabin;
|
struct tasdevice_rca rcabin;
|
||||||
struct calidata cali_data;
|
struct calidata cali_data;
|
||||||
struct tasdevice_fw *fmw;
|
struct tasdevice_fw *fmw;
|
||||||
@ -115,6 +174,7 @@ struct tasdevice_priv {
|
|||||||
unsigned int chip_id;
|
unsigned int chip_id;
|
||||||
unsigned int sysclk;
|
unsigned int sysclk;
|
||||||
|
|
||||||
|
int irq;
|
||||||
int cur_prog;
|
int cur_prog;
|
||||||
int cur_conf;
|
int cur_conf;
|
||||||
int fw_state;
|
int fw_state;
|
||||||
@ -124,6 +184,7 @@ struct tasdevice_priv {
|
|||||||
bool force_fwload_status;
|
bool force_fwload_status;
|
||||||
bool playback_started;
|
bool playback_started;
|
||||||
bool isacpi;
|
bool isacpi;
|
||||||
|
bool is_user_space_calidata;
|
||||||
unsigned int global_addr;
|
unsigned int global_addr;
|
||||||
|
|
||||||
int (*fw_parse_variable_header)(struct tasdevice_priv *tas_priv,
|
int (*fw_parse_variable_header)(struct tasdevice_priv *tas_priv,
|
||||||
@ -150,6 +211,8 @@ int tasdevice_init(struct tasdevice_priv *tas_priv);
|
|||||||
void tasdevice_remove(struct tasdevice_priv *tas_priv);
|
void tasdevice_remove(struct tasdevice_priv *tas_priv);
|
||||||
int tasdevice_save_calibration(struct tasdevice_priv *tas_priv);
|
int tasdevice_save_calibration(struct tasdevice_priv *tas_priv);
|
||||||
void tasdevice_apply_calibration(struct tasdevice_priv *tas_priv);
|
void tasdevice_apply_calibration(struct tasdevice_priv *tas_priv);
|
||||||
|
int tasdev_chn_switch(struct tasdevice_priv *tas_priv,
|
||||||
|
unsigned short chn);
|
||||||
int tasdevice_dev_read(struct tasdevice_priv *tas_priv,
|
int tasdevice_dev_read(struct tasdevice_priv *tas_priv,
|
||||||
unsigned short chn, unsigned int reg, unsigned int *value);
|
unsigned short chn, unsigned int reg, unsigned int *value);
|
||||||
int tasdevice_dev_write(struct tasdevice_priv *tas_priv,
|
int tasdevice_dev_write(struct tasdevice_priv *tas_priv,
|
||||||
|
@ -13,6 +13,15 @@ struct snd_ump_ops;
|
|||||||
struct ump_cvt_to_ump;
|
struct ump_cvt_to_ump;
|
||||||
struct snd_seq_ump_ops;
|
struct snd_seq_ump_ops;
|
||||||
|
|
||||||
|
struct snd_ump_group {
|
||||||
|
int group; /* group index (0-based) */
|
||||||
|
unsigned int dir_bits; /* directions */
|
||||||
|
bool active; /* activeness */
|
||||||
|
bool valid; /* valid group (referred by blocks) */
|
||||||
|
bool is_midi1; /* belongs to a MIDI1 FB */
|
||||||
|
char name[64]; /* group name */
|
||||||
|
};
|
||||||
|
|
||||||
struct snd_ump_endpoint {
|
struct snd_ump_endpoint {
|
||||||
struct snd_rawmidi core; /* raw UMP access */
|
struct snd_rawmidi core; /* raw UMP access */
|
||||||
|
|
||||||
@ -41,6 +50,8 @@ struct snd_ump_endpoint {
|
|||||||
|
|
||||||
struct mutex open_mutex;
|
struct mutex open_mutex;
|
||||||
|
|
||||||
|
struct snd_ump_group groups[SNDRV_UMP_MAX_GROUPS]; /* table of groups */
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
|
#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
|
||||||
spinlock_t legacy_locks[2];
|
spinlock_t legacy_locks[2];
|
||||||
struct snd_rawmidi *legacy_rmidi;
|
struct snd_rawmidi *legacy_rmidi;
|
||||||
@ -112,6 +123,7 @@ static inline int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
|
|||||||
|
|
||||||
int snd_ump_receive_ump_val(struct snd_ump_endpoint *ump, u32 val);
|
int snd_ump_receive_ump_val(struct snd_ump_endpoint *ump, u32 val);
|
||||||
int snd_ump_switch_protocol(struct snd_ump_endpoint *ump, unsigned int protocol);
|
int snd_ump_switch_protocol(struct snd_ump_endpoint *ump, unsigned int protocol);
|
||||||
|
void snd_ump_update_group_attrs(struct snd_ump_endpoint *ump);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some definitions for UMP
|
* Some definitions for UMP
|
||||||
|
@ -155,7 +155,6 @@ struct vx_core {
|
|||||||
unsigned int chip_status;
|
unsigned int chip_status;
|
||||||
unsigned int pcm_running;
|
unsigned int pcm_running;
|
||||||
|
|
||||||
struct device *dev;
|
|
||||||
struct snd_hwdep *hwdep;
|
struct snd_hwdep *hwdep;
|
||||||
|
|
||||||
struct vx_rmh irq_rmh; /* RMH used in interrupts */
|
struct vx_rmh irq_rmh; /* RMH used in interrupts */
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <linux/ktime.h>
|
#include <linux/ktime.h>
|
||||||
#include <linux/tracepoint.h>
|
#include <linux/tracepoint.h>
|
||||||
#include <sound/jack.h>
|
#include <sound/jack.h>
|
||||||
|
#include <sound/pcm.h>
|
||||||
|
|
||||||
#define DAPM_DIRECT "(direct)"
|
#define DAPM_DIRECT "(direct)"
|
||||||
#define DAPM_ARROW(dir) (((dir) == SND_SOC_DAPM_DIR_OUT) ? "->" : "<-")
|
#define DAPM_ARROW(dir) (((dir) == SND_SOC_DAPM_DIR_OUT) ? "->" : "<-")
|
||||||
@ -212,7 +213,7 @@ TRACE_EVENT(snd_soc_dapm_connected,
|
|||||||
),
|
),
|
||||||
|
|
||||||
TP_printk("%s: found %d paths",
|
TP_printk("%s: found %d paths",
|
||||||
__entry->stream ? "capture" : "playback", __entry->paths)
|
snd_pcm_direction_name(__entry->stream), __entry->paths)
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(snd_soc_jack_irq,
|
TRACE_EVENT(snd_soc_jack_irq,
|
||||||
|
@ -461,6 +461,8 @@ struct snd_seq_remove_events {
|
|||||||
#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1)
|
#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1)
|
||||||
#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2)
|
#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2)
|
||||||
|
|
||||||
|
#define SNDRV_SEQ_PORT_FLG_IS_MIDI1 (1<<3) /* Keep MIDI 1.0 protocol */
|
||||||
|
|
||||||
/* port direction */
|
/* port direction */
|
||||||
#define SNDRV_SEQ_PORT_DIR_UNKNOWN 0
|
#define SNDRV_SEQ_PORT_DIR_UNKNOWN 0
|
||||||
#define SNDRV_SEQ_PORT_DIR_INPUT 1
|
#define SNDRV_SEQ_PORT_DIR_INPUT 1
|
||||||
|
@ -869,7 +869,7 @@ struct snd_ump_block_info {
|
|||||||
* Timer section - /dev/snd/timer
|
* Timer section - /dev/snd/timer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7)
|
#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 8)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SNDRV_TIMER_CLASS_NONE = -1,
|
SNDRV_TIMER_CLASS_NONE = -1,
|
||||||
@ -894,6 +894,7 @@ enum {
|
|||||||
#define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */
|
#define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */
|
||||||
#define SNDRV_TIMER_GLOBAL_HPET 2
|
#define SNDRV_TIMER_GLOBAL_HPET 2
|
||||||
#define SNDRV_TIMER_GLOBAL_HRTIMER 3
|
#define SNDRV_TIMER_GLOBAL_HRTIMER 3
|
||||||
|
#define SNDRV_TIMER_GLOBAL_UDRIVEN 4
|
||||||
|
|
||||||
/* info flags */
|
/* info flags */
|
||||||
#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
|
#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
|
||||||
@ -974,6 +975,18 @@ struct snd_timer_status {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure describes the userspace-driven timer. Such timers are purely virtual,
|
||||||
|
* and can only be triggered from software (for instance, by userspace application).
|
||||||
|
*/
|
||||||
|
struct snd_timer_uinfo {
|
||||||
|
/* To pretend being a normal timer, we need to know the resolution in ns. */
|
||||||
|
__u64 resolution;
|
||||||
|
int fd;
|
||||||
|
unsigned int id;
|
||||||
|
unsigned char reserved[16];
|
||||||
|
};
|
||||||
|
|
||||||
#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
|
#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
|
||||||
#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
|
#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
|
||||||
#define SNDRV_TIMER_IOCTL_TREAD_OLD _IOW('T', 0x02, int)
|
#define SNDRV_TIMER_IOCTL_TREAD_OLD _IOW('T', 0x02, int)
|
||||||
@ -990,6 +1003,8 @@ struct snd_timer_status {
|
|||||||
#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
|
#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
|
||||||
#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
|
#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
|
||||||
#define SNDRV_TIMER_IOCTL_TREAD64 _IOW('T', 0xa4, int)
|
#define SNDRV_TIMER_IOCTL_TREAD64 _IOW('T', 0xa4, int)
|
||||||
|
#define SNDRV_TIMER_IOCTL_CREATE _IOWR('T', 0xa5, struct snd_timer_uinfo)
|
||||||
|
#define SNDRV_TIMER_IOCTL_TRIGGER _IO('T', 0xa6)
|
||||||
|
|
||||||
#if __BITS_PER_LONG == 64
|
#if __BITS_PER_LONG == 64
|
||||||
#define SNDRV_TIMER_IOCTL_TREAD SNDRV_TIMER_IOCTL_TREAD_OLD
|
#define SNDRV_TIMER_IOCTL_TREAD SNDRV_TIMER_IOCTL_TREAD_OLD
|
||||||
|
@ -335,7 +335,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
|
|||||||
|
|
||||||
static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match)
|
static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match)
|
||||||
{
|
{
|
||||||
struct device_node *np = NULL;
|
struct device_node *np;
|
||||||
int got = 0, err;
|
int got = 0, err;
|
||||||
struct i2sbus_control *control = NULL;
|
struct i2sbus_control *control = NULL;
|
||||||
|
|
||||||
@ -347,7 +347,7 @@ static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((np = of_get_next_child(dev->ofdev.dev.of_node, np))) {
|
for_each_child_of_node(dev->ofdev.dev.of_node, np) {
|
||||||
if (of_device_is_compatible(np, "i2sbus") ||
|
if (of_device_is_compatible(np, "i2sbus") ||
|
||||||
of_device_is_compatible(np, "i2s-modem")) {
|
of_device_is_compatible(np, "i2s-modem")) {
|
||||||
got += i2sbus_add_dev(dev, control, np);
|
got += i2sbus_add_dev(dev, control, np);
|
||||||
|
@ -175,15 +175,6 @@ config SND_VERBOSE_PROCFS
|
|||||||
useful information to developers when a problem occurs). On the
|
useful information to developers when a problem occurs). On the
|
||||||
other side, it makes the ALSA subsystem larger.
|
other side, it makes the ALSA subsystem larger.
|
||||||
|
|
||||||
config SND_VERBOSE_PRINTK
|
|
||||||
bool "Verbose printk"
|
|
||||||
help
|
|
||||||
Say Y here to enable verbose log messages. These messages
|
|
||||||
will help to identify source file and position containing
|
|
||||||
printed messages.
|
|
||||||
|
|
||||||
You don't need this unless you're debugging ALSA.
|
|
||||||
|
|
||||||
config SND_CTL_FAST_LOOKUP
|
config SND_CTL_FAST_LOOKUP
|
||||||
bool "Fast lookup of control elements" if EXPERT
|
bool "Fast lookup of control elements" if EXPERT
|
||||||
default y
|
default y
|
||||||
@ -251,6 +242,16 @@ config SND_JACK_INJECTION_DEBUG
|
|||||||
Say Y if you are debugging via jack injection interface.
|
Say Y if you are debugging via jack injection interface.
|
||||||
If unsure select "N".
|
If unsure select "N".
|
||||||
|
|
||||||
|
config SND_UTIMER
|
||||||
|
bool "Enable support for userspace-controlled virtual timers"
|
||||||
|
depends on SND_TIMER
|
||||||
|
help
|
||||||
|
Say Y to enable the support of userspace-controlled timers. These
|
||||||
|
timers are purely virtual, and they are supposed to be triggered
|
||||||
|
from userspace. They could be quite useful when synchronizing the
|
||||||
|
sound timing with userspace applications (for instance, when sending
|
||||||
|
data through snd-aloop).
|
||||||
|
|
||||||
config SND_VMASTER
|
config SND_VMASTER
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
@ -581,7 +581,7 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
|
|||||||
*/
|
*/
|
||||||
params = memdup_user((void __user *)arg, sizeof(*params));
|
params = memdup_user((void __user *)arg, sizeof(*params));
|
||||||
if (IS_ERR(params))
|
if (IS_ERR(params))
|
||||||
return PTR_ERR(no_free_ptr(params));
|
return PTR_ERR(params);
|
||||||
|
|
||||||
retval = snd_compress_check_input(params);
|
retval = snd_compress_check_input(params);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -79,7 +79,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
|
|||||||
ctl->preferred_subdevice[i] = -1;
|
ctl->preferred_subdevice[i] = -1;
|
||||||
ctl->pid = get_pid(task_pid(current));
|
ctl->pid = get_pid(task_pid(current));
|
||||||
file->private_data = ctl;
|
file->private_data = ctl;
|
||||||
scoped_guard(write_lock_irqsave, &card->ctl_files_rwlock)
|
scoped_guard(write_lock_irqsave, &card->controls_rwlock)
|
||||||
list_add_tail(&ctl->list, &card->ctl_files);
|
list_add_tail(&ctl->list, &card->ctl_files);
|
||||||
snd_card_unref(card);
|
snd_card_unref(card);
|
||||||
return 0;
|
return 0;
|
||||||
@ -117,7 +117,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
|
|||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
card = ctl->card;
|
card = ctl->card;
|
||||||
|
|
||||||
scoped_guard(write_lock_irqsave, &card->ctl_files_rwlock)
|
scoped_guard(write_lock_irqsave, &card->controls_rwlock)
|
||||||
list_del(&ctl->list);
|
list_del(&ctl->list);
|
||||||
|
|
||||||
scoped_guard(rwsem_write, &card->controls_rwsem) {
|
scoped_guard(rwsem_write, &card->controls_rwsem) {
|
||||||
@ -157,7 +157,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
|
|||||||
if (card->shutdown)
|
if (card->shutdown)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
guard(read_lock_irqsave)(&card->ctl_files_rwlock);
|
guard(read_lock_irqsave)(&card->controls_rwlock);
|
||||||
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
|
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
|
||||||
card->mixer_oss_change_count++;
|
card->mixer_oss_change_count++;
|
||||||
#endif
|
#endif
|
||||||
@ -237,11 +237,11 @@ static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count,
|
|||||||
if (!*kctl)
|
if (!*kctl)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
(*kctl)->count = count;
|
||||||
for (idx = 0; idx < count; idx++) {
|
for (idx = 0; idx < count; idx++) {
|
||||||
(*kctl)->vd[idx].access = access;
|
(*kctl)->vd[idx].access = access;
|
||||||
(*kctl)->vd[idx].owner = file;
|
(*kctl)->vd[idx].owner = file;
|
||||||
}
|
}
|
||||||
(*kctl)->count = count;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -470,7 +470,7 @@ static int __snd_ctl_add_replace(struct snd_card *card,
|
|||||||
if (id.index > UINT_MAX - kcontrol->count)
|
if (id.index > UINT_MAX - kcontrol->count)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
old = snd_ctl_find_id_locked(card, &id);
|
old = snd_ctl_find_id(card, &id);
|
||||||
if (!old) {
|
if (!old) {
|
||||||
if (mode == CTL_REPLACE)
|
if (mode == CTL_REPLACE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -491,10 +491,12 @@ static int __snd_ctl_add_replace(struct snd_card *card,
|
|||||||
if (snd_ctl_find_hole(card, kcontrol->count) < 0)
|
if (snd_ctl_find_hole(card, kcontrol->count) < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
list_add_tail(&kcontrol->list, &card->controls);
|
scoped_guard(write_lock_irq, &card->controls_rwlock) {
|
||||||
card->controls_count += kcontrol->count;
|
list_add_tail(&kcontrol->list, &card->controls);
|
||||||
kcontrol->id.numid = card->last_numid + 1;
|
card->controls_count += kcontrol->count;
|
||||||
card->last_numid += kcontrol->count;
|
kcontrol->id.numid = card->last_numid + 1;
|
||||||
|
card->last_numid += kcontrol->count;
|
||||||
|
}
|
||||||
|
|
||||||
add_hash_entries(card, kcontrol);
|
add_hash_entries(card, kcontrol);
|
||||||
|
|
||||||
@ -579,12 +581,15 @@ static int __snd_ctl_remove(struct snd_card *card,
|
|||||||
|
|
||||||
if (snd_BUG_ON(!card || !kcontrol))
|
if (snd_BUG_ON(!card || !kcontrol))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
list_del(&kcontrol->list);
|
|
||||||
|
|
||||||
if (remove_hash)
|
if (remove_hash)
|
||||||
remove_hash_entries(card, kcontrol);
|
remove_hash_entries(card, kcontrol);
|
||||||
|
|
||||||
card->controls_count -= kcontrol->count;
|
scoped_guard(write_lock_irq, &card->controls_rwlock) {
|
||||||
|
list_del(&kcontrol->list);
|
||||||
|
card->controls_count -= kcontrol->count;
|
||||||
|
}
|
||||||
|
|
||||||
for (idx = 0; idx < kcontrol->count; idx++)
|
for (idx = 0; idx < kcontrol->count; idx++)
|
||||||
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_REMOVE, kcontrol, idx);
|
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_REMOVE, kcontrol, idx);
|
||||||
snd_ctl_free_one(kcontrol);
|
snd_ctl_free_one(kcontrol);
|
||||||
@ -634,7 +639,7 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
|
|||||||
struct snd_kcontrol *kctl;
|
struct snd_kcontrol *kctl;
|
||||||
|
|
||||||
guard(rwsem_write)(&card->controls_rwsem);
|
guard(rwsem_write)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, id);
|
kctl = snd_ctl_find_id(card, id);
|
||||||
if (kctl == NULL)
|
if (kctl == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
return snd_ctl_remove_locked(card, kctl);
|
return snd_ctl_remove_locked(card, kctl);
|
||||||
@ -659,7 +664,7 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
|
|||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
guard(rwsem_write)(&card->controls_rwsem);
|
guard(rwsem_write)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, id);
|
kctl = snd_ctl_find_id(card, id);
|
||||||
if (kctl == NULL)
|
if (kctl == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER))
|
if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER))
|
||||||
@ -691,7 +696,7 @@ int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
down_write(&card->controls_rwsem);
|
down_write(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, id);
|
kctl = snd_ctl_find_id(card, id);
|
||||||
if (kctl == NULL) {
|
if (kctl == NULL) {
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@ -745,7 +750,7 @@ int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
|
|||||||
int saved_numid;
|
int saved_numid;
|
||||||
|
|
||||||
guard(rwsem_write)(&card->controls_rwsem);
|
guard(rwsem_write)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, src_id);
|
kctl = snd_ctl_find_id(card, src_id);
|
||||||
if (kctl == NULL)
|
if (kctl == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
saved_numid = kctl->id.numid;
|
saved_numid = kctl->id.numid;
|
||||||
@ -787,6 +792,7 @@ snd_ctl_find_numid_slow(struct snd_card *card, unsigned int numid)
|
|||||||
{
|
{
|
||||||
struct snd_kcontrol *kctl;
|
struct snd_kcontrol *kctl;
|
||||||
|
|
||||||
|
guard(read_lock_irqsave)(&card->controls_rwlock);
|
||||||
list_for_each_entry(kctl, &card->controls, list) {
|
list_for_each_entry(kctl, &card->controls, list) {
|
||||||
if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid)
|
if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid)
|
||||||
return kctl;
|
return kctl;
|
||||||
@ -795,32 +801,6 @@ snd_ctl_find_numid_slow(struct snd_card *card, unsigned int numid)
|
|||||||
}
|
}
|
||||||
#endif /* !CONFIG_SND_CTL_FAST_LOOKUP */
|
#endif /* !CONFIG_SND_CTL_FAST_LOOKUP */
|
||||||
|
|
||||||
/**
|
|
||||||
* snd_ctl_find_numid_locked - find the control instance with the given number-id
|
|
||||||
* @card: the card instance
|
|
||||||
* @numid: the number-id to search
|
|
||||||
*
|
|
||||||
* Finds the control instance with the given number-id from the card.
|
|
||||||
*
|
|
||||||
* The caller must down card->controls_rwsem before calling this function
|
|
||||||
* (if the race condition can happen).
|
|
||||||
*
|
|
||||||
* Return: The pointer of the instance if found, or %NULL if not.
|
|
||||||
*/
|
|
||||||
struct snd_kcontrol *
|
|
||||||
snd_ctl_find_numid_locked(struct snd_card *card, unsigned int numid)
|
|
||||||
{
|
|
||||||
if (snd_BUG_ON(!card || !numid))
|
|
||||||
return NULL;
|
|
||||||
lockdep_assert_held(&card->controls_rwsem);
|
|
||||||
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
|
|
||||||
return xa_load(&card->ctl_numids, numid);
|
|
||||||
#else
|
|
||||||
return snd_ctl_find_numid_slow(card, numid);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(snd_ctl_find_numid_locked);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_ctl_find_numid - find the control instance with the given number-id
|
* snd_ctl_find_numid - find the control instance with the given number-id
|
||||||
* @card: the card instance
|
* @card: the card instance
|
||||||
@ -830,54 +810,22 @@ EXPORT_SYMBOL(snd_ctl_find_numid_locked);
|
|||||||
*
|
*
|
||||||
* Return: The pointer of the instance if found, or %NULL if not.
|
* Return: The pointer of the instance if found, or %NULL if not.
|
||||||
*
|
*
|
||||||
* Note that this function takes card->controls_rwsem lock internally.
|
* Note that this function takes card->controls_rwlock lock internally.
|
||||||
*/
|
*/
|
||||||
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card,
|
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card,
|
||||||
unsigned int numid)
|
unsigned int numid)
|
||||||
{
|
{
|
||||||
guard(rwsem_read)(&card->controls_rwsem);
|
if (snd_BUG_ON(!card || !numid))
|
||||||
return snd_ctl_find_numid_locked(card, numid);
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
|
||||||
|
return xa_load(&card->ctl_numids, numid);
|
||||||
|
#else
|
||||||
|
return snd_ctl_find_numid_slow(card, numid);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(snd_ctl_find_numid);
|
EXPORT_SYMBOL(snd_ctl_find_numid);
|
||||||
|
|
||||||
/**
|
|
||||||
* snd_ctl_find_id_locked - find the control instance with the given id
|
|
||||||
* @card: the card instance
|
|
||||||
* @id: the id to search
|
|
||||||
*
|
|
||||||
* Finds the control instance with the given id from the card.
|
|
||||||
*
|
|
||||||
* The caller must down card->controls_rwsem before calling this function
|
|
||||||
* (if the race condition can happen).
|
|
||||||
*
|
|
||||||
* Return: The pointer of the instance if found, or %NULL if not.
|
|
||||||
*/
|
|
||||||
struct snd_kcontrol *snd_ctl_find_id_locked(struct snd_card *card,
|
|
||||||
const struct snd_ctl_elem_id *id)
|
|
||||||
{
|
|
||||||
struct snd_kcontrol *kctl;
|
|
||||||
|
|
||||||
if (snd_BUG_ON(!card || !id))
|
|
||||||
return NULL;
|
|
||||||
lockdep_assert_held(&card->controls_rwsem);
|
|
||||||
if (id->numid != 0)
|
|
||||||
return snd_ctl_find_numid_locked(card, id->numid);
|
|
||||||
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
|
|
||||||
kctl = xa_load(&card->ctl_hash, get_ctl_id_hash(id));
|
|
||||||
if (kctl && elem_id_matches(kctl, id))
|
|
||||||
return kctl;
|
|
||||||
if (!card->ctl_hash_collision)
|
|
||||||
return NULL; /* we can rely on only hash table */
|
|
||||||
#endif
|
|
||||||
/* no matching in hash table - try all as the last resort */
|
|
||||||
list_for_each_entry(kctl, &card->controls, list)
|
|
||||||
if (elem_id_matches(kctl, id))
|
|
||||||
return kctl;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(snd_ctl_find_id_locked);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_ctl_find_id - find the control instance with the given id
|
* snd_ctl_find_id - find the control instance with the given id
|
||||||
* @card: the card instance
|
* @card: the card instance
|
||||||
@ -887,13 +835,32 @@ EXPORT_SYMBOL(snd_ctl_find_id_locked);
|
|||||||
*
|
*
|
||||||
* Return: The pointer of the instance if found, or %NULL if not.
|
* Return: The pointer of the instance if found, or %NULL if not.
|
||||||
*
|
*
|
||||||
* Note that this function takes card->controls_rwsem lock internally.
|
* Note that this function takes card->controls_rwlock lock internally.
|
||||||
*/
|
*/
|
||||||
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
|
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
|
||||||
const struct snd_ctl_elem_id *id)
|
const struct snd_ctl_elem_id *id)
|
||||||
{
|
{
|
||||||
guard(rwsem_read)(&card->controls_rwsem);
|
struct snd_kcontrol *kctl;
|
||||||
return snd_ctl_find_id_locked(card, id);
|
|
||||||
|
if (snd_BUG_ON(!card || !id))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (id->numid != 0)
|
||||||
|
return snd_ctl_find_numid(card, id->numid);
|
||||||
|
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
|
||||||
|
kctl = xa_load(&card->ctl_hash, get_ctl_id_hash(id));
|
||||||
|
if (kctl && elem_id_matches(kctl, id))
|
||||||
|
return kctl;
|
||||||
|
if (!card->ctl_hash_collision)
|
||||||
|
return NULL; /* we can rely on only hash table */
|
||||||
|
#endif
|
||||||
|
/* no matching in hash table - try all as the last resort */
|
||||||
|
guard(read_lock_irqsave)(&card->controls_rwlock);
|
||||||
|
list_for_each_entry(kctl, &card->controls, list)
|
||||||
|
if (elem_id_matches(kctl, id))
|
||||||
|
return kctl;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(snd_ctl_find_id);
|
EXPORT_SYMBOL(snd_ctl_find_id);
|
||||||
|
|
||||||
@ -1167,10 +1134,7 @@ static int __snd_ctl_elem_info(struct snd_card *card,
|
|||||||
#ifdef CONFIG_SND_DEBUG
|
#ifdef CONFIG_SND_DEBUG
|
||||||
info->access = 0;
|
info->access = 0;
|
||||||
#endif
|
#endif
|
||||||
result = snd_power_ref_and_wait(card);
|
result = kctl->info(kctl, info);
|
||||||
if (!result)
|
|
||||||
result = kctl->info(kctl, info);
|
|
||||||
snd_power_unref(card);
|
|
||||||
if (result >= 0) {
|
if (result >= 0) {
|
||||||
snd_BUG_ON(info->access);
|
snd_BUG_ON(info->access);
|
||||||
index_offset = snd_ctl_get_ioff(kctl, &info->id);
|
index_offset = snd_ctl_get_ioff(kctl, &info->id);
|
||||||
@ -1199,7 +1163,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
|
|||||||
struct snd_kcontrol *kctl;
|
struct snd_kcontrol *kctl;
|
||||||
|
|
||||||
guard(rwsem_read)(&card->controls_rwsem);
|
guard(rwsem_read)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, &info->id);
|
kctl = snd_ctl_find_id(card, &info->id);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
return __snd_ctl_elem_info(card, kctl, info, ctl);
|
return __snd_ctl_elem_info(card, kctl, info, ctl);
|
||||||
@ -1208,12 +1172,17 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
|
|||||||
static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
|
static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
|
||||||
struct snd_ctl_elem_info __user *_info)
|
struct snd_ctl_elem_info __user *_info)
|
||||||
{
|
{
|
||||||
|
struct snd_card *card = ctl->card;
|
||||||
struct snd_ctl_elem_info info;
|
struct snd_ctl_elem_info info;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (copy_from_user(&info, _info, sizeof(info)))
|
if (copy_from_user(&info, _info, sizeof(info)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
result = snd_power_ref_and_wait(card);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
result = snd_ctl_elem_info(ctl, &info);
|
result = snd_ctl_elem_info(ctl, &info);
|
||||||
|
snd_power_unref(card);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
/* drop internal access flags */
|
/* drop internal access flags */
|
||||||
@ -1235,7 +1204,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
guard(rwsem_read)(&card->controls_rwsem);
|
guard(rwsem_read)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, &control->id);
|
kctl = snd_ctl_find_id(card, &control->id);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
@ -1257,10 +1226,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
|||||||
|
|
||||||
if (!snd_ctl_skip_validation(&info))
|
if (!snd_ctl_skip_validation(&info))
|
||||||
fill_remaining_elem_value(control, &info, pattern);
|
fill_remaining_elem_value(control, &info, pattern);
|
||||||
ret = snd_power_ref_and_wait(card);
|
ret = kctl->get(kctl, control);
|
||||||
if (!ret)
|
|
||||||
ret = kctl->get(kctl, control);
|
|
||||||
snd_power_unref(card);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if (!snd_ctl_skip_validation(&info) &&
|
if (!snd_ctl_skip_validation(&info) &&
|
||||||
@ -1283,9 +1249,13 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
|
|||||||
|
|
||||||
control = memdup_user(_control, sizeof(*control));
|
control = memdup_user(_control, sizeof(*control));
|
||||||
if (IS_ERR(control))
|
if (IS_ERR(control))
|
||||||
return PTR_ERR(no_free_ptr(control));
|
return PTR_ERR(control);
|
||||||
|
|
||||||
|
result = snd_power_ref_and_wait(card);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
result = snd_ctl_elem_read(card, control);
|
result = snd_ctl_elem_read(card, control);
|
||||||
|
snd_power_unref(card);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -1300,10 +1270,10 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
|||||||
struct snd_kcontrol *kctl;
|
struct snd_kcontrol *kctl;
|
||||||
struct snd_kcontrol_volatile *vd;
|
struct snd_kcontrol_volatile *vd;
|
||||||
unsigned int index_offset;
|
unsigned int index_offset;
|
||||||
int result;
|
int result = 0;
|
||||||
|
|
||||||
down_write(&card->controls_rwsem);
|
down_write(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, &control->id);
|
kctl = snd_ctl_find_id(card, &control->id);
|
||||||
if (kctl == NULL) {
|
if (kctl == NULL) {
|
||||||
up_write(&card->controls_rwsem);
|
up_write(&card->controls_rwsem);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -1318,9 +1288,8 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
snd_ctl_build_ioff(&control->id, kctl, index_offset);
|
snd_ctl_build_ioff(&control->id, kctl, index_offset);
|
||||||
result = snd_power_ref_and_wait(card);
|
|
||||||
/* validate input values */
|
/* validate input values */
|
||||||
if (IS_ENABLED(CONFIG_SND_CTL_INPUT_VALIDATION) && !result) {
|
if (IS_ENABLED(CONFIG_SND_CTL_INPUT_VALIDATION)) {
|
||||||
struct snd_ctl_elem_info info;
|
struct snd_ctl_elem_info info;
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
@ -1332,7 +1301,6 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
|||||||
}
|
}
|
||||||
if (!result)
|
if (!result)
|
||||||
result = kctl->put(kctl, control);
|
result = kctl->put(kctl, control);
|
||||||
snd_power_unref(card);
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
up_write(&card->controls_rwsem);
|
up_write(&card->controls_rwsem);
|
||||||
return result;
|
return result;
|
||||||
@ -1358,10 +1326,14 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
|
|||||||
|
|
||||||
control = memdup_user(_control, sizeof(*control));
|
control = memdup_user(_control, sizeof(*control));
|
||||||
if (IS_ERR(control))
|
if (IS_ERR(control))
|
||||||
return PTR_ERR(no_free_ptr(control));
|
return PTR_ERR(control);
|
||||||
|
|
||||||
card = file->card;
|
card = file->card;
|
||||||
|
result = snd_power_ref_and_wait(card);
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
result = snd_ctl_elem_write(card, file, control);
|
result = snd_ctl_elem_write(card, file, control);
|
||||||
|
snd_power_unref(card);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -1381,7 +1353,7 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file,
|
|||||||
if (copy_from_user(&id, _id, sizeof(id)))
|
if (copy_from_user(&id, _id, sizeof(id)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
guard(rwsem_write)(&card->controls_rwsem);
|
guard(rwsem_write)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, &id);
|
kctl = snd_ctl_find_id(card, &id);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
|
vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
|
||||||
@ -1402,7 +1374,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
|
|||||||
if (copy_from_user(&id, _id, sizeof(id)))
|
if (copy_from_user(&id, _id, sizeof(id)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
guard(rwsem_write)(&card->controls_rwsem);
|
guard(rwsem_write)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, &id);
|
kctl = snd_ctl_find_id(card, &id);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
|
vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
|
||||||
@ -1830,7 +1802,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
|
|||||||
{SNDRV_CTL_TLV_OP_CMD, SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
|
{SNDRV_CTL_TLV_OP_CMD, SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
|
||||||
};
|
};
|
||||||
struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
|
struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
|
||||||
int i, ret;
|
int i;
|
||||||
|
|
||||||
/* Check support of the request for this element. */
|
/* Check support of the request for this element. */
|
||||||
for (i = 0; i < ARRAY_SIZE(pairs); ++i) {
|
for (i = 0; i < ARRAY_SIZE(pairs); ++i) {
|
||||||
@ -1848,11 +1820,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
|
|||||||
vd->owner != NULL && vd->owner != file)
|
vd->owner != NULL && vd->owner != file)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
ret = snd_power_ref_and_wait(file->card);
|
return kctl->tlv.c(kctl, op_flag, size, buf);
|
||||||
if (!ret)
|
|
||||||
ret = kctl->tlv.c(kctl, op_flag, size, buf);
|
|
||||||
snd_power_unref(file->card);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id,
|
static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id,
|
||||||
@ -1903,7 +1871,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
|
|||||||
container_size = header.length;
|
container_size = header.length;
|
||||||
container = buf->tlv;
|
container = buf->tlv;
|
||||||
|
|
||||||
kctl = snd_ctl_find_numid_locked(file->card, header.numid);
|
kctl = snd_ctl_find_numid(file->card, header.numid);
|
||||||
if (kctl == NULL)
|
if (kctl == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
@ -1965,16 +1933,28 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
|
|||||||
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
|
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
|
||||||
return snd_ctl_subscribe_events(ctl, ip);
|
return snd_ctl_subscribe_events(ctl, ip);
|
||||||
case SNDRV_CTL_IOCTL_TLV_READ:
|
case SNDRV_CTL_IOCTL_TLV_READ:
|
||||||
scoped_guard(rwsem_read, &ctl->card->controls_rwsem)
|
err = snd_power_ref_and_wait(card);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
scoped_guard(rwsem_read, &card->controls_rwsem)
|
||||||
err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
|
err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
|
||||||
|
snd_power_unref(card);
|
||||||
return err;
|
return err;
|
||||||
case SNDRV_CTL_IOCTL_TLV_WRITE:
|
case SNDRV_CTL_IOCTL_TLV_WRITE:
|
||||||
scoped_guard(rwsem_write, &ctl->card->controls_rwsem)
|
err = snd_power_ref_and_wait(card);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
scoped_guard(rwsem_write, &card->controls_rwsem)
|
||||||
err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
|
err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
|
||||||
|
snd_power_unref(card);
|
||||||
return err;
|
return err;
|
||||||
case SNDRV_CTL_IOCTL_TLV_COMMAND:
|
case SNDRV_CTL_IOCTL_TLV_COMMAND:
|
||||||
scoped_guard(rwsem_write, &ctl->card->controls_rwsem)
|
err = snd_power_ref_and_wait(card);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
scoped_guard(rwsem_write, &card->controls_rwsem)
|
||||||
err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
|
err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
|
||||||
|
snd_power_unref(card);
|
||||||
return err;
|
return err;
|
||||||
case SNDRV_CTL_IOCTL_POWER:
|
case SNDRV_CTL_IOCTL_POWER:
|
||||||
return -ENOPROTOOPT;
|
return -ENOPROTOOPT;
|
||||||
@ -2178,7 +2158,7 @@ int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
|
|||||||
struct snd_ctl_file *kctl;
|
struct snd_ctl_file *kctl;
|
||||||
int subdevice = -1;
|
int subdevice = -1;
|
||||||
|
|
||||||
guard(read_lock_irqsave)(&card->ctl_files_rwlock);
|
guard(read_lock_irqsave)(&card->controls_rwlock);
|
||||||
list_for_each_entry(kctl, &card->ctl_files, list) {
|
list_for_each_entry(kctl, &card->ctl_files, list) {
|
||||||
if (kctl->pid == task_pid(current)) {
|
if (kctl->pid == task_pid(current)) {
|
||||||
subdevice = kctl->preferred_subdevice[type];
|
subdevice = kctl->preferred_subdevice[type];
|
||||||
@ -2328,7 +2308,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
|
|||||||
struct snd_card *card = device->device_data;
|
struct snd_card *card = device->device_data;
|
||||||
struct snd_ctl_file *ctl;
|
struct snd_ctl_file *ctl;
|
||||||
|
|
||||||
scoped_guard(read_lock_irqsave, &card->ctl_files_rwlock) {
|
scoped_guard(read_lock_irqsave, &card->controls_rwlock) {
|
||||||
list_for_each_entry(ctl, &card->ctl_files, list) {
|
list_for_each_entry(ctl, &card->ctl_files, list) {
|
||||||
wake_up(&ctl->change_sleep);
|
wake_up(&ctl->change_sleep);
|
||||||
snd_kill_fasync(ctl->fasync, SIGIO, POLL_ERR);
|
snd_kill_fasync(ctl->fasync, SIGIO, POLL_ERR);
|
||||||
|
@ -79,6 +79,7 @@ struct snd_ctl_elem_info32 {
|
|||||||
static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
|
static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
|
||||||
struct snd_ctl_elem_info32 __user *data32)
|
struct snd_ctl_elem_info32 __user *data32)
|
||||||
{
|
{
|
||||||
|
struct snd_card *card = ctl->card;
|
||||||
struct snd_ctl_elem_info *data __free(kfree) = NULL;
|
struct snd_ctl_elem_info *data __free(kfree) = NULL;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -95,7 +96,11 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
|
|||||||
if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
|
if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
err = snd_power_ref_and_wait(card);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
err = snd_ctl_elem_info(ctl, data);
|
err = snd_ctl_elem_info(ctl, data);
|
||||||
|
snd_power_unref(card);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
/* restore info to 32bit */
|
/* restore info to 32bit */
|
||||||
@ -168,17 +173,14 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
guard(rwsem_read)(&card->controls_rwsem);
|
guard(rwsem_read)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, id);
|
kctl = snd_ctl_find_id(card, id);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
info->id = *id;
|
info->id = *id;
|
||||||
err = snd_power_ref_and_wait(card);
|
err = kctl->info(kctl, info);
|
||||||
if (!err)
|
|
||||||
err = kctl->info(kctl, info);
|
|
||||||
snd_power_unref(card);
|
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
err = info->type;
|
err = info->type;
|
||||||
*countp = info->count;
|
*countp = info->count;
|
||||||
@ -275,8 +277,8 @@ static int copy_ctl_value_to_user(void __user *userdata,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ctl_elem_read_user(struct snd_card *card,
|
static int __ctl_elem_read_user(struct snd_card *card,
|
||||||
void __user *userdata, void __user *valuep)
|
void __user *userdata, void __user *valuep)
|
||||||
{
|
{
|
||||||
struct snd_ctl_elem_value *data __free(kfree) = NULL;
|
struct snd_ctl_elem_value *data __free(kfree) = NULL;
|
||||||
int err, type, count;
|
int err, type, count;
|
||||||
@ -296,8 +298,21 @@ static int ctl_elem_read_user(struct snd_card *card,
|
|||||||
return copy_ctl_value_to_user(userdata, valuep, data, type, count);
|
return copy_ctl_value_to_user(userdata, valuep, data, type, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ctl_elem_write_user(struct snd_ctl_file *file,
|
static int ctl_elem_read_user(struct snd_card *card,
|
||||||
void __user *userdata, void __user *valuep)
|
void __user *userdata, void __user *valuep)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = snd_power_ref_and_wait(card);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = __ctl_elem_read_user(card, userdata, valuep);
|
||||||
|
snd_power_unref(card);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __ctl_elem_write_user(struct snd_ctl_file *file,
|
||||||
|
void __user *userdata, void __user *valuep)
|
||||||
{
|
{
|
||||||
struct snd_ctl_elem_value *data __free(kfree) = NULL;
|
struct snd_ctl_elem_value *data __free(kfree) = NULL;
|
||||||
struct snd_card *card = file->card;
|
struct snd_card *card = file->card;
|
||||||
@ -318,6 +333,20 @@ static int ctl_elem_write_user(struct snd_ctl_file *file,
|
|||||||
return copy_ctl_value_to_user(userdata, valuep, data, type, count);
|
return copy_ctl_value_to_user(userdata, valuep, data, type, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ctl_elem_write_user(struct snd_ctl_file *file,
|
||||||
|
void __user *userdata, void __user *valuep)
|
||||||
|
{
|
||||||
|
struct snd_card *card = file->card;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = snd_power_ref_and_wait(card);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = __ctl_elem_write_user(file, userdata, valuep);
|
||||||
|
snd_power_unref(card);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_ctl_elem_read_user_compat(struct snd_card *card,
|
static int snd_ctl_elem_read_user_compat(struct snd_card *card,
|
||||||
struct snd_ctl_elem_value32 __user *data32)
|
struct snd_ctl_elem_value32 __user *data32)
|
||||||
{
|
{
|
||||||
|
@ -254,7 +254,7 @@ static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id,
|
|||||||
if (!card)
|
if (!card)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
guard(rwsem_write)(&card->controls_rwsem);
|
guard(rwsem_write)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_id_locked(card, id);
|
kctl = snd_ctl_find_id(card, id);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
ioff = snd_ctl_get_ioff(kctl, id);
|
ioff = snd_ctl_get_ioff(kctl, id);
|
||||||
@ -677,7 +677,7 @@ static void snd_ctl_led_sysfs_add(struct snd_card *card)
|
|||||||
cerr:
|
cerr:
|
||||||
put_device(&led_card->dev);
|
put_device(&led_card->dev);
|
||||||
cerr2:
|
cerr2:
|
||||||
printk(KERN_ERR "snd_ctl_led: unable to add card%d", card->number);
|
dev_err(card->dev, "snd_ctl_led: unable to add card%d", card->number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
|
|||||||
card->module = module;
|
card->module = module;
|
||||||
INIT_LIST_HEAD(&card->devices);
|
INIT_LIST_HEAD(&card->devices);
|
||||||
init_rwsem(&card->controls_rwsem);
|
init_rwsem(&card->controls_rwsem);
|
||||||
rwlock_init(&card->ctl_files_rwlock);
|
rwlock_init(&card->controls_rwlock);
|
||||||
INIT_LIST_HEAD(&card->controls);
|
INIT_LIST_HEAD(&card->controls);
|
||||||
INIT_LIST_HEAD(&card->ctl_files);
|
INIT_LIST_HEAD(&card->ctl_files);
|
||||||
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
|
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
|
||||||
|
@ -17,7 +17,17 @@
|
|||||||
#include <asm/set_memory.h>
|
#include <asm/set_memory.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sound/memalloc.h>
|
#include <sound/memalloc.h>
|
||||||
#include "memalloc_local.h"
|
|
||||||
|
struct snd_malloc_ops {
|
||||||
|
void *(*alloc)(struct snd_dma_buffer *dmab, size_t size);
|
||||||
|
void (*free)(struct snd_dma_buffer *dmab);
|
||||||
|
dma_addr_t (*get_addr)(struct snd_dma_buffer *dmab, size_t offset);
|
||||||
|
struct page *(*get_page)(struct snd_dma_buffer *dmab, size_t offset);
|
||||||
|
unsigned int (*get_chunk_size)(struct snd_dma_buffer *dmab,
|
||||||
|
unsigned int ofs, unsigned int size);
|
||||||
|
int (*mmap)(struct snd_dma_buffer *dmab, struct vm_area_struct *area);
|
||||||
|
void (*sync)(struct snd_dma_buffer *dmab, enum snd_dma_sync_mode mode);
|
||||||
|
};
|
||||||
|
|
||||||
#define DEFAULT_GFP \
|
#define DEFAULT_GFP \
|
||||||
(GFP_KERNEL | \
|
(GFP_KERNEL | \
|
||||||
@ -26,10 +36,6 @@
|
|||||||
|
|
||||||
static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab);
|
static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab);
|
||||||
|
|
||||||
#ifdef CONFIG_SND_DMA_SGBUF
|
|
||||||
static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void *__snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
|
static void *__snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
|
||||||
{
|
{
|
||||||
const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
|
const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
|
||||||
@ -490,15 +496,26 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
|
|||||||
/*
|
/*
|
||||||
* Write-combined pages
|
* Write-combined pages
|
||||||
*/
|
*/
|
||||||
/* x86-specific allocations */
|
|
||||||
#ifdef CONFIG_SND_DMA_SGBUF
|
#ifdef CONFIG_SND_DMA_SGBUF
|
||||||
|
/* x86-specific allocations */
|
||||||
static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
|
static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||||
{
|
{
|
||||||
return do_alloc_pages(dmab->dev.dev, size, &dmab->addr, true);
|
void *p = do_alloc_pages(dmab->dev.dev, size, &dmab->addr, true);
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
return NULL;
|
||||||
|
dmab->addr = dma_map_single(dmab->dev.dev, p, size, DMA_BIDIRECTIONAL);
|
||||||
|
if (dmab->addr == DMA_MAPPING_ERROR) {
|
||||||
|
do_free_pages(dmab->area, size, true);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
|
static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
|
||||||
{
|
{
|
||||||
|
dma_unmap_single(dmab->dev.dev, dmab->addr, dmab->bytes,
|
||||||
|
DMA_BIDIRECTIONAL);
|
||||||
do_free_pages(dmab->area, dmab->bytes, true);
|
do_free_pages(dmab->area, dmab->bytes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,7 +523,8 @@ static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
|
|||||||
struct vm_area_struct *area)
|
struct vm_area_struct *area)
|
||||||
{
|
{
|
||||||
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
|
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
|
||||||
return snd_dma_continuous_mmap(dmab, area);
|
return dma_mmap_coherent(dmab->dev.dev, area,
|
||||||
|
dmab->area, dmab->addr, dmab->bytes);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
|
static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||||
@ -525,7 +543,7 @@ static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
|
|||||||
return dma_mmap_wc(dmab->dev.dev, area,
|
return dma_mmap_wc(dmab->dev.dev, area,
|
||||||
dmab->area, dmab->addr, dmab->bytes);
|
dmab->area, dmab->addr, dmab->bytes);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SND_DMA_SGBUF */
|
#endif
|
||||||
|
|
||||||
static const struct snd_malloc_ops snd_dma_wc_ops = {
|
static const struct snd_malloc_ops snd_dma_wc_ops = {
|
||||||
.alloc = snd_dma_wc_alloc,
|
.alloc = snd_dma_wc_alloc,
|
||||||
@ -541,16 +559,8 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)
|
|||||||
struct sg_table *sgt;
|
struct sg_table *sgt;
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
#ifdef CONFIG_SND_DMA_SGBUF
|
|
||||||
if (cpu_feature_enabled(X86_FEATURE_XENPV))
|
|
||||||
return snd_dma_sg_fallback_alloc(dmab, size);
|
|
||||||
#endif
|
|
||||||
sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir,
|
sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir,
|
||||||
DEFAULT_GFP, 0);
|
DEFAULT_GFP, 0);
|
||||||
#ifdef CONFIG_SND_DMA_SGBUF
|
|
||||||
if (!sgt && !get_dma_ops(dmab->dev.dev))
|
|
||||||
return snd_dma_sg_fallback_alloc(dmab, size);
|
|
||||||
#endif
|
|
||||||
if (!sgt)
|
if (!sgt)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -667,125 +677,64 @@ static const struct snd_malloc_ops snd_dma_noncontig_ops = {
|
|||||||
.get_chunk_size = snd_dma_noncontig_get_chunk_size,
|
.get_chunk_size = snd_dma_noncontig_get_chunk_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* x86-specific SG-buffer with WC pages */
|
|
||||||
#ifdef CONFIG_SND_DMA_SGBUF
|
#ifdef CONFIG_SND_DMA_SGBUF
|
||||||
#define sg_wc_address(it) ((unsigned long)page_address(sg_page_iter_page(it)))
|
|
||||||
|
|
||||||
static void *snd_dma_sg_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
|
|
||||||
{
|
|
||||||
void *p = snd_dma_noncontig_alloc(dmab, size);
|
|
||||||
struct sg_table *sgt = dmab->private_data;
|
|
||||||
struct sg_page_iter iter;
|
|
||||||
|
|
||||||
if (!p)
|
|
||||||
return NULL;
|
|
||||||
if (dmab->dev.type != SNDRV_DMA_TYPE_DEV_WC_SG)
|
|
||||||
return p;
|
|
||||||
for_each_sgtable_page(sgt, &iter, 0)
|
|
||||||
set_memory_wc(sg_wc_address(&iter), 1);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void snd_dma_sg_wc_free(struct snd_dma_buffer *dmab)
|
|
||||||
{
|
|
||||||
struct sg_table *sgt = dmab->private_data;
|
|
||||||
struct sg_page_iter iter;
|
|
||||||
|
|
||||||
for_each_sgtable_page(sgt, &iter, 0)
|
|
||||||
set_memory_wb(sg_wc_address(&iter), 1);
|
|
||||||
snd_dma_noncontig_free(dmab);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snd_dma_sg_wc_mmap(struct snd_dma_buffer *dmab,
|
|
||||||
struct vm_area_struct *area)
|
|
||||||
{
|
|
||||||
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
|
|
||||||
return dma_mmap_noncontiguous(dmab->dev.dev, area,
|
|
||||||
dmab->bytes, dmab->private_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct snd_malloc_ops snd_dma_sg_wc_ops = {
|
|
||||||
.alloc = snd_dma_sg_wc_alloc,
|
|
||||||
.free = snd_dma_sg_wc_free,
|
|
||||||
.mmap = snd_dma_sg_wc_mmap,
|
|
||||||
.sync = snd_dma_noncontig_sync,
|
|
||||||
.get_addr = snd_dma_noncontig_get_addr,
|
|
||||||
.get_page = snd_dma_noncontig_get_page,
|
|
||||||
.get_chunk_size = snd_dma_noncontig_get_chunk_size,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Fallback SG-buffer allocations for x86 */
|
/* Fallback SG-buffer allocations for x86 */
|
||||||
struct snd_dma_sg_fallback {
|
struct snd_dma_sg_fallback {
|
||||||
bool use_dma_alloc_coherent;
|
struct sg_table sgt; /* used by get_addr - must be the first item */
|
||||||
size_t count;
|
size_t count;
|
||||||
struct page **pages;
|
struct page **pages;
|
||||||
/* DMA address array; the first page contains #pages in ~PAGE_MASK */
|
unsigned int *npages;
|
||||||
dma_addr_t *addrs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
|
static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
|
||||||
struct snd_dma_sg_fallback *sgbuf)
|
struct snd_dma_sg_fallback *sgbuf)
|
||||||
{
|
{
|
||||||
|
bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG;
|
||||||
size_t i, size;
|
size_t i, size;
|
||||||
|
|
||||||
if (sgbuf->pages && sgbuf->addrs) {
|
if (sgbuf->pages && sgbuf->npages) {
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < sgbuf->count) {
|
while (i < sgbuf->count) {
|
||||||
if (!sgbuf->pages[i] || !sgbuf->addrs[i])
|
size = sgbuf->npages[i];
|
||||||
|
if (!size)
|
||||||
break;
|
break;
|
||||||
size = sgbuf->addrs[i] & ~PAGE_MASK;
|
do_free_pages(page_address(sgbuf->pages[i]),
|
||||||
if (WARN_ON(!size))
|
size << PAGE_SHIFT, wc);
|
||||||
break;
|
|
||||||
if (sgbuf->use_dma_alloc_coherent)
|
|
||||||
dma_free_coherent(dmab->dev.dev, size << PAGE_SHIFT,
|
|
||||||
page_address(sgbuf->pages[i]),
|
|
||||||
sgbuf->addrs[i] & PAGE_MASK);
|
|
||||||
else
|
|
||||||
do_free_pages(page_address(sgbuf->pages[i]),
|
|
||||||
size << PAGE_SHIFT, false);
|
|
||||||
i += size;
|
i += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kvfree(sgbuf->pages);
|
kvfree(sgbuf->pages);
|
||||||
kvfree(sgbuf->addrs);
|
kvfree(sgbuf->npages);
|
||||||
kfree(sgbuf);
|
kfree(sgbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fallback manual S/G buffer allocations */
|
||||||
static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
|
static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||||
{
|
{
|
||||||
|
bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG;
|
||||||
struct snd_dma_sg_fallback *sgbuf;
|
struct snd_dma_sg_fallback *sgbuf;
|
||||||
struct page **pagep, *curp;
|
struct page **pagep, *curp;
|
||||||
size_t chunk, npages;
|
size_t chunk;
|
||||||
dma_addr_t *addrp;
|
|
||||||
dma_addr_t addr;
|
dma_addr_t addr;
|
||||||
|
unsigned int idx, npages;
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
/* correct the type */
|
|
||||||
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG)
|
|
||||||
dmab->dev.type = SNDRV_DMA_TYPE_DEV_SG_FALLBACK;
|
|
||||||
else if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
|
|
||||||
dmab->dev.type = SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
|
|
||||||
|
|
||||||
sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
|
sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
|
||||||
if (!sgbuf)
|
if (!sgbuf)
|
||||||
return NULL;
|
return NULL;
|
||||||
sgbuf->use_dma_alloc_coherent = cpu_feature_enabled(X86_FEATURE_XENPV);
|
|
||||||
size = PAGE_ALIGN(size);
|
size = PAGE_ALIGN(size);
|
||||||
sgbuf->count = size >> PAGE_SHIFT;
|
sgbuf->count = size >> PAGE_SHIFT;
|
||||||
sgbuf->pages = kvcalloc(sgbuf->count, sizeof(*sgbuf->pages), GFP_KERNEL);
|
sgbuf->pages = kvcalloc(sgbuf->count, sizeof(*sgbuf->pages), GFP_KERNEL);
|
||||||
sgbuf->addrs = kvcalloc(sgbuf->count, sizeof(*sgbuf->addrs), GFP_KERNEL);
|
sgbuf->npages = kvcalloc(sgbuf->count, sizeof(*sgbuf->npages), GFP_KERNEL);
|
||||||
if (!sgbuf->pages || !sgbuf->addrs)
|
if (!sgbuf->pages || !sgbuf->npages)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
pagep = sgbuf->pages;
|
pagep = sgbuf->pages;
|
||||||
addrp = sgbuf->addrs;
|
chunk = size;
|
||||||
chunk = (PAGE_SIZE - 1) << PAGE_SHIFT; /* to fit in low bits in addrs */
|
idx = 0;
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
chunk = min(size, chunk);
|
chunk = min(size, chunk);
|
||||||
if (sgbuf->use_dma_alloc_coherent)
|
p = do_alloc_pages(dmab->dev.dev, chunk, &addr, wc);
|
||||||
p = dma_alloc_coherent(dmab->dev.dev, chunk, &addr, DEFAULT_GFP);
|
|
||||||
else
|
|
||||||
p = do_alloc_pages(dmab->dev.dev, chunk, &addr, false);
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
if (chunk <= PAGE_SIZE)
|
if (chunk <= PAGE_SIZE)
|
||||||
goto error;
|
goto error;
|
||||||
@ -797,27 +746,33 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
|
|||||||
size -= chunk;
|
size -= chunk;
|
||||||
/* fill pages */
|
/* fill pages */
|
||||||
npages = chunk >> PAGE_SHIFT;
|
npages = chunk >> PAGE_SHIFT;
|
||||||
*addrp = npages; /* store in lower bits */
|
sgbuf->npages[idx] = npages;
|
||||||
|
idx += npages;
|
||||||
curp = virt_to_page(p);
|
curp = virt_to_page(p);
|
||||||
while (npages--) {
|
while (npages--)
|
||||||
*pagep++ = curp++;
|
*pagep++ = curp++;
|
||||||
*addrp++ |= addr;
|
|
||||||
addr += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sg_alloc_table_from_pages(&sgbuf->sgt, sgbuf->pages, sgbuf->count,
|
||||||
|
0, sgbuf->count << PAGE_SHIFT, GFP_KERNEL))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (dma_map_sgtable(dmab->dev.dev, &sgbuf->sgt, DMA_BIDIRECTIONAL, 0))
|
||||||
|
goto error_dma_map;
|
||||||
|
|
||||||
p = vmap(sgbuf->pages, sgbuf->count, VM_MAP, PAGE_KERNEL);
|
p = vmap(sgbuf->pages, sgbuf->count, VM_MAP, PAGE_KERNEL);
|
||||||
if (!p)
|
if (!p)
|
||||||
goto error;
|
goto error_vmap;
|
||||||
|
|
||||||
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
|
|
||||||
set_pages_array_wc(sgbuf->pages, sgbuf->count);
|
|
||||||
|
|
||||||
dmab->private_data = sgbuf;
|
dmab->private_data = sgbuf;
|
||||||
/* store the first page address for convenience */
|
/* store the first page address for convenience */
|
||||||
dmab->addr = sgbuf->addrs[0] & PAGE_MASK;
|
dmab->addr = snd_sgbuf_get_addr(dmab, 0);
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
|
error_vmap:
|
||||||
|
dma_unmap_sgtable(dmab->dev.dev, &sgbuf->sgt, DMA_BIDIRECTIONAL, 0);
|
||||||
|
error_dma_map:
|
||||||
|
sg_free_table(&sgbuf->sgt);
|
||||||
error:
|
error:
|
||||||
__snd_dma_sg_fallback_free(dmab, sgbuf);
|
__snd_dma_sg_fallback_free(dmab, sgbuf);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -827,36 +782,46 @@ static void snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab)
|
|||||||
{
|
{
|
||||||
struct snd_dma_sg_fallback *sgbuf = dmab->private_data;
|
struct snd_dma_sg_fallback *sgbuf = dmab->private_data;
|
||||||
|
|
||||||
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
|
|
||||||
set_pages_array_wb(sgbuf->pages, sgbuf->count);
|
|
||||||
vunmap(dmab->area);
|
vunmap(dmab->area);
|
||||||
|
dma_unmap_sgtable(dmab->dev.dev, &sgbuf->sgt, DMA_BIDIRECTIONAL, 0);
|
||||||
|
sg_free_table(&sgbuf->sgt);
|
||||||
__snd_dma_sg_fallback_free(dmab, dmab->private_data);
|
__snd_dma_sg_fallback_free(dmab, dmab->private_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static dma_addr_t snd_dma_sg_fallback_get_addr(struct snd_dma_buffer *dmab,
|
|
||||||
size_t offset)
|
|
||||||
{
|
|
||||||
struct snd_dma_sg_fallback *sgbuf = dmab->private_data;
|
|
||||||
size_t index = offset >> PAGE_SHIFT;
|
|
||||||
|
|
||||||
return (sgbuf->addrs[index] & PAGE_MASK) | (offset & ~PAGE_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snd_dma_sg_fallback_mmap(struct snd_dma_buffer *dmab,
|
static int snd_dma_sg_fallback_mmap(struct snd_dma_buffer *dmab,
|
||||||
struct vm_area_struct *area)
|
struct vm_area_struct *area)
|
||||||
{
|
{
|
||||||
struct snd_dma_sg_fallback *sgbuf = dmab->private_data;
|
struct snd_dma_sg_fallback *sgbuf = dmab->private_data;
|
||||||
|
|
||||||
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
|
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
|
||||||
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
|
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
|
||||||
return vm_map_pages(area, sgbuf->pages, sgbuf->count);
|
return vm_map_pages(area, sgbuf->pages, sgbuf->count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct snd_malloc_ops snd_dma_sg_fallback_ops = {
|
static void *snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||||
.alloc = snd_dma_sg_fallback_alloc,
|
{
|
||||||
|
int type = dmab->dev.type;
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
/* try the standard DMA API allocation at first */
|
||||||
|
if (type == SNDRV_DMA_TYPE_DEV_WC_SG)
|
||||||
|
dmab->dev.type = SNDRV_DMA_TYPE_DEV_WC;
|
||||||
|
else
|
||||||
|
dmab->dev.type = SNDRV_DMA_TYPE_DEV;
|
||||||
|
p = __snd_dma_alloc_pages(dmab, size);
|
||||||
|
if (p)
|
||||||
|
return p;
|
||||||
|
|
||||||
|
dmab->dev.type = type; /* restore the type */
|
||||||
|
return snd_dma_sg_fallback_alloc(dmab, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct snd_malloc_ops snd_dma_sg_ops = {
|
||||||
|
.alloc = snd_dma_sg_alloc,
|
||||||
.free = snd_dma_sg_fallback_free,
|
.free = snd_dma_sg_fallback_free,
|
||||||
.mmap = snd_dma_sg_fallback_mmap,
|
.mmap = snd_dma_sg_fallback_mmap,
|
||||||
.get_addr = snd_dma_sg_fallback_get_addr,
|
/* reuse noncontig helper */
|
||||||
|
.get_addr = snd_dma_noncontig_get_addr,
|
||||||
/* reuse vmalloc helpers */
|
/* reuse vmalloc helpers */
|
||||||
.get_page = snd_dma_vmalloc_get_page,
|
.get_page = snd_dma_vmalloc_get_page,
|
||||||
.get_chunk_size = snd_dma_vmalloc_get_chunk_size,
|
.get_chunk_size = snd_dma_vmalloc_get_chunk_size,
|
||||||
@ -927,15 +892,12 @@ static const struct snd_malloc_ops *snd_dma_ops[] = {
|
|||||||
[SNDRV_DMA_TYPE_NONCONTIG] = &snd_dma_noncontig_ops,
|
[SNDRV_DMA_TYPE_NONCONTIG] = &snd_dma_noncontig_ops,
|
||||||
[SNDRV_DMA_TYPE_NONCOHERENT] = &snd_dma_noncoherent_ops,
|
[SNDRV_DMA_TYPE_NONCOHERENT] = &snd_dma_noncoherent_ops,
|
||||||
#ifdef CONFIG_SND_DMA_SGBUF
|
#ifdef CONFIG_SND_DMA_SGBUF
|
||||||
[SNDRV_DMA_TYPE_DEV_WC_SG] = &snd_dma_sg_wc_ops,
|
[SNDRV_DMA_TYPE_DEV_SG] = &snd_dma_sg_ops,
|
||||||
|
[SNDRV_DMA_TYPE_DEV_WC_SG] = &snd_dma_sg_ops,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_GENERIC_ALLOCATOR
|
#ifdef CONFIG_GENERIC_ALLOCATOR
|
||||||
[SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops,
|
[SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops,
|
||||||
#endif /* CONFIG_GENERIC_ALLOCATOR */
|
#endif /* CONFIG_GENERIC_ALLOCATOR */
|
||||||
#ifdef CONFIG_SND_DMA_SGBUF
|
|
||||||
[SNDRV_DMA_TYPE_DEV_SG_FALLBACK] = &snd_dma_sg_fallback_ops,
|
|
||||||
[SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK] = &snd_dma_sg_fallback_ops,
|
|
||||||
#endif
|
|
||||||
#endif /* CONFIG_HAS_DMA */
|
#endif /* CONFIG_HAS_DMA */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
#ifndef __MEMALLOC_LOCAL_H
|
|
||||||
#define __MEMALLOC_LOCAL_H
|
|
||||||
|
|
||||||
struct snd_malloc_ops {
|
|
||||||
void *(*alloc)(struct snd_dma_buffer *dmab, size_t size);
|
|
||||||
void (*free)(struct snd_dma_buffer *dmab);
|
|
||||||
dma_addr_t (*get_addr)(struct snd_dma_buffer *dmab, size_t offset);
|
|
||||||
struct page *(*get_page)(struct snd_dma_buffer *dmab, size_t offset);
|
|
||||||
unsigned int (*get_chunk_size)(struct snd_dma_buffer *dmab,
|
|
||||||
unsigned int ofs, unsigned int size);
|
|
||||||
int (*mmap)(struct snd_dma_buffer *dmab, struct vm_area_struct *area);
|
|
||||||
void (*sync)(struct snd_dma_buffer *dmab, enum snd_dma_sync_mode mode);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __MEMALLOC_LOCAL_H */
|
|
@ -13,20 +13,6 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
|
|
||||||
#ifdef CONFIG_SND_DEBUG
|
|
||||||
|
|
||||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
|
||||||
#define DEFAULT_DEBUG_LEVEL 2
|
|
||||||
#else
|
|
||||||
#define DEFAULT_DEBUG_LEVEL 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int debug = DEFAULT_DEBUG_LEVEL;
|
|
||||||
module_param(debug, int, 0644);
|
|
||||||
MODULE_PARM_DESC(debug, "Debug level (0 = disable)");
|
|
||||||
|
|
||||||
#endif /* CONFIG_SND_DEBUG */
|
|
||||||
|
|
||||||
void release_and_free_resource(struct resource *res)
|
void release_and_free_resource(struct resource *res)
|
||||||
{
|
{
|
||||||
if (res) {
|
if (res) {
|
||||||
@ -36,63 +22,6 @@ void release_and_free_resource(struct resource *res)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(release_and_free_resource);
|
EXPORT_SYMBOL(release_and_free_resource);
|
||||||
|
|
||||||
#ifdef CONFIG_SND_VERBOSE_PRINTK
|
|
||||||
/* strip the leading path if the given path is absolute */
|
|
||||||
static const char *sanity_file_name(const char *path)
|
|
||||||
{
|
|
||||||
if (*path == '/')
|
|
||||||
return strrchr(path, '/') + 1;
|
|
||||||
else
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK)
|
|
||||||
void __snd_printk(unsigned int level, const char *path, int line,
|
|
||||||
const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
#ifdef CONFIG_SND_VERBOSE_PRINTK
|
|
||||||
int kern_level;
|
|
||||||
struct va_format vaf;
|
|
||||||
char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV";
|
|
||||||
bool level_found = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_SND_DEBUG
|
|
||||||
if (debug < level)
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
va_start(args, format);
|
|
||||||
#ifdef CONFIG_SND_VERBOSE_PRINTK
|
|
||||||
vaf.fmt = format;
|
|
||||||
vaf.va = &args;
|
|
||||||
|
|
||||||
while ((kern_level = printk_get_level(vaf.fmt)) != 0) {
|
|
||||||
const char *end_of_header = printk_skip_level(vaf.fmt);
|
|
||||||
|
|
||||||
/* Ignore KERN_CONT. We print filename:line for each piece. */
|
|
||||||
if (kern_level >= '0' && kern_level <= '7') {
|
|
||||||
memcpy(verbose_fmt, vaf.fmt, end_of_header - vaf.fmt);
|
|
||||||
level_found = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
vaf.fmt = end_of_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!level_found && level)
|
|
||||||
memcpy(verbose_fmt, KERN_DEBUG, sizeof(KERN_DEBUG) - 1);
|
|
||||||
|
|
||||||
printk(verbose_fmt, sanity_file_name(path), line, &vaf);
|
|
||||||
#else
|
|
||||||
vprintk(format, args);
|
|
||||||
#endif
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(__snd_printk);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
/**
|
/**
|
||||||
|
@ -510,7 +510,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c
|
|||||||
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||||
strscpy(id.name, name, sizeof(id.name));
|
strscpy(id.name, name, sizeof(id.name));
|
||||||
id.index = index;
|
id.index = index;
|
||||||
return snd_ctl_find_id_locked(card, &id);
|
return snd_ctl_find_id(card, &id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
||||||
@ -526,7 +526,7 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
|||||||
if (numid == ID_UNKNOWN)
|
if (numid == ID_UNKNOWN)
|
||||||
return;
|
return;
|
||||||
guard(rwsem_read)(&card->controls_rwsem);
|
guard(rwsem_read)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
kctl = snd_ctl_find_numid(card, numid);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return;
|
return;
|
||||||
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
||||||
@ -559,7 +559,7 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer,
|
|||||||
if (numid == ID_UNKNOWN)
|
if (numid == ID_UNKNOWN)
|
||||||
return;
|
return;
|
||||||
guard(rwsem_read)(&card->controls_rwsem);
|
guard(rwsem_read)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
kctl = snd_ctl_find_numid(card, numid);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return;
|
return;
|
||||||
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
||||||
@ -619,7 +619,7 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
|||||||
if (numid == ID_UNKNOWN)
|
if (numid == ID_UNKNOWN)
|
||||||
return;
|
return;
|
||||||
guard(rwsem_read)(&card->controls_rwsem);
|
guard(rwsem_read)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
kctl = snd_ctl_find_numid(card, numid);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return;
|
return;
|
||||||
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
||||||
@ -656,7 +656,7 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
|
|||||||
if (numid == ID_UNKNOWN)
|
if (numid == ID_UNKNOWN)
|
||||||
return;
|
return;
|
||||||
guard(rwsem_read)(&card->controls_rwsem);
|
guard(rwsem_read)(&card->controls_rwsem);
|
||||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
kctl = snd_ctl_find_numid(card, numid);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return;
|
return;
|
||||||
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
||||||
|
@ -74,7 +74,6 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *handle,
|
|||||||
size_t extra,
|
size_t extra,
|
||||||
struct snd_pcm_plugin **ret);
|
struct snd_pcm_plugin **ret);
|
||||||
int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin);
|
int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin);
|
||||||
int snd_pcm_plugin_clear(struct snd_pcm_plugin **first);
|
|
||||||
int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames);
|
int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames);
|
||||||
snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size);
|
snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size);
|
||||||
snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size);
|
snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size);
|
||||||
@ -139,8 +138,6 @@ int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel,
|
|||||||
size_t dst_offset,
|
size_t dst_offset,
|
||||||
size_t samples, snd_pcm_format_t format);
|
size_t samples, snd_pcm_format_t format);
|
||||||
|
|
||||||
void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size);
|
|
||||||
void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr);
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
|
static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
|
||||||
@ -160,7 +157,7 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
|
|||||||
void **bufs, snd_pcm_uframes_t frames);
|
void **bufs, snd_pcm_uframes_t frames);
|
||||||
|
|
||||||
#ifdef PLUGIN_DEBUG
|
#ifdef PLUGIN_DEBUG
|
||||||
#define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args)
|
#define pdprintf(fmt, args...) pr_debug("plugin: " fmt, ##args)
|
||||||
#else
|
#else
|
||||||
#define pdprintf(fmt, args...)
|
#define pdprintf(fmt, args...)
|
||||||
#endif
|
#endif
|
||||||
|
@ -462,6 +462,9 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
|
|||||||
snd_iprintf(buffer, "-----\n");
|
snd_iprintf(buffer, "-----\n");
|
||||||
snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr);
|
snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr);
|
||||||
snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr);
|
snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr);
|
||||||
|
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
||||||
|
snd_iprintf(buffer, "xrun_counter: %d\n", substream->xrun_counter);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
||||||
@ -970,6 +973,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
|
|||||||
substream->pid = get_pid(task_pid(current));
|
substream->pid = get_pid(task_pid(current));
|
||||||
pstr->substream_opened++;
|
pstr->substream_opened++;
|
||||||
*rsubstream = substream;
|
*rsubstream = substream;
|
||||||
|
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
||||||
|
substream->xrun_counter = 0;
|
||||||
|
#endif /* CONFIG_SND_PCM_XRUN_DEBUG */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,6 +184,9 @@ void __snd_pcm_xrun(struct snd_pcm_substream *substream)
|
|||||||
pcm_warn(substream->pcm, "XRUN: %s\n", name);
|
pcm_warn(substream->pcm, "XRUN: %s\n", name);
|
||||||
dump_stack_on_xrun(substream);
|
dump_stack_on_xrun(substream);
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
||||||
|
substream->xrun_counter++;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
#include <linux/vmalloc.h>
|
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
@ -184,7 +183,7 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
|
|||||||
struct snd_pcm_substream *substream = entry->private_data;
|
struct snd_pcm_substream *substream = entry->private_data;
|
||||||
struct snd_card *card = substream->pcm->card;
|
struct snd_card *card = substream->pcm->card;
|
||||||
char line[64], str[64];
|
char line[64], str[64];
|
||||||
size_t size;
|
unsigned long size;
|
||||||
struct snd_dma_buffer new_dmab;
|
struct snd_dma_buffer new_dmab;
|
||||||
|
|
||||||
guard(mutex)(&substream->pcm->open_mutex);
|
guard(mutex)(&substream->pcm->open_mutex);
|
||||||
@ -194,7 +193,10 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
|
|||||||
}
|
}
|
||||||
if (!snd_info_get_line(buffer, line, sizeof(line))) {
|
if (!snd_info_get_line(buffer, line, sizeof(line))) {
|
||||||
snd_info_get_str(str, line, sizeof(str));
|
snd_info_get_str(str, line, sizeof(str));
|
||||||
size = simple_strtoul(str, NULL, 10) * 1024;
|
buffer->error = kstrtoul(str, 10, &size);
|
||||||
|
if (buffer->error != 0)
|
||||||
|
return;
|
||||||
|
size *= 1024;
|
||||||
if ((size != 0 && size < 8192) || size > substream->dma_max) {
|
if ((size != 0 && size < 8192) || size > substream->dma_max) {
|
||||||
buffer->error = -EINVAL;
|
buffer->error = -EINVAL;
|
||||||
return;
|
return;
|
||||||
@ -210,7 +212,7 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
|
|||||||
substream->stream,
|
substream->stream,
|
||||||
size, &new_dmab) < 0) {
|
size, &new_dmab) < 0) {
|
||||||
buffer->error = -ENOMEM;
|
buffer->error = -ENOMEM;
|
||||||
pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
|
pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %lu\n",
|
||||||
substream->pcm->card->number, substream->pcm->device,
|
substream->pcm->card->number, substream->pcm->device,
|
||||||
substream->stream ? 'c' : 'p', substream->number,
|
substream->stream ? 'c' : 'p', substream->number,
|
||||||
substream->pcm->name, size);
|
substream->pcm->name, size);
|
||||||
@ -497,61 +499,3 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(snd_pcm_lib_free_pages);
|
EXPORT_SYMBOL(snd_pcm_lib_free_pages);
|
||||||
|
|
||||||
int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
|
|
||||||
size_t size, gfp_t gfp_flags)
|
|
||||||
{
|
|
||||||
struct snd_pcm_runtime *runtime;
|
|
||||||
|
|
||||||
if (PCM_RUNTIME_CHECK(substream))
|
|
||||||
return -EINVAL;
|
|
||||||
runtime = substream->runtime;
|
|
||||||
if (runtime->dma_area) {
|
|
||||||
if (runtime->dma_bytes >= size)
|
|
||||||
return 0; /* already large enough */
|
|
||||||
vfree(runtime->dma_area);
|
|
||||||
}
|
|
||||||
runtime->dma_area = __vmalloc(size, gfp_flags);
|
|
||||||
if (!runtime->dma_area)
|
|
||||||
return -ENOMEM;
|
|
||||||
runtime->dma_bytes = size;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer
|
|
||||||
* @substream: the substream with a buffer allocated by
|
|
||||||
* snd_pcm_lib_alloc_vmalloc_buffer()
|
|
||||||
*
|
|
||||||
* Return: Zero if successful, or a negative error code on failure.
|
|
||||||
*/
|
|
||||||
int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream)
|
|
||||||
{
|
|
||||||
struct snd_pcm_runtime *runtime;
|
|
||||||
|
|
||||||
if (PCM_RUNTIME_CHECK(substream))
|
|
||||||
return -EINVAL;
|
|
||||||
runtime = substream->runtime;
|
|
||||||
vfree(runtime->dma_area);
|
|
||||||
runtime->dma_area = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* snd_pcm_lib_get_vmalloc_page - map vmalloc buffer offset to page struct
|
|
||||||
* @substream: the substream with a buffer allocated by
|
|
||||||
* snd_pcm_lib_alloc_vmalloc_buffer()
|
|
||||||
* @offset: offset in the buffer
|
|
||||||
*
|
|
||||||
* This function is to be used as the page callback in the PCM ops.
|
|
||||||
*
|
|
||||||
* Return: The page struct, or %NULL on failure.
|
|
||||||
*/
|
|
||||||
struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
|
|
||||||
unsigned long offset)
|
|
||||||
{
|
|
||||||
return vmalloc_to_page(substream->runtime->dma_area + offset);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(snd_pcm_lib_get_vmalloc_page);
|
|
||||||
|
@ -494,18 +494,20 @@ EXPORT_SYMBOL(snd_pcm_format_set_silence);
|
|||||||
int snd_pcm_hw_limit_rates(struct snd_pcm_hardware *hw)
|
int snd_pcm_hw_limit_rates(struct snd_pcm_hardware *hw)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
unsigned int rmin, rmax;
|
||||||
|
|
||||||
|
rmin = UINT_MAX;
|
||||||
|
rmax = 0;
|
||||||
for (i = 0; i < (int)snd_pcm_known_rates.count; i++) {
|
for (i = 0; i < (int)snd_pcm_known_rates.count; i++) {
|
||||||
if (hw->rates & (1 << i)) {
|
if (hw->rates & (1 << i)) {
|
||||||
hw->rate_min = snd_pcm_known_rates.list[i];
|
rmin = min(rmin, snd_pcm_known_rates.list[i]);
|
||||||
break;
|
rmax = max(rmax, snd_pcm_known_rates.list[i]);
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i = (int)snd_pcm_known_rates.count - 1; i >= 0; i--) {
|
|
||||||
if (hw->rates & (1 << i)) {
|
|
||||||
hw->rate_max = snd_pcm_known_rates.list[i];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rmin > rmax)
|
||||||
|
return -EINVAL;
|
||||||
|
hw->rate_min = rmin;
|
||||||
|
hw->rate_max = rmax;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(snd_pcm_hw_limit_rates);
|
EXPORT_SYMBOL(snd_pcm_hw_limit_rates);
|
||||||
|
@ -582,7 +582,7 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
params = memdup_user(_params, sizeof(*params));
|
params = memdup_user(_params, sizeof(*params));
|
||||||
if (IS_ERR(params))
|
if (IS_ERR(params))
|
||||||
return PTR_ERR(no_free_ptr(params));
|
return PTR_ERR(params);
|
||||||
|
|
||||||
err = snd_pcm_hw_refine(substream, params);
|
err = snd_pcm_hw_refine(substream, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -872,7 +872,7 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
params = memdup_user(_params, sizeof(*params));
|
params = memdup_user(_params, sizeof(*params));
|
||||||
if (IS_ERR(params))
|
if (IS_ERR(params))
|
||||||
return PTR_ERR(no_free_ptr(params));
|
return PTR_ERR(params);
|
||||||
|
|
||||||
err = snd_pcm_hw_params(substream, params);
|
err = snd_pcm_hw_params(substream, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -2418,13 +2418,17 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
|
|||||||
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
|
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
|
#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 ||\
|
||||||
|
SNDRV_PCM_RATE_128000 != 1 << 19
|
||||||
#error "Change this table"
|
#error "Change this table"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* NOTE: the list is unsorted! */
|
||||||
static const unsigned int rates[] = {
|
static const unsigned int rates[] = {
|
||||||
5512, 8000, 11025, 16000, 22050, 32000, 44100,
|
5512, 8000, 11025, 16000, 22050, 32000, 44100,
|
||||||
48000, 64000, 88200, 96000, 176400, 192000, 352800, 384000, 705600, 768000
|
48000, 64000, 88200, 96000, 176400, 192000, 352800, 384000, 705600, 768000,
|
||||||
|
/* extended */
|
||||||
|
12000, 24000, 128000
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
|
const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
|
||||||
@ -3243,7 +3247,7 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
bufs = memdup_user(xfern.bufs, sizeof(void *) * runtime->channels);
|
bufs = memdup_user(xfern.bufs, sizeof(void *) * runtime->channels);
|
||||||
if (IS_ERR(bufs))
|
if (IS_ERR(bufs))
|
||||||
return PTR_ERR(no_free_ptr(bufs));
|
return PTR_ERR(bufs);
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
|
result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
|
||||||
else
|
else
|
||||||
@ -4032,7 +4036,7 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
oparams = memdup_user(_oparams, sizeof(*oparams));
|
oparams = memdup_user(_oparams, sizeof(*oparams));
|
||||||
if (IS_ERR(oparams))
|
if (IS_ERR(oparams))
|
||||||
return PTR_ERR(no_free_ptr(oparams));
|
return PTR_ERR(oparams);
|
||||||
snd_pcm_hw_convert_from_old_params(params, oparams);
|
snd_pcm_hw_convert_from_old_params(params, oparams);
|
||||||
err = snd_pcm_hw_refine(substream, params);
|
err = snd_pcm_hw_refine(substream, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -4061,7 +4065,7 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
oparams = memdup_user(_oparams, sizeof(*oparams));
|
oparams = memdup_user(_oparams, sizeof(*oparams));
|
||||||
if (IS_ERR(oparams))
|
if (IS_ERR(oparams))
|
||||||
return PTR_ERR(no_free_ptr(oparams));
|
return PTR_ERR(oparams);
|
||||||
|
|
||||||
snd_pcm_hw_convert_from_old_params(params, oparams);
|
snd_pcm_hw_convert_from_old_params(params, oparams);
|
||||||
err = snd_pcm_hw_params(substream, params);
|
err = snd_pcm_hw_params(substream, params);
|
||||||
|
@ -108,8 +108,7 @@ void snd_pcm_timer_init(struct snd_pcm_substream *substream)
|
|||||||
if (snd_timer_new(substream->pcm->card, "PCM", &tid, &timer) < 0)
|
if (snd_timer_new(substream->pcm->card, "PCM", &tid, &timer) < 0)
|
||||||
return;
|
return;
|
||||||
sprintf(timer->name, "PCM %s %i-%i-%i",
|
sprintf(timer->name, "PCM %s %i-%i-%i",
|
||||||
substream->stream == SNDRV_PCM_STREAM_CAPTURE ?
|
snd_pcm_direction_name(substream->stream),
|
||||||
"capture" : "playback",
|
|
||||||
tid.card, tid.device, tid.subdevice);
|
tid.card, tid.device, tid.subdevice);
|
||||||
timer->hw = snd_pcm_timer;
|
timer->hw = snd_pcm_timer;
|
||||||
if (snd_device_register(timer->card, timer) < 0) {
|
if (snd_device_register(timer->card, timer) < 0) {
|
||||||
|
@ -116,10 +116,6 @@ __poll_t snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_ta
|
|||||||
|
|
||||||
void snd_seq_oss_reset(struct seq_oss_devinfo *dp);
|
void snd_seq_oss_reset(struct seq_oss_devinfo *dp);
|
||||||
|
|
||||||
/* */
|
|
||||||
void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time);
|
|
||||||
|
|
||||||
|
|
||||||
/* proc interface */
|
/* proc interface */
|
||||||
void snd_seq_oss_system_info_read(struct snd_info_buffer *buf);
|
void snd_seq_oss_system_info_read(struct snd_info_buffer *buf);
|
||||||
void snd_seq_oss_midi_info_read(struct snd_info_buffer *buf);
|
void snd_seq_oss_midi_info_read(struct snd_info_buffer *buf);
|
||||||
|
@ -70,7 +70,7 @@ static int bounce_error_event(struct snd_seq_client *client,
|
|||||||
int err, int atomic, int hop);
|
int err, int atomic, int hop);
|
||||||
static int snd_seq_deliver_single_event(struct snd_seq_client *client,
|
static int snd_seq_deliver_single_event(struct snd_seq_client *client,
|
||||||
struct snd_seq_event *event,
|
struct snd_seq_event *event,
|
||||||
int filter, int atomic, int hop);
|
int atomic, int hop);
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
|
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
|
||||||
static void free_ump_info(struct snd_seq_client *client);
|
static void free_ump_info(struct snd_seq_client *client);
|
||||||
@ -525,10 +525,8 @@ static int check_port_perm(struct snd_seq_client_port *port, unsigned int flags)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* check if the destination client is available, and return the pointer
|
* check if the destination client is available, and return the pointer
|
||||||
* if filter is non-zero, client filter bitmap is tested.
|
|
||||||
*/
|
*/
|
||||||
static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event,
|
static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event)
|
||||||
int filter)
|
|
||||||
{
|
{
|
||||||
struct snd_seq_client *dest;
|
struct snd_seq_client *dest;
|
||||||
|
|
||||||
@ -543,8 +541,6 @@ static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event,
|
|||||||
if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) &&
|
if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) &&
|
||||||
! test_bit(event->type, dest->event_filter))
|
! test_bit(event->type, dest->event_filter))
|
||||||
goto __not_avail;
|
goto __not_avail;
|
||||||
if (filter && !(dest->filter & filter))
|
|
||||||
goto __not_avail;
|
|
||||||
|
|
||||||
return dest; /* ok - accessible */
|
return dest; /* ok - accessible */
|
||||||
__not_avail:
|
__not_avail:
|
||||||
@ -588,7 +584,7 @@ static int bounce_error_event(struct snd_seq_client *client,
|
|||||||
bounce_ev.data.quote.origin = event->dest;
|
bounce_ev.data.quote.origin = event->dest;
|
||||||
bounce_ev.data.quote.event = event;
|
bounce_ev.data.quote.event = event;
|
||||||
bounce_ev.data.quote.value = -err; /* use positive value */
|
bounce_ev.data.quote.value = -err; /* use positive value */
|
||||||
result = snd_seq_deliver_single_event(NULL, &bounce_ev, 0, atomic, hop + 1);
|
result = snd_seq_deliver_single_event(NULL, &bounce_ev, atomic, hop + 1);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
client->event_lost++;
|
client->event_lost++;
|
||||||
return result;
|
return result;
|
||||||
@ -655,7 +651,7 @@ int __snd_seq_deliver_single_event(struct snd_seq_client *dest,
|
|||||||
*/
|
*/
|
||||||
static int snd_seq_deliver_single_event(struct snd_seq_client *client,
|
static int snd_seq_deliver_single_event(struct snd_seq_client *client,
|
||||||
struct snd_seq_event *event,
|
struct snd_seq_event *event,
|
||||||
int filter, int atomic, int hop)
|
int atomic, int hop)
|
||||||
{
|
{
|
||||||
struct snd_seq_client *dest = NULL;
|
struct snd_seq_client *dest = NULL;
|
||||||
struct snd_seq_client_port *dest_port = NULL;
|
struct snd_seq_client_port *dest_port = NULL;
|
||||||
@ -664,7 +660,7 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client,
|
|||||||
|
|
||||||
direct = snd_seq_ev_is_direct(event);
|
direct = snd_seq_ev_is_direct(event);
|
||||||
|
|
||||||
dest = get_event_dest_client(event, filter);
|
dest = get_event_dest_client(event);
|
||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
goto __skip;
|
goto __skip;
|
||||||
dest_port = snd_seq_port_use_ptr(dest, event->dest.port);
|
dest_port = snd_seq_port_use_ptr(dest, event->dest.port);
|
||||||
@ -744,8 +740,7 @@ static int __deliver_to_subscribers(struct snd_seq_client *client,
|
|||||||
/* convert time according to flag with subscription */
|
/* convert time according to flag with subscription */
|
||||||
update_timestamp_of_queue(event, subs->info.queue,
|
update_timestamp_of_queue(event, subs->info.queue,
|
||||||
subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL);
|
subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL);
|
||||||
err = snd_seq_deliver_single_event(client, event,
|
err = snd_seq_deliver_single_event(client, event, atomic, hop);
|
||||||
0, atomic, hop);
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
/* save first error that occurs and continue */
|
/* save first error that occurs and continue */
|
||||||
if (!result)
|
if (!result)
|
||||||
@ -818,7 +813,7 @@ static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_e
|
|||||||
event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS)
|
event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS)
|
||||||
result = deliver_to_subscribers(client, event, atomic, hop);
|
result = deliver_to_subscribers(client, event, atomic, hop);
|
||||||
else
|
else
|
||||||
result = snd_seq_deliver_single_event(client, event, 0, atomic, hop);
|
result = snd_seq_deliver_single_event(client, event, atomic, hop);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2636,13 +2631,18 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
|
|||||||
list_for_each_entry(p, &client->ports_list_head, list) {
|
list_for_each_entry(p, &client->ports_list_head, list) {
|
||||||
if (p->capability & SNDRV_SEQ_PORT_CAP_INACTIVE)
|
if (p->capability & SNDRV_SEQ_PORT_CAP_INACTIVE)
|
||||||
continue;
|
continue;
|
||||||
snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c) [%s]\n",
|
snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c) [%s]",
|
||||||
p->addr.port, p->name,
|
p->addr.port, p->name,
|
||||||
FLAG_PERM_RD(p->capability),
|
FLAG_PERM_RD(p->capability),
|
||||||
FLAG_PERM_WR(p->capability),
|
FLAG_PERM_WR(p->capability),
|
||||||
FLAG_PERM_EX(p->capability),
|
FLAG_PERM_EX(p->capability),
|
||||||
FLAG_PERM_DUPLEX(p->capability),
|
FLAG_PERM_DUPLEX(p->capability),
|
||||||
port_direction_name(p->direction));
|
port_direction_name(p->direction));
|
||||||
|
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
|
||||||
|
if (snd_seq_client_is_midi2(client) && p->is_midi1)
|
||||||
|
snd_iprintf(buffer, " [MIDI1]");
|
||||||
|
#endif
|
||||||
|
snd_iprintf(buffer, "\n");
|
||||||
snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, " Connecting To: ");
|
snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, " Connecting To: ");
|
||||||
snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, " Connected From: ");
|
snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, " Connected From: ");
|
||||||
}
|
}
|
||||||
|
@ -362,6 +362,8 @@ int snd_seq_set_port_info(struct snd_seq_client_port * port,
|
|||||||
port->direction |= SNDRV_SEQ_PORT_DIR_OUTPUT;
|
port->direction |= SNDRV_SEQ_PORT_DIR_OUTPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
port->is_midi1 = !!(info->flags & SNDRV_SEQ_PORT_FLG_IS_MIDI1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,6 +401,9 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port,
|
|||||||
info->time_queue = port->time_queue;
|
info->time_queue = port->time_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (port->is_midi1)
|
||||||
|
info->flags |= SNDRV_SEQ_PORT_FLG_IS_MIDI1;
|
||||||
|
|
||||||
/* UMP direction and group */
|
/* UMP direction and group */
|
||||||
info->direction = port->direction;
|
info->direction = port->direction;
|
||||||
info->ump_group = port->ump_group;
|
info->ump_group = port->ump_group;
|
||||||
|
@ -77,6 +77,8 @@ struct snd_seq_client_port {
|
|||||||
unsigned char direction;
|
unsigned char direction;
|
||||||
unsigned char ump_group;
|
unsigned char ump_group;
|
||||||
|
|
||||||
|
bool is_midi1; /* keep MIDI 1.0 protocol */
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
|
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
|
||||||
struct ump_cvt_to_ump_bank midi2_bank[16]; /* per channel */
|
struct ump_cvt_to_ump_bank midi2_bank[16]; /* per channel */
|
||||||
#endif
|
#endif
|
||||||
|
@ -84,7 +84,6 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop);
|
|||||||
int snd_seq_queue_check_access(int queueid, int client);
|
int snd_seq_queue_check_access(int queueid, int client);
|
||||||
int snd_seq_queue_timer_set_tempo(int queueid, int client, struct snd_seq_queue_tempo *info);
|
int snd_seq_queue_timer_set_tempo(int queueid, int client, struct snd_seq_queue_tempo *info);
|
||||||
int snd_seq_queue_set_owner(int queueid, int client, int locked);
|
int snd_seq_queue_set_owner(int queueid, int client, int locked);
|
||||||
int snd_seq_queue_set_locked(int queueid, int client, int locked);
|
|
||||||
int snd_seq_queue_timer_open(int queueid);
|
int snd_seq_queue_timer_open(int queueid);
|
||||||
int snd_seq_queue_timer_close(int queueid);
|
int snd_seq_queue_timer_close(int queueid);
|
||||||
int snd_seq_queue_use(int queueid, int client, int use);
|
int snd_seq_queue_use(int queueid, int client, int use);
|
||||||
|
@ -109,8 +109,6 @@ static inline void snd_seq_inc_time_nsec(snd_seq_real_time_t *tm, unsigned long
|
|||||||
struct snd_seq_queue;
|
struct snd_seq_queue;
|
||||||
int snd_seq_timer_open(struct snd_seq_queue *q);
|
int snd_seq_timer_open(struct snd_seq_queue *q);
|
||||||
int snd_seq_timer_close(struct snd_seq_queue *q);
|
int snd_seq_timer_close(struct snd_seq_queue *q);
|
||||||
int snd_seq_timer_midi_open(struct snd_seq_queue *q);
|
|
||||||
int snd_seq_timer_midi_close(struct snd_seq_queue *q);
|
|
||||||
void snd_seq_timer_defaults(struct snd_seq_timer *tmr);
|
void snd_seq_timer_defaults(struct snd_seq_timer *tmr);
|
||||||
void snd_seq_timer_reset(struct snd_seq_timer *tmr);
|
void snd_seq_timer_reset(struct snd_seq_timer *tmr);
|
||||||
int snd_seq_timer_stop(struct snd_seq_timer *tmr);
|
int snd_seq_timer_stop(struct snd_seq_timer *tmr);
|
||||||
|
@ -23,15 +23,6 @@ enum {
|
|||||||
STR_OUT = SNDRV_RAWMIDI_STREAM_OUTPUT
|
STR_OUT = SNDRV_RAWMIDI_STREAM_OUTPUT
|
||||||
};
|
};
|
||||||
|
|
||||||
/* object per UMP group; corresponding to a sequencer port */
|
|
||||||
struct seq_ump_group {
|
|
||||||
int group; /* group index (0-based) */
|
|
||||||
unsigned int dir_bits; /* directions */
|
|
||||||
bool active; /* activeness */
|
|
||||||
bool valid; /* valid group (referred by blocks) */
|
|
||||||
char name[64]; /* seq port name */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* context for UMP input parsing, per EP */
|
/* context for UMP input parsing, per EP */
|
||||||
struct seq_ump_input_buffer {
|
struct seq_ump_input_buffer {
|
||||||
unsigned char len; /* total length in words */
|
unsigned char len; /* total length in words */
|
||||||
@ -48,7 +39,6 @@ struct seq_ump_client {
|
|||||||
int opened[2]; /* current opens for each direction */
|
int opened[2]; /* current opens for each direction */
|
||||||
struct snd_rawmidi_file out_rfile; /* rawmidi for output */
|
struct snd_rawmidi_file out_rfile; /* rawmidi for output */
|
||||||
struct seq_ump_input_buffer input; /* input parser context */
|
struct seq_ump_input_buffer input; /* input parser context */
|
||||||
struct seq_ump_group groups[SNDRV_UMP_MAX_GROUPS]; /* table of groups */
|
|
||||||
void *ump_info[SNDRV_UMP_MAX_BLOCKS + 1]; /* shadow of seq client ump_info */
|
void *ump_info[SNDRV_UMP_MAX_BLOCKS + 1]; /* shadow of seq client ump_info */
|
||||||
struct work_struct group_notify_work; /* FB change notification */
|
struct work_struct group_notify_work; /* FB change notification */
|
||||||
};
|
};
|
||||||
@ -175,7 +165,7 @@ static int seq_ump_unuse(void *pdata, struct snd_seq_port_subscribe *info)
|
|||||||
/* fill port_info from the given UMP EP and group info */
|
/* fill port_info from the given UMP EP and group info */
|
||||||
static void fill_port_info(struct snd_seq_port_info *port,
|
static void fill_port_info(struct snd_seq_port_info *port,
|
||||||
struct seq_ump_client *client,
|
struct seq_ump_client *client,
|
||||||
struct seq_ump_group *group)
|
struct snd_ump_group *group)
|
||||||
{
|
{
|
||||||
unsigned int rawmidi_info = client->ump->core.info_flags;
|
unsigned int rawmidi_info = client->ump->core.info_flags;
|
||||||
|
|
||||||
@ -199,6 +189,8 @@ static void fill_port_info(struct snd_seq_port_info *port,
|
|||||||
port->ump_group = group->group + 1;
|
port->ump_group = group->group + 1;
|
||||||
if (!group->active)
|
if (!group->active)
|
||||||
port->capability |= SNDRV_SEQ_PORT_CAP_INACTIVE;
|
port->capability |= SNDRV_SEQ_PORT_CAP_INACTIVE;
|
||||||
|
if (group->is_midi1)
|
||||||
|
port->flags |= SNDRV_SEQ_PORT_FLG_IS_MIDI1;
|
||||||
port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
|
port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
|
||||||
SNDRV_SEQ_PORT_TYPE_MIDI_UMP |
|
SNDRV_SEQ_PORT_TYPE_MIDI_UMP |
|
||||||
SNDRV_SEQ_PORT_TYPE_HARDWARE |
|
SNDRV_SEQ_PORT_TYPE_HARDWARE |
|
||||||
@ -212,7 +204,7 @@ static void fill_port_info(struct snd_seq_port_info *port,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* skip non-existing group for static blocks */
|
/* skip non-existing group for static blocks */
|
||||||
static bool skip_group(struct seq_ump_client *client, struct seq_ump_group *group)
|
static bool skip_group(struct seq_ump_client *client, struct snd_ump_group *group)
|
||||||
{
|
{
|
||||||
return !group->valid &&
|
return !group->valid &&
|
||||||
(client->ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS);
|
(client->ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS);
|
||||||
@ -221,7 +213,7 @@ static bool skip_group(struct seq_ump_client *client, struct seq_ump_group *grou
|
|||||||
/* create a new sequencer port per UMP group */
|
/* create a new sequencer port per UMP group */
|
||||||
static int seq_ump_group_init(struct seq_ump_client *client, int group_index)
|
static int seq_ump_group_init(struct seq_ump_client *client, int group_index)
|
||||||
{
|
{
|
||||||
struct seq_ump_group *group = &client->groups[group_index];
|
struct snd_ump_group *group = &client->ump->groups[group_index];
|
||||||
struct snd_seq_port_info *port __free(kfree) = NULL;
|
struct snd_seq_port_info *port __free(kfree) = NULL;
|
||||||
struct snd_seq_port_callback pcallbacks;
|
struct snd_seq_port_callback pcallbacks;
|
||||||
|
|
||||||
@ -233,7 +225,7 @@ static int seq_ump_group_init(struct seq_ump_client *client, int group_index)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
fill_port_info(port, client, group);
|
fill_port_info(port, client, group);
|
||||||
port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
|
port->flags |= SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
|
||||||
memset(&pcallbacks, 0, sizeof(pcallbacks));
|
memset(&pcallbacks, 0, sizeof(pcallbacks));
|
||||||
pcallbacks.owner = THIS_MODULE;
|
pcallbacks.owner = THIS_MODULE;
|
||||||
pcallbacks.private_data = client;
|
pcallbacks.private_data = client;
|
||||||
@ -261,7 +253,7 @@ static void update_port_infos(struct seq_ump_client *client)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) {
|
for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) {
|
||||||
if (skip_group(client, &client->groups[i]))
|
if (skip_group(client, &client->ump->groups[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
old->addr.client = client->seq_client;
|
old->addr.client = client->seq_client;
|
||||||
@ -271,7 +263,7 @@ static void update_port_infos(struct seq_ump_client *client)
|
|||||||
old);
|
old);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return;
|
return;
|
||||||
fill_port_info(new, client, &client->groups[i]);
|
fill_port_info(new, client, &client->ump->groups[i]);
|
||||||
if (old->capability == new->capability &&
|
if (old->capability == new->capability &&
|
||||||
!strcmp(old->name, new->name))
|
!strcmp(old->name, new->name))
|
||||||
continue;
|
continue;
|
||||||
@ -285,57 +277,6 @@ static void update_port_infos(struct seq_ump_client *client)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update dir_bits and active flag for all groups in the client */
|
|
||||||
static void update_group_attrs(struct seq_ump_client *client)
|
|
||||||
{
|
|
||||||
struct snd_ump_block *fb;
|
|
||||||
struct seq_ump_group *group;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) {
|
|
||||||
group = &client->groups[i];
|
|
||||||
*group->name = 0;
|
|
||||||
group->dir_bits = 0;
|
|
||||||
group->active = 0;
|
|
||||||
group->group = i;
|
|
||||||
group->valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(fb, &client->ump->block_list, list) {
|
|
||||||
if (fb->info.first_group + fb->info.num_groups > SNDRV_UMP_MAX_GROUPS)
|
|
||||||
break;
|
|
||||||
group = &client->groups[fb->info.first_group];
|
|
||||||
for (i = 0; i < fb->info.num_groups; i++, group++) {
|
|
||||||
group->valid = true;
|
|
||||||
if (fb->info.active)
|
|
||||||
group->active = 1;
|
|
||||||
switch (fb->info.direction) {
|
|
||||||
case SNDRV_UMP_DIR_INPUT:
|
|
||||||
group->dir_bits |= (1 << STR_IN);
|
|
||||||
break;
|
|
||||||
case SNDRV_UMP_DIR_OUTPUT:
|
|
||||||
group->dir_bits |= (1 << STR_OUT);
|
|
||||||
break;
|
|
||||||
case SNDRV_UMP_DIR_BIDIRECTION:
|
|
||||||
group->dir_bits |= (1 << STR_OUT) | (1 << STR_IN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!*fb->info.name)
|
|
||||||
continue;
|
|
||||||
if (!*group->name) {
|
|
||||||
/* store the first matching name */
|
|
||||||
strscpy(group->name, fb->info.name,
|
|
||||||
sizeof(group->name));
|
|
||||||
} else {
|
|
||||||
/* when overlapping, concat names */
|
|
||||||
strlcat(group->name, ", ", sizeof(group->name));
|
|
||||||
strlcat(group->name, fb->info.name,
|
|
||||||
sizeof(group->name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create a UMP Endpoint port */
|
/* create a UMP Endpoint port */
|
||||||
static int create_ump_endpoint_port(struct seq_ump_client *client)
|
static int create_ump_endpoint_port(struct seq_ump_client *client)
|
||||||
{
|
{
|
||||||
@ -432,7 +373,7 @@ static void setup_client_group_filter(struct seq_ump_client *client)
|
|||||||
return;
|
return;
|
||||||
filter = ~(1U << 0); /* always allow groupless messages */
|
filter = ~(1U << 0); /* always allow groupless messages */
|
||||||
for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) {
|
for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) {
|
||||||
if (client->groups[p].active)
|
if (client->ump->groups[p].active)
|
||||||
filter &= ~(1U << (p + 1));
|
filter &= ~(1U << (p + 1));
|
||||||
}
|
}
|
||||||
cptr->group_filter = filter;
|
cptr->group_filter = filter;
|
||||||
@ -445,7 +386,6 @@ static void handle_group_notify(struct work_struct *work)
|
|||||||
struct seq_ump_client *client =
|
struct seq_ump_client *client =
|
||||||
container_of(work, struct seq_ump_client, group_notify_work);
|
container_of(work, struct seq_ump_client, group_notify_work);
|
||||||
|
|
||||||
update_group_attrs(client);
|
|
||||||
update_port_infos(client);
|
update_port_infos(client);
|
||||||
setup_client_group_filter(client);
|
setup_client_group_filter(client);
|
||||||
}
|
}
|
||||||
@ -508,7 +448,6 @@ static int snd_seq_ump_probe(struct device *_dev)
|
|||||||
client->ump_info[fb->info.block_id + 1] = &fb->info;
|
client->ump_info[fb->info.block_id + 1] = &fb->info;
|
||||||
|
|
||||||
setup_client_midi_version(client);
|
setup_client_midi_version(client);
|
||||||
update_group_attrs(client);
|
|
||||||
|
|
||||||
for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) {
|
for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) {
|
||||||
err = seq_ump_group_init(client, p);
|
err = seq_ump_group_init(client, p);
|
||||||
|
@ -595,12 +595,13 @@ int snd_seq_deliver_from_ump(struct snd_seq_client *source,
|
|||||||
type = ump_message_type(ump_ev->ump[0]);
|
type = ump_message_type(ump_ev->ump[0]);
|
||||||
|
|
||||||
if (snd_seq_client_is_ump(dest)) {
|
if (snd_seq_client_is_ump(dest)) {
|
||||||
if (snd_seq_client_is_midi2(dest) &&
|
bool is_midi2 = snd_seq_client_is_midi2(dest) &&
|
||||||
type == UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE)
|
!dest_port->is_midi1;
|
||||||
|
|
||||||
|
if (is_midi2 && type == UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE)
|
||||||
return cvt_ump_midi1_to_midi2(dest, dest_port,
|
return cvt_ump_midi1_to_midi2(dest, dest_port,
|
||||||
event, atomic, hop);
|
event, atomic, hop);
|
||||||
else if (!snd_seq_client_is_midi2(dest) &&
|
else if (!is_midi2 && type == UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE)
|
||||||
type == UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE)
|
|
||||||
return cvt_ump_midi2_to_midi1(dest, dest_port,
|
return cvt_ump_midi2_to_midi1(dest, dest_port,
|
||||||
event, atomic, hop);
|
event, atomic, hop);
|
||||||
/* non-EP port and different group is set? */
|
/* non-EP port and different group is set? */
|
||||||
@ -1279,7 +1280,7 @@ int snd_seq_deliver_to_ump(struct snd_seq_client *source,
|
|||||||
return 0; /* group filtered - skip the event */
|
return 0; /* group filtered - skip the event */
|
||||||
if (event->type == SNDRV_SEQ_EVENT_SYSEX)
|
if (event->type == SNDRV_SEQ_EVENT_SYSEX)
|
||||||
return cvt_sysex_to_ump(dest, dest_port, event, atomic, hop);
|
return cvt_sysex_to_ump(dest, dest_port, event, atomic, hop);
|
||||||
else if (snd_seq_client_is_midi2(dest))
|
else if (snd_seq_client_is_midi2(dest) && !dest_port->is_midi1)
|
||||||
return cvt_to_ump_midi2(dest, dest_port, event, atomic, hop);
|
return cvt_to_ump_midi2(dest, dest_port, event, atomic, hop);
|
||||||
else
|
else
|
||||||
return cvt_to_ump_midi1(dest, dest_port, event, atomic, hop);
|
return cvt_to_ump_midi1(dest, dest_port, event, atomic, hop);
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/sched/signal.h>
|
#include <linux/sched/signal.h>
|
||||||
|
#include <linux/anon_inodes.h>
|
||||||
|
#include <linux/idr.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/timer.h>
|
#include <sound/timer.h>
|
||||||
#include <sound/control.h>
|
#include <sound/control.h>
|
||||||
@ -109,6 +111,16 @@ struct snd_timer_status64 {
|
|||||||
unsigned char reserved[64]; /* reserved */
|
unsigned char reserved[64]; /* reserved */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_SND_UTIMER
|
||||||
|
#define SNDRV_UTIMERS_MAX_COUNT 128
|
||||||
|
/* Internal data structure for keeping the state of the userspace-driven timer */
|
||||||
|
struct snd_utimer {
|
||||||
|
char *name;
|
||||||
|
struct snd_timer *timer;
|
||||||
|
unsigned int id;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SNDRV_TIMER_IOCTL_STATUS64 _IOR('T', 0x14, struct snd_timer_status64)
|
#define SNDRV_TIMER_IOCTL_STATUS64 _IOR('T', 0x14, struct snd_timer_status64)
|
||||||
|
|
||||||
/* list of timers */
|
/* list of timers */
|
||||||
@ -1162,7 +1174,7 @@ static int snd_timer_s_close(struct snd_timer *timer)
|
|||||||
static const struct snd_timer_hardware snd_timer_system =
|
static const struct snd_timer_hardware snd_timer_system =
|
||||||
{
|
{
|
||||||
.flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_WORK,
|
.flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_WORK,
|
||||||
.resolution = 1000000000L / HZ,
|
.resolution = NSEC_PER_SEC / HZ,
|
||||||
.ticks = 10000000L,
|
.ticks = 10000000L,
|
||||||
.close = snd_timer_s_close,
|
.close = snd_timer_s_close,
|
||||||
.start = snd_timer_s_start,
|
.start = snd_timer_s_start,
|
||||||
@ -1603,7 +1615,7 @@ static int snd_timer_user_ginfo(struct file *file,
|
|||||||
|
|
||||||
ginfo = memdup_user(_ginfo, sizeof(*ginfo));
|
ginfo = memdup_user(_ginfo, sizeof(*ginfo));
|
||||||
if (IS_ERR(ginfo))
|
if (IS_ERR(ginfo))
|
||||||
return PTR_ERR(no_free_ptr(ginfo));
|
return PTR_ERR(ginfo);
|
||||||
|
|
||||||
tid = ginfo->tid;
|
tid = ginfo->tid;
|
||||||
memset(ginfo, 0, sizeof(*ginfo));
|
memset(ginfo, 0, sizeof(*ginfo));
|
||||||
@ -2009,6 +2021,217 @@ enum {
|
|||||||
SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
|
SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_SND_UTIMER
|
||||||
|
/*
|
||||||
|
* Since userspace-driven timers are passed to userspace, we need to have an identifier
|
||||||
|
* which will allow us to use them (basically, the subdevice number of udriven timer).
|
||||||
|
*/
|
||||||
|
static DEFINE_IDA(snd_utimer_ids);
|
||||||
|
|
||||||
|
static void snd_utimer_put_id(struct snd_utimer *utimer)
|
||||||
|
{
|
||||||
|
int timer_id = utimer->id;
|
||||||
|
|
||||||
|
snd_BUG_ON(timer_id < 0 || timer_id >= SNDRV_UTIMERS_MAX_COUNT);
|
||||||
|
ida_free(&snd_utimer_ids, timer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_utimer_take_id(void)
|
||||||
|
{
|
||||||
|
return ida_alloc_max(&snd_utimer_ids, SNDRV_UTIMERS_MAX_COUNT - 1, GFP_KERNEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void snd_utimer_free(struct snd_utimer *utimer)
|
||||||
|
{
|
||||||
|
snd_timer_free(utimer->timer);
|
||||||
|
snd_utimer_put_id(utimer);
|
||||||
|
kfree(utimer->name);
|
||||||
|
kfree(utimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_utimer_release(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
struct snd_utimer *utimer = (struct snd_utimer *)file->private_data;
|
||||||
|
|
||||||
|
snd_utimer_free(utimer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_utimer_trigger(struct file *file)
|
||||||
|
{
|
||||||
|
struct snd_utimer *utimer = (struct snd_utimer *)file->private_data;
|
||||||
|
|
||||||
|
snd_timer_interrupt(utimer->timer, utimer->timer->sticks);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long snd_utimer_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
|
||||||
|
{
|
||||||
|
switch (ioctl) {
|
||||||
|
case SNDRV_TIMER_IOCTL_TRIGGER:
|
||||||
|
return snd_utimer_trigger(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations snd_utimer_fops = {
|
||||||
|
.llseek = noop_llseek,
|
||||||
|
.release = snd_utimer_release,
|
||||||
|
.unlocked_ioctl = snd_utimer_ioctl,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int snd_utimer_start(struct snd_timer *t)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_utimer_stop(struct snd_timer *t)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_utimer_open(struct snd_timer *t)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_utimer_close(struct snd_timer *t)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct snd_timer_hardware timer_hw = {
|
||||||
|
.flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_WORK,
|
||||||
|
.open = snd_utimer_open,
|
||||||
|
.close = snd_utimer_close,
|
||||||
|
.start = snd_utimer_start,
|
||||||
|
.stop = snd_utimer_stop,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int snd_utimer_create(struct snd_timer_uinfo *utimer_info,
|
||||||
|
struct snd_utimer **r_utimer)
|
||||||
|
{
|
||||||
|
struct snd_utimer *utimer;
|
||||||
|
struct snd_timer *timer;
|
||||||
|
struct snd_timer_id tid;
|
||||||
|
int utimer_id;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (!utimer_info || utimer_info->resolution == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
utimer = kzalloc(sizeof(*utimer), GFP_KERNEL);
|
||||||
|
if (!utimer)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* We hold the ioctl lock here so we won't get a race condition when allocating id */
|
||||||
|
utimer_id = snd_utimer_take_id();
|
||||||
|
if (utimer_id < 0) {
|
||||||
|
err = utimer_id;
|
||||||
|
goto err_take_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
utimer->name = kasprintf(GFP_KERNEL, "snd-utimer%d", utimer_id);
|
||||||
|
if (!utimer->name) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto err_get_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
utimer->id = utimer_id;
|
||||||
|
|
||||||
|
tid.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
|
||||||
|
tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL;
|
||||||
|
tid.card = -1;
|
||||||
|
tid.device = SNDRV_TIMER_GLOBAL_UDRIVEN;
|
||||||
|
tid.subdevice = utimer_id;
|
||||||
|
|
||||||
|
err = snd_timer_new(NULL, utimer->name, &tid, &timer);
|
||||||
|
if (err < 0) {
|
||||||
|
pr_err("Can't create userspace-driven timer\n");
|
||||||
|
goto err_timer_new;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer->module = THIS_MODULE;
|
||||||
|
timer->hw = timer_hw;
|
||||||
|
timer->hw.resolution = utimer_info->resolution;
|
||||||
|
timer->hw.ticks = 1;
|
||||||
|
timer->max_instances = MAX_SLAVE_INSTANCES;
|
||||||
|
|
||||||
|
utimer->timer = timer;
|
||||||
|
|
||||||
|
err = snd_timer_global_register(timer);
|
||||||
|
if (err < 0) {
|
||||||
|
pr_err("Can't register a userspace-driven timer\n");
|
||||||
|
goto err_timer_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
*r_utimer = utimer;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_timer_reg:
|
||||||
|
snd_timer_free(timer);
|
||||||
|
err_timer_new:
|
||||||
|
kfree(utimer->name);
|
||||||
|
err_get_name:
|
||||||
|
snd_utimer_put_id(utimer);
|
||||||
|
err_take_id:
|
||||||
|
kfree(utimer);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_utimer_ioctl_create(struct file *file,
|
||||||
|
struct snd_timer_uinfo __user *_utimer_info)
|
||||||
|
{
|
||||||
|
struct snd_utimer *utimer;
|
||||||
|
struct snd_timer_uinfo *utimer_info __free(kfree) = NULL;
|
||||||
|
int err, timer_fd;
|
||||||
|
|
||||||
|
utimer_info = memdup_user(_utimer_info, sizeof(*utimer_info));
|
||||||
|
if (IS_ERR(utimer_info))
|
||||||
|
return PTR_ERR(utimer_info);
|
||||||
|
|
||||||
|
err = snd_utimer_create(utimer_info, &utimer);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
utimer_info->id = utimer->id;
|
||||||
|
|
||||||
|
timer_fd = anon_inode_getfd(utimer->name, &snd_utimer_fops, utimer, O_RDWR | O_CLOEXEC);
|
||||||
|
if (timer_fd < 0) {
|
||||||
|
snd_utimer_free(utimer);
|
||||||
|
return timer_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
utimer_info->fd = timer_fd;
|
||||||
|
|
||||||
|
err = copy_to_user(_utimer_info, utimer_info, sizeof(*utimer_info));
|
||||||
|
if (err) {
|
||||||
|
/*
|
||||||
|
* "Leak" the fd, as there is nothing we can do about it.
|
||||||
|
* It might have been closed already since anon_inode_getfd
|
||||||
|
* makes it available for userspace.
|
||||||
|
*
|
||||||
|
* We have to rely on the process exit path to do any
|
||||||
|
* necessary cleanup (e.g. releasing the file).
|
||||||
|
*/
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static int snd_utimer_ioctl_create(struct file *file,
|
||||||
|
struct snd_timer_uinfo __user *_utimer_info)
|
||||||
|
{
|
||||||
|
return -ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
||||||
unsigned long arg, bool compat)
|
unsigned long arg, bool compat)
|
||||||
{
|
{
|
||||||
@ -2053,6 +2276,8 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
|||||||
case SNDRV_TIMER_IOCTL_PAUSE:
|
case SNDRV_TIMER_IOCTL_PAUSE:
|
||||||
case SNDRV_TIMER_IOCTL_PAUSE_OLD:
|
case SNDRV_TIMER_IOCTL_PAUSE_OLD:
|
||||||
return snd_timer_user_pause(file);
|
return snd_timer_user_pause(file);
|
||||||
|
case SNDRV_TIMER_IOCTL_CREATE:
|
||||||
|
return snd_utimer_ioctl_create(file, argp);
|
||||||
}
|
}
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
}
|
}
|
||||||
|
120
sound/core/ump.c
120
sound/core/ump.c
@ -489,11 +489,7 @@ static void snd_ump_proc_read(struct snd_info_entry *entry,
|
|||||||
ump->info.manufacturer_id);
|
ump->info.manufacturer_id);
|
||||||
snd_iprintf(buffer, "Family ID: 0x%04x\n", ump->info.family_id);
|
snd_iprintf(buffer, "Family ID: 0x%04x\n", ump->info.family_id);
|
||||||
snd_iprintf(buffer, "Model ID: 0x%04x\n", ump->info.model_id);
|
snd_iprintf(buffer, "Model ID: 0x%04x\n", ump->info.model_id);
|
||||||
snd_iprintf(buffer, "SW Revision: 0x%02x%02x%02x%02x\n",
|
snd_iprintf(buffer, "SW Revision: 0x%4phN\n", ump->info.sw_revision);
|
||||||
ump->info.sw_revision[0],
|
|
||||||
ump->info.sw_revision[1],
|
|
||||||
ump->info.sw_revision[2],
|
|
||||||
ump->info.sw_revision[3]);
|
|
||||||
}
|
}
|
||||||
snd_iprintf(buffer, "Static Blocks: %s\n",
|
snd_iprintf(buffer, "Static Blocks: %s\n",
|
||||||
(ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS) ? "Yes" : "No");
|
(ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS) ? "Yes" : "No");
|
||||||
@ -524,6 +520,62 @@ static void snd_ump_proc_read(struct snd_info_entry *entry,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update dir_bits and active flag for all groups in the client */
|
||||||
|
void snd_ump_update_group_attrs(struct snd_ump_endpoint *ump)
|
||||||
|
{
|
||||||
|
struct snd_ump_block *fb;
|
||||||
|
struct snd_ump_group *group;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) {
|
||||||
|
group = &ump->groups[i];
|
||||||
|
*group->name = 0;
|
||||||
|
group->dir_bits = 0;
|
||||||
|
group->active = 0;
|
||||||
|
group->group = i;
|
||||||
|
group->valid = false;
|
||||||
|
group->is_midi1 = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(fb, &ump->block_list, list) {
|
||||||
|
if (fb->info.first_group + fb->info.num_groups > SNDRV_UMP_MAX_GROUPS)
|
||||||
|
break;
|
||||||
|
group = &ump->groups[fb->info.first_group];
|
||||||
|
for (i = 0; i < fb->info.num_groups; i++, group++) {
|
||||||
|
group->valid = true;
|
||||||
|
if (fb->info.active)
|
||||||
|
group->active = 1;
|
||||||
|
if (fb->info.flags & SNDRV_UMP_BLOCK_IS_MIDI1)
|
||||||
|
group->is_midi1 = true;
|
||||||
|
switch (fb->info.direction) {
|
||||||
|
case SNDRV_UMP_DIR_INPUT:
|
||||||
|
group->dir_bits |= (1 << SNDRV_RAWMIDI_STREAM_INPUT);
|
||||||
|
break;
|
||||||
|
case SNDRV_UMP_DIR_OUTPUT:
|
||||||
|
group->dir_bits |= (1 << SNDRV_RAWMIDI_STREAM_OUTPUT);
|
||||||
|
break;
|
||||||
|
case SNDRV_UMP_DIR_BIDIRECTION:
|
||||||
|
group->dir_bits |= (1 << SNDRV_RAWMIDI_STREAM_INPUT) |
|
||||||
|
(1 << SNDRV_RAWMIDI_STREAM_OUTPUT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!*fb->info.name)
|
||||||
|
continue;
|
||||||
|
if (!*group->name) {
|
||||||
|
/* store the first matching name */
|
||||||
|
strscpy(group->name, fb->info.name,
|
||||||
|
sizeof(group->name));
|
||||||
|
} else {
|
||||||
|
/* when overlapping, concat names */
|
||||||
|
strlcat(group->name, ", ", sizeof(group->name));
|
||||||
|
strlcat(group->name, fb->info.name,
|
||||||
|
sizeof(group->name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_ump_update_group_attrs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UMP endpoint and function block handling
|
* UMP endpoint and function block handling
|
||||||
*/
|
*/
|
||||||
@ -602,6 +654,17 @@ static int ump_append_string(struct snd_ump_endpoint *ump, char *dest,
|
|||||||
format == UMP_STREAM_MSG_FORMAT_END);
|
format == UMP_STREAM_MSG_FORMAT_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Choose the default protocol */
|
||||||
|
static void choose_default_protocol(struct snd_ump_endpoint *ump)
|
||||||
|
{
|
||||||
|
if (ump->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK)
|
||||||
|
return;
|
||||||
|
if (ump->info.protocol_caps & SNDRV_UMP_EP_INFO_PROTO_MIDI2)
|
||||||
|
ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI2;
|
||||||
|
else
|
||||||
|
ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI1;
|
||||||
|
}
|
||||||
|
|
||||||
/* handle EP info stream message; update the UMP attributes */
|
/* handle EP info stream message; update the UMP attributes */
|
||||||
static int ump_handle_ep_info_msg(struct snd_ump_endpoint *ump,
|
static int ump_handle_ep_info_msg(struct snd_ump_endpoint *ump,
|
||||||
const union snd_ump_stream_msg *buf)
|
const union snd_ump_stream_msg *buf)
|
||||||
@ -623,6 +686,10 @@ static int ump_handle_ep_info_msg(struct snd_ump_endpoint *ump,
|
|||||||
|
|
||||||
ump_dbg(ump, "EP info: version=%x, num_blocks=%x, proto_caps=%x\n",
|
ump_dbg(ump, "EP info: version=%x, num_blocks=%x, proto_caps=%x\n",
|
||||||
ump->info.version, ump->info.num_blocks, ump->info.protocol_caps);
|
ump->info.version, ump->info.num_blocks, ump->info.protocol_caps);
|
||||||
|
|
||||||
|
ump->info.protocol &= ump->info.protocol_caps;
|
||||||
|
choose_default_protocol(ump);
|
||||||
|
|
||||||
return 1; /* finished */
|
return 1; /* finished */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,14 +706,11 @@ static int ump_handle_device_info_msg(struct snd_ump_endpoint *ump,
|
|||||||
ump->info.sw_revision[1] = (buf->device_info.sw_revision >> 16) & 0x7f;
|
ump->info.sw_revision[1] = (buf->device_info.sw_revision >> 16) & 0x7f;
|
||||||
ump->info.sw_revision[2] = (buf->device_info.sw_revision >> 8) & 0x7f;
|
ump->info.sw_revision[2] = (buf->device_info.sw_revision >> 8) & 0x7f;
|
||||||
ump->info.sw_revision[3] = buf->device_info.sw_revision & 0x7f;
|
ump->info.sw_revision[3] = buf->device_info.sw_revision & 0x7f;
|
||||||
ump_dbg(ump, "EP devinfo: manid=%08x, family=%04x, model=%04x, sw=%02x%02x%02x%02x\n",
|
ump_dbg(ump, "EP devinfo: manid=%08x, family=%04x, model=%04x, sw=%4phN\n",
|
||||||
ump->info.manufacturer_id,
|
ump->info.manufacturer_id,
|
||||||
ump->info.family_id,
|
ump->info.family_id,
|
||||||
ump->info.model_id,
|
ump->info.model_id,
|
||||||
ump->info.sw_revision[0],
|
ump->info.sw_revision);
|
||||||
ump->info.sw_revision[1],
|
|
||||||
ump->info.sw_revision[2],
|
|
||||||
ump->info.sw_revision[3]);
|
|
||||||
return 1; /* finished */
|
return 1; /* finished */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -792,8 +856,10 @@ static int ump_handle_fb_info_msg(struct snd_ump_endpoint *ump,
|
|||||||
|
|
||||||
if (fb) {
|
if (fb) {
|
||||||
fill_fb_info(ump, &fb->info, buf);
|
fill_fb_info(ump, &fb->info, buf);
|
||||||
if (ump->parsed)
|
if (ump->parsed) {
|
||||||
|
snd_ump_update_group_attrs(ump);
|
||||||
seq_notify_fb_change(ump, fb);
|
seq_notify_fb_change(ump, fb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1; /* finished */
|
return 1; /* finished */
|
||||||
@ -822,8 +888,10 @@ static int ump_handle_fb_name_msg(struct snd_ump_endpoint *ump,
|
|||||||
ret = ump_append_string(ump, fb->info.name, sizeof(fb->info.name),
|
ret = ump_append_string(ump, fb->info.name, sizeof(fb->info.name),
|
||||||
buf->raw, 3);
|
buf->raw, 3);
|
||||||
/* notify the FB name update to sequencer, too */
|
/* notify the FB name update to sequencer, too */
|
||||||
if (ret > 0 && ump->parsed)
|
if (ret > 0 && ump->parsed) {
|
||||||
|
snd_ump_update_group_attrs(ump);
|
||||||
seq_notify_fb_change(ump, fb);
|
seq_notify_fb_change(ump, fb);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -981,12 +1049,7 @@ int snd_ump_parse_endpoint(struct snd_ump_endpoint *ump)
|
|||||||
ump_dbg(ump, "Unable to get UMP EP stream config\n");
|
ump_dbg(ump, "Unable to get UMP EP stream config\n");
|
||||||
|
|
||||||
/* If no protocol is set by some reason, assume the valid one */
|
/* If no protocol is set by some reason, assume the valid one */
|
||||||
if (!(ump->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK)) {
|
choose_default_protocol(ump);
|
||||||
if (ump->info.protocol_caps & SNDRV_UMP_EP_INFO_PROTO_MIDI2)
|
|
||||||
ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI2;
|
|
||||||
else if (ump->info.protocol_caps & SNDRV_UMP_EP_INFO_PROTO_MIDI1)
|
|
||||||
ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Query and create blocks from Function Blocks */
|
/* Query and create blocks from Function Blocks */
|
||||||
for (blk = 0; blk < ump->info.num_blocks; blk++) {
|
for (blk = 0; blk < ump->info.num_blocks; blk++) {
|
||||||
@ -995,6 +1058,9 @@ int snd_ump_parse_endpoint(struct snd_ump_endpoint *ump)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* initialize group attributions */
|
||||||
|
snd_ump_update_group_attrs(ump);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
ump->parsed = true;
|
ump->parsed = true;
|
||||||
ump_request_close(ump);
|
ump_request_close(ump);
|
||||||
@ -1097,6 +1163,7 @@ static int process_legacy_output(struct snd_ump_endpoint *ump,
|
|||||||
struct snd_rawmidi_substream *substream;
|
struct snd_rawmidi_substream *substream;
|
||||||
struct ump_cvt_to_ump *ctx;
|
struct ump_cvt_to_ump *ctx;
|
||||||
const int dir = SNDRV_RAWMIDI_STREAM_OUTPUT;
|
const int dir = SNDRV_RAWMIDI_STREAM_OUTPUT;
|
||||||
|
unsigned int protocol;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
int group, size = 0;
|
int group, size = 0;
|
||||||
|
|
||||||
@ -1109,9 +1176,13 @@ static int process_legacy_output(struct snd_ump_endpoint *ump,
|
|||||||
if (!substream)
|
if (!substream)
|
||||||
continue;
|
continue;
|
||||||
ctx = &ump->out_cvts[group];
|
ctx = &ump->out_cvts[group];
|
||||||
|
protocol = ump->info.protocol;
|
||||||
|
if ((protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI2) &&
|
||||||
|
ump->groups[group].is_midi1)
|
||||||
|
protocol = SNDRV_UMP_EP_INFO_PROTO_MIDI1;
|
||||||
while (!ctx->ump_bytes &&
|
while (!ctx->ump_bytes &&
|
||||||
snd_rawmidi_transmit(substream, &c, 1) > 0)
|
snd_rawmidi_transmit(substream, &c, 1) > 0)
|
||||||
snd_ump_convert_to_ump(ctx, group, ump->info.protocol, c);
|
snd_ump_convert_to_ump(ctx, group, protocol, c);
|
||||||
if (ctx->ump_bytes && ctx->ump_bytes <= count) {
|
if (ctx->ump_bytes && ctx->ump_bytes <= count) {
|
||||||
size = ctx->ump_bytes;
|
size = ctx->ump_bytes;
|
||||||
memcpy(buffer, ctx->ump, size);
|
memcpy(buffer, ctx->ump, size);
|
||||||
@ -1172,10 +1243,17 @@ static void fill_substream_names(struct snd_ump_endpoint *ump,
|
|||||||
struct snd_rawmidi *rmidi, int dir)
|
struct snd_rawmidi *rmidi, int dir)
|
||||||
{
|
{
|
||||||
struct snd_rawmidi_substream *s;
|
struct snd_rawmidi_substream *s;
|
||||||
|
const char *name;
|
||||||
|
int idx;
|
||||||
|
|
||||||
list_for_each_entry(s, &rmidi->streams[dir].substreams, list)
|
list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
|
||||||
|
idx = ump->legacy_mapping[s->number];
|
||||||
|
name = ump->groups[idx].name;
|
||||||
|
if (!*name)
|
||||||
|
name = ump->info.name;
|
||||||
snprintf(s->name, sizeof(s->name), "Group %d (%.16s)",
|
snprintf(s->name, sizeof(s->name), "Group %d (%.16s)",
|
||||||
ump->legacy_mapping[s->number] + 1, ump->info.name);
|
idx + 1, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
|
int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
|
||||||
|
@ -900,8 +900,7 @@ static void loopback_snd_timer_dpcm_info(struct loopback_pcm *dpcm,
|
|||||||
cable->snd_timer.id.device,
|
cable->snd_timer.id.device,
|
||||||
cable->snd_timer.id.subdevice);
|
cable->snd_timer.id.subdevice);
|
||||||
snd_iprintf(buffer, " timer open:\t\t%s\n",
|
snd_iprintf(buffer, " timer open:\t\t%s\n",
|
||||||
(cable->snd_timer.stream == SNDRV_PCM_STREAM_CAPTURE) ?
|
snd_pcm_direction_name(cable->snd_timer.stream));
|
||||||
"capture" : "playback");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
|
static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
|
||||||
@ -1130,6 +1129,8 @@ static int loopback_parse_timer_id(const char *str,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (card_idx == -1)
|
||||||
|
tid->dev_class = SNDRV_TIMER_CLASS_GLOBAL;
|
||||||
if (!err && tid) {
|
if (!err && tid) {
|
||||||
tid->card = card_idx;
|
tid->card = card_idx;
|
||||||
tid->device = dev;
|
tid->device = dev;
|
||||||
@ -1897,7 +1898,7 @@ static int __init alsa_card_loopback_init(void)
|
|||||||
}
|
}
|
||||||
if (!cards) {
|
if (!cards) {
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
printk(KERN_ERR "aloop: No loopback enabled\n");
|
pr_err("aloop: No loopback enabled\n");
|
||||||
#endif
|
#endif
|
||||||
loopback_unregister_all();
|
loopback_unregister_all();
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -1033,8 +1033,7 @@ static int snd_dummy_probe(struct platform_device *devptr)
|
|||||||
dummy->card = card;
|
dummy->card = card;
|
||||||
for (mdl = dummy_models; *mdl && model[dev]; mdl++) {
|
for (mdl = dummy_models; *mdl && model[dev]; mdl++) {
|
||||||
if (strcmp(model[dev], (*mdl)->name) == 0) {
|
if (strcmp(model[dev], (*mdl)->name) == 0) {
|
||||||
printk(KERN_INFO
|
pr_info("snd-dummy: Using model '%s' for card %i\n",
|
||||||
"snd-dummy: Using model '%s' for card %i\n",
|
|
||||||
(*mdl)->name, card->number);
|
(*mdl)->name, card->number);
|
||||||
m = dummy->model = *mdl;
|
m = dummy->model = *mdl;
|
||||||
break;
|
break;
|
||||||
@ -1168,7 +1167,7 @@ static int __init alsa_card_dummy_init(void)
|
|||||||
}
|
}
|
||||||
if (!cards) {
|
if (!cards) {
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
printk(KERN_ERR "Dummy soundcard not found or device busy\n");
|
pr_err("Dummy soundcard not found or device busy\n");
|
||||||
#endif
|
#endif
|
||||||
snd_dummy_unregister_all();
|
snd_dummy_unregister_all();
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -56,7 +56,7 @@ static int snd_mpu401_create(struct device *devptr, int dev,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!uart_enter[dev])
|
if (!uart_enter[dev])
|
||||||
snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n");
|
dev_err(devptr, "the uart_enter option is obsolete; remove it\n");
|
||||||
|
|
||||||
*rcard = NULL;
|
*rcard = NULL;
|
||||||
err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
|
err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
|
||||||
@ -75,7 +75,7 @@ static int snd_mpu401_create(struct device *devptr, int dev,
|
|||||||
err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0,
|
err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0,
|
||||||
irq[dev], NULL);
|
irq[dev], NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
|
dev_err(devptr, "MPU401 not detected at 0x%lx\n", port[dev]);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,11 +90,11 @@ static int snd_mpu401_probe(struct platform_device *devptr)
|
|||||||
struct snd_card *card;
|
struct snd_card *card;
|
||||||
|
|
||||||
if (port[dev] == SNDRV_AUTO_PORT) {
|
if (port[dev] == SNDRV_AUTO_PORT) {
|
||||||
snd_printk(KERN_ERR "specify port\n");
|
dev_err(&devptr->dev, "specify port\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (irq[dev] == SNDRV_AUTO_IRQ) {
|
if (irq[dev] == SNDRV_AUTO_IRQ) {
|
||||||
snd_printk(KERN_ERR "specify or disable IRQ\n");
|
dev_err(&devptr->dev, "specify or disable IRQ\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
err = snd_mpu401_create(&devptr->dev, dev, &card);
|
err = snd_mpu401_create(&devptr->dev, dev, &card);
|
||||||
@ -133,11 +133,11 @@ static int snd_mpu401_pnp(int dev, struct pnp_dev *device,
|
|||||||
{
|
{
|
||||||
if (!pnp_port_valid(device, 0) ||
|
if (!pnp_port_valid(device, 0) ||
|
||||||
pnp_port_flags(device, 0) & IORESOURCE_DISABLED) {
|
pnp_port_flags(device, 0) & IORESOURCE_DISABLED) {
|
||||||
snd_printk(KERN_ERR "no PnP port\n");
|
dev_err(&device->dev, "no PnP port\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
if (pnp_port_len(device, 0) < IO_EXTENT) {
|
if (pnp_port_len(device, 0) < IO_EXTENT) {
|
||||||
snd_printk(KERN_ERR "PnP port length is %llu, expected %d\n",
|
dev_err(&device->dev, "PnP port length is %llu, expected %d\n",
|
||||||
(unsigned long long)pnp_port_len(device, 0),
|
(unsigned long long)pnp_port_len(device, 0),
|
||||||
IO_EXTENT);
|
IO_EXTENT);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -146,7 +146,7 @@ static int snd_mpu401_pnp(int dev, struct pnp_dev *device,
|
|||||||
|
|
||||||
if (!pnp_irq_valid(device, 0) ||
|
if (!pnp_irq_valid(device, 0) ||
|
||||||
pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) {
|
pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) {
|
||||||
snd_printk(KERN_WARNING "no PnP irq, using polling\n");
|
dev_warn(&device->dev, "no PnP irq, using polling\n");
|
||||||
irq[dev] = -1;
|
irq[dev] = -1;
|
||||||
} else {
|
} else {
|
||||||
irq[dev] = pnp_irq(device, 0);
|
irq[dev] = pnp_irq(device, 0);
|
||||||
@ -234,7 +234,7 @@ static int __init alsa_card_mpu401_init(void)
|
|||||||
|
|
||||||
if (!snd_mpu401_devices) {
|
if (!snd_mpu401_devices) {
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
printk(KERN_ERR "MPU-401 device not found or device busy\n");
|
pr_err("MPU-401 device not found or device busy\n");
|
||||||
#endif
|
#endif
|
||||||
snd_mpu401_unregister_all();
|
snd_mpu401_unregister_all();
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -73,8 +73,9 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu)
|
|||||||
mpu->read(mpu, MPU401D(mpu));
|
mpu->read(mpu, MPU401D(mpu));
|
||||||
#ifdef CONFIG_SND_DEBUG
|
#ifdef CONFIG_SND_DEBUG
|
||||||
if (timeout <= 0)
|
if (timeout <= 0)
|
||||||
snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n",
|
dev_err(mpu->rmidi->dev,
|
||||||
mpu->read(mpu, MPU401C(mpu)));
|
"cmd: clear rx timeout (status = 0x%x)\n",
|
||||||
|
mpu->read(mpu, MPU401C(mpu)));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,8 +225,9 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
|
|||||||
udelay(10);
|
udelay(10);
|
||||||
#ifdef CONFIG_SND_DEBUG
|
#ifdef CONFIG_SND_DEBUG
|
||||||
if (!timeout)
|
if (!timeout)
|
||||||
snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n",
|
dev_err(mpu->rmidi->dev,
|
||||||
mpu->read(mpu, MPU401C(mpu)));
|
"cmd: tx timeout (status = 0x%x)\n",
|
||||||
|
mpu->read(mpu, MPU401C(mpu)));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
mpu->write(mpu, cmd, MPU401C(mpu));
|
mpu->write(mpu, cmd, MPU401C(mpu));
|
||||||
@ -244,10 +246,11 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
|
|||||||
ok = 1;
|
ok = 1;
|
||||||
spin_unlock_irqrestore(&mpu->input_lock, flags);
|
spin_unlock_irqrestore(&mpu->input_lock, flags);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx "
|
dev_err(mpu->rmidi->dev,
|
||||||
"(status = 0x%x, data = 0x%x)\n", cmd, mpu->port,
|
"cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n",
|
||||||
mpu->read(mpu, MPU401C(mpu)),
|
cmd, mpu->port,
|
||||||
mpu->read(mpu, MPU401D(mpu)));
|
mpu->read(mpu, MPU401C(mpu)),
|
||||||
|
mpu->read(mpu, MPU401D(mpu)));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -546,13 +549,14 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
|
|||||||
spin_lock_init(&mpu->timer_lock);
|
spin_lock_init(&mpu->timer_lock);
|
||||||
mpu->hardware = hardware;
|
mpu->hardware = hardware;
|
||||||
mpu->irq = -1;
|
mpu->irq = -1;
|
||||||
|
mpu->rmidi = rmidi;
|
||||||
if (! (info_flags & MPU401_INFO_INTEGRATED)) {
|
if (! (info_flags & MPU401_INFO_INTEGRATED)) {
|
||||||
int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
|
int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
|
||||||
mpu->res = request_region(port, res_size, "MPU401 UART");
|
mpu->res = request_region(port, res_size, "MPU401 UART");
|
||||||
if (!mpu->res) {
|
if (!mpu->res) {
|
||||||
snd_printk(KERN_ERR "mpu401_uart: "
|
dev_err(rmidi->dev,
|
||||||
"unable to grab port 0x%lx size %d\n",
|
"mpu401_uart: unable to grab port 0x%lx size %d\n",
|
||||||
port, res_size);
|
port, res_size);
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
goto free_device;
|
goto free_device;
|
||||||
}
|
}
|
||||||
@ -572,8 +576,8 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
|
|||||||
if (irq >= 0) {
|
if (irq >= 0) {
|
||||||
if (request_irq(irq, snd_mpu401_uart_interrupt, 0,
|
if (request_irq(irq, snd_mpu401_uart_interrupt, 0,
|
||||||
"MPU401 UART", (void *) mpu)) {
|
"MPU401 UART", (void *) mpu)) {
|
||||||
snd_printk(KERN_ERR "mpu401_uart: "
|
dev_err(rmidi->dev,
|
||||||
"unable to grab IRQ %d\n", irq);
|
"mpu401_uart: unable to grab IRQ %d\n", irq);
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
goto free_device;
|
goto free_device;
|
||||||
}
|
}
|
||||||
@ -599,7 +603,6 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
|
|||||||
if (out_enable)
|
if (out_enable)
|
||||||
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
|
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
|
||||||
}
|
}
|
||||||
mpu->rmidi = rmidi;
|
|
||||||
if (rrawmidi)
|
if (rrawmidi)
|
||||||
*rrawmidi = rmidi;
|
*rrawmidi = rmidi;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -285,10 +285,6 @@ static void snd_mtpav_output_port_write(struct mtpav *mtp_card,
|
|||||||
|
|
||||||
snd_mtpav_send_byte(mtp_card, 0xf5);
|
snd_mtpav_send_byte(mtp_card, 0xf5);
|
||||||
snd_mtpav_send_byte(mtp_card, portp->hwport);
|
snd_mtpav_send_byte(mtp_card, portp->hwport);
|
||||||
/*
|
|
||||||
snd_printk(KERN_DEBUG "new outport: 0x%x\n",
|
|
||||||
(unsigned int) portp->hwport);
|
|
||||||
*/
|
|
||||||
if (!(outbyte & 0x80) && portp->running_status)
|
if (!(outbyte & 0x80) && portp->running_status)
|
||||||
snd_mtpav_send_byte(mtp_card, portp->running_status);
|
snd_mtpav_send_byte(mtp_card, portp->running_status);
|
||||||
}
|
}
|
||||||
@ -522,8 +518,6 @@ static void snd_mtpav_read_bytes(struct mtpav *mcrd)
|
|||||||
|
|
||||||
u8 sbyt = snd_mtpav_getreg(mcrd, SREG);
|
u8 sbyt = snd_mtpav_getreg(mcrd, SREG);
|
||||||
|
|
||||||
/* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */
|
|
||||||
|
|
||||||
if (!(sbyt & SIGS_BYTE))
|
if (!(sbyt & SIGS_BYTE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -569,13 +563,13 @@ static int snd_mtpav_get_ISA(struct mtpav *mcard)
|
|||||||
mcard->res_port = devm_request_region(mcard->card->dev, port, 3,
|
mcard->res_port = devm_request_region(mcard->card->dev, port, 3,
|
||||||
"MotuMTPAV MIDI");
|
"MotuMTPAV MIDI");
|
||||||
if (!mcard->res_port) {
|
if (!mcard->res_port) {
|
||||||
snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
|
dev_err(mcard->card->dev, "MTVAP port 0x%lx is busy\n", port);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
mcard->port = port;
|
mcard->port = port;
|
||||||
if (devm_request_irq(mcard->card->dev, irq, snd_mtpav_irqh, 0,
|
if (devm_request_irq(mcard->card->dev, irq, snd_mtpav_irqh, 0,
|
||||||
"MOTU MTPAV", mcard)) {
|
"MOTU MTPAV", mcard)) {
|
||||||
snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq);
|
dev_err(mcard->card->dev, "MTVAP IRQ %d busy\n", irq);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
mcard->irq = irq;
|
mcard->irq = irq;
|
||||||
@ -717,7 +711,9 @@ static int snd_mtpav_probe(struct platform_device *dev)
|
|||||||
card->private_free = snd_mtpav_free;
|
card->private_free = snd_mtpav_free;
|
||||||
|
|
||||||
platform_set_drvdata(dev, card);
|
platform_set_drvdata(dev, card);
|
||||||
printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
|
dev_info(card->dev,
|
||||||
|
"Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n",
|
||||||
|
irq, port);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -652,8 +652,8 @@ static int snd_mts64_ctl_create(struct snd_card *card,
|
|||||||
for (i = 0; control[i]; ++i) {
|
for (i = 0; control[i]; ++i) {
|
||||||
err = snd_ctl_add(card, snd_ctl_new1(control[i], mts));
|
err = snd_ctl_add(card, snd_ctl_new1(control[i], mts));
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
snd_printd("Cannot create control: %s\n",
|
dev_dbg(card->dev, "Cannot create control: %s\n",
|
||||||
control[i]->name);
|
control[i]->name);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -926,7 +926,7 @@ static int snd_mts64_probe(struct platform_device *pdev)
|
|||||||
err = snd_card_new(&pdev->dev, index[dev], id[dev], THIS_MODULE,
|
err = snd_card_new(&pdev->dev, index[dev], id[dev], THIS_MODULE,
|
||||||
0, &card);
|
0, &card);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
snd_printd("Cannot create card\n");
|
dev_dbg(&pdev->dev, "Cannot create card\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
strcpy(card->driver, DRIVER_NAME);
|
strcpy(card->driver, DRIVER_NAME);
|
||||||
@ -940,21 +940,21 @@ static int snd_mts64_probe(struct platform_device *pdev)
|
|||||||
&mts64_cb, /* callbacks */
|
&mts64_cb, /* callbacks */
|
||||||
pdev->id); /* device number */
|
pdev->id); /* device number */
|
||||||
if (!pardev) {
|
if (!pardev) {
|
||||||
snd_printd("Cannot register pardevice\n");
|
dev_dbg(card->dev, "Cannot register pardevice\n");
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
goto __err;
|
goto __err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* claim parport */
|
/* claim parport */
|
||||||
if (parport_claim(pardev)) {
|
if (parport_claim(pardev)) {
|
||||||
snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base);
|
dev_dbg(card->dev, "Cannot claim parport 0x%lx\n", pardev->port->base);
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
goto free_pardev;
|
goto free_pardev;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snd_mts64_create(card, pardev, &mts);
|
err = snd_mts64_create(card, pardev, &mts);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
snd_printd("Cannot create main component\n");
|
dev_dbg(card->dev, "Cannot create main component\n");
|
||||||
goto release_pardev;
|
goto release_pardev;
|
||||||
}
|
}
|
||||||
card->private_data = mts;
|
card->private_data = mts;
|
||||||
@ -968,7 +968,7 @@ static int snd_mts64_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
err = snd_mts64_rawmidi_create(card);
|
err = snd_mts64_rawmidi_create(card);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
snd_printd("Creating Rawmidi component failed\n");
|
dev_dbg(card->dev, "Creating Rawmidi component failed\n");
|
||||||
goto __err;
|
goto __err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -982,11 +982,11 @@ static int snd_mts64_probe(struct platform_device *pdev)
|
|||||||
/* At this point card will be usable */
|
/* At this point card will be usable */
|
||||||
err = snd_card_register(card);
|
err = snd_card_register(card);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
snd_printd("Cannot register card\n");
|
dev_dbg(card->dev, "Cannot register card\n");
|
||||||
goto __err;
|
goto __err;
|
||||||
}
|
}
|
||||||
|
|
||||||
snd_printk(KERN_INFO "ESI Miditerminal 4140 on 0x%lx\n", p->base);
|
dev_info(card->dev, "ESI Miditerminal 4140 on 0x%lx\n", p->base);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
release_pardev:
|
release_pardev:
|
||||||
|
@ -92,7 +92,7 @@ static int snd_opl3_detect(struct snd_opl3 * opl3)
|
|||||||
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
|
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
|
||||||
signature = stat1 = inb(opl3->l_port); /* Status register */
|
signature = stat1 = inb(opl3->l_port); /* Status register */
|
||||||
if ((stat1 & 0xe0) != 0x00) { /* Should be 0x00 */
|
if ((stat1 & 0xe0) != 0x00) { /* Should be 0x00 */
|
||||||
snd_printd("OPL3: stat1 = 0x%x\n", stat1);
|
dev_dbg(opl3->card->dev, "OPL3: stat1 = 0x%x\n", stat1);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
/* Set timer1 to 0xff */
|
/* Set timer1 to 0xff */
|
||||||
@ -108,7 +108,7 @@ static int snd_opl3_detect(struct snd_opl3 * opl3)
|
|||||||
/* Reset the IRQ of the FM chip */
|
/* Reset the IRQ of the FM chip */
|
||||||
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
|
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
|
||||||
if ((stat2 & 0xe0) != 0xc0) { /* There is no YM3812 */
|
if ((stat2 & 0xe0) != 0xc0) { /* There is no YM3812 */
|
||||||
snd_printd("OPL3: stat2 = 0x%x\n", stat2);
|
dev_dbg(opl3->card->dev, "OPL3: stat2 = 0x%x\n", stat2);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,9 +289,6 @@ void snd_opl3_interrupt(struct snd_hwdep * hw)
|
|||||||
|
|
||||||
opl3 = hw->private_data;
|
opl3 = hw->private_data;
|
||||||
status = inb(opl3->l_port);
|
status = inb(opl3->l_port);
|
||||||
#if 0
|
|
||||||
snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status);
|
|
||||||
#endif
|
|
||||||
if (!(status & 0x80))
|
if (!(status & 0x80))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -365,7 +362,8 @@ EXPORT_SYMBOL(snd_opl3_new);
|
|||||||
int snd_opl3_init(struct snd_opl3 *opl3)
|
int snd_opl3_init(struct snd_opl3 *opl3)
|
||||||
{
|
{
|
||||||
if (! opl3->command) {
|
if (! opl3->command) {
|
||||||
printk(KERN_ERR "snd_opl3_init: command not defined!\n");
|
dev_err(opl3->card->dev,
|
||||||
|
"snd_opl3_init: command not defined!\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,14 +403,14 @@ int snd_opl3_create(struct snd_card *card,
|
|||||||
if (! integrated) {
|
if (! integrated) {
|
||||||
opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)");
|
opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)");
|
||||||
if (!opl3->res_l_port) {
|
if (!opl3->res_l_port) {
|
||||||
snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port);
|
dev_err(card->dev, "opl3: can't grab left port 0x%lx\n", l_port);
|
||||||
snd_device_free(card, opl3);
|
snd_device_free(card, opl3);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
if (r_port != 0) {
|
if (r_port != 0) {
|
||||||
opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)");
|
opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)");
|
||||||
if (!opl3->res_r_port) {
|
if (!opl3->res_r_port) {
|
||||||
snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port);
|
dev_err(card->dev, "opl3: can't grab right port 0x%lx\n", r_port);
|
||||||
snd_device_free(card, opl3);
|
snd_device_free(card, opl3);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
@ -432,8 +430,8 @@ int snd_opl3_create(struct snd_card *card,
|
|||||||
opl3->command = &snd_opl2_command;
|
opl3->command = &snd_opl2_command;
|
||||||
err = snd_opl3_detect(opl3);
|
err = snd_opl3_detect(opl3);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n",
|
dev_dbg(card->dev, "OPL2/3 chip not detected at 0x%lx/0x%lx\n",
|
||||||
opl3->l_port, opl3->r_port);
|
opl3->l_port, opl3->r_port);
|
||||||
snd_device_free(card, opl3);
|
snd_device_free(card, opl3);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user