Merge 2f27fce671 ("Merge tag 'sound-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound") into android-mainline
Steps on the way to 6.12-rc1 Bug: 367265496 Change-Id: I787d27c45a1421a2153fbdb5d43acdf4d180b028 Signed-off-by: Matthias Maennich <maennich@google.com>
This commit is contained in:
@@ -37,6 +37,24 @@ properties:
|
||||
"#interrupt-cells":
|
||||
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:
|
||||
type: object
|
||||
$ref: /schemas/regulator/mediatek,mt6357-regulator.yaml
|
||||
@@ -83,6 +101,9 @@ examples:
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
mediatek,micbias0-microvolt = <1700000>;
|
||||
mediatek,micbias1-microvolt = <1700000>;
|
||||
|
||||
regulators {
|
||||
mt6357_vproc_reg: buck-vproc {
|
||||
regulator-name = "vproc";
|
||||
|
||||
@@ -26,6 +26,13 @@ properties:
|
||||
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
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
description:
|
||||
Base PLL clocks of audio susbsytem, used to configure base clock
|
||||
frequencies for different audio use-cases.
|
||||
|
||||
patternProperties:
|
||||
"^dai-link-[0-9]+$":
|
||||
type: object
|
||||
|
||||
@@ -27,6 +27,13 @@ properties:
|
||||
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
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
description:
|
||||
Base PLL clocks of audio susbsytem, used to configure base clock
|
||||
frequencies for different audio use-cases.
|
||||
|
||||
patternProperties:
|
||||
"^dai-link-[0-9]+$":
|
||||
type: object
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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
|
||||
compliant with the IEC-60958 standard.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
@@ -53,7 +56,7 @@ required:
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
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:
|
||||
enum:
|
||||
- qcom,sc7280-lpass-wsa-macro
|
||||
- qcom,sm8250-lpass-wsa-macro
|
||||
- qcom,sm8450-lpass-wsa-macro
|
||||
- qcom,sc8280xp-lpass-wsa-macro
|
||||
then:
|
||||
@@ -79,24 +80,6 @@ allOf:
|
||||
- const: dcodec
|
||||
- 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:
|
||||
properties:
|
||||
compatible:
|
||||
@@ -130,8 +113,7 @@ examples:
|
||||
<&audiocc 0>,
|
||||
<&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
||||
<&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
||||
<&aoncc LPASS_CDC_VA_MCLK>,
|
||||
<&vamacro>;
|
||||
clock-names = "mclk", "npl", "macro", "dcodec", "va", "fsgen";
|
||||
clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
|
||||
clock-output-names = "mclk";
|
||||
};
|
||||
|
||||
@@ -27,9 +27,7 @@ properties:
|
||||
- qcom,sm8650-sndcard
|
||||
- const: qcom,sm8450-sndcard
|
||||
- enum:
|
||||
- qcom,apq8016-sbc-sndcard
|
||||
- qcom,apq8096-sndcard
|
||||
- qcom,msm8916-qdsp6-sndcard
|
||||
- qcom,qcm6490-idp-sndcard
|
||||
- qcom,qcs6490-rb3gen2-sndcard
|
||||
- qcom,qrb5165-rb5-sndcard
|
||||
@@ -58,18 +56,6 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: User visible long sound card name
|
||||
|
||||
pin-switches:
|
||||
description: List of widget names for which pin switches should be created.
|
||||
$ref: /schemas/types.yaml#/definitions/string-array
|
||||
|
||||
widgets:
|
||||
description: User specified audio sound widgets.
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
|
||||
# Only valid for some compatibles (see allOf if below)
|
||||
reg: true
|
||||
reg-names: true
|
||||
|
||||
patternProperties:
|
||||
".*-dai-link$":
|
||||
description:
|
||||
@@ -122,34 +108,6 @@ required:
|
||||
- compatible
|
||||
- model
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,apq8016-sbc-sndcard
|
||||
- qcom,msm8916-qdsp6-sndcard
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: Microphone I/O mux register address
|
||||
- description: Speaker I/O mux register address
|
||||
reg-names:
|
||||
items:
|
||||
- const: mic-iomux
|
||||
- const: spkr-iomux
|
||||
required:
|
||||
- compatible
|
||||
- model
|
||||
- reg
|
||||
- reg-names
|
||||
else:
|
||||
properties:
|
||||
reg: false
|
||||
reg-names: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
@@ -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:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Master clock to the CODEC
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mclk
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -112,6 +112,12 @@ properties:
|
||||
description: List of necessary clock names.
|
||||
# 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
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#/definitions/port-base
|
||||
|
||||
@@ -87,6 +87,10 @@ properties:
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#/definitions/port-base
|
||||
description: Connection to controller providing I2S signals
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -27,11 +27,6 @@ properties:
|
||||
- const: samsung,odroid-xu4-audio
|
||||
deprecated: true
|
||||
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
assigned-clocks: true
|
||||
clocks: true
|
||||
|
||||
cpu:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
power_save_controller
|
||||
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
|
||||
Force rounding of buffer/period sizes to multiples of 128 bytes.
|
||||
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,
|
||||
``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_*``
|
||||
options. Note that each of them corresponds to the codec chip, not
|
||||
|
||||
@@ -13,6 +13,7 @@ Sound Subsystem Documentation
|
||||
alsa-configuration
|
||||
hd-audio/index
|
||||
cards/index
|
||||
utimers
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
|
||||
@@ -4030,31 +4030,6 @@ located in the new subdirectory, sound/pci/xyz.
|
||||
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()`
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -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.
|
||||
+2
-2
@@ -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,slg51000.yaml
|
||||
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/watchdog/dlg,da9062-watchdog.yaml
|
||||
F: Documentation/hwmon/da90??.rst
|
||||
@@ -22732,12 +22733,11 @@ F: Documentation/devicetree/bindings/sound/tas2552.txt
|
||||
F: Documentation/devicetree/bindings/sound/ti,tas2562.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,tas2770.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,pcm3168a.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,tlv320*.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/tlv320*.h
|
||||
F: include/sound/tpa6130a2-plat.h
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <drm/bridge/dw_hdmi.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)
|
||||
{
|
||||
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,
|
||||
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. */
|
||||
return snd_pcm_lib_alloc_vmalloc_buffer(substream,
|
||||
params_buffer_bytes(params));
|
||||
if (runtime->dma_area) {
|
||||
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)
|
||||
@@ -515,7 +537,7 @@ static const struct snd_pcm_ops snd_dw_hdmi_ops = {
|
||||
.prepare = dw_hdmi_prepare,
|
||||
.trigger = dw_hdmi_trigger,
|
||||
.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)
|
||||
|
||||
@@ -222,6 +222,13 @@ static inline bool sdw_intel_sync_check_cmdsync_unlocked(struct sdw_intel *sdw)
|
||||
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 */
|
||||
int intel_start_bus(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);
|
||||
}
|
||||
|
||||
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 = {
|
||||
.debugfs_init = intel_ace2x_debugfs_init,
|
||||
.debugfs_exit = intel_ace2x_debugfs_exit,
|
||||
|
||||
.get_link_count = intel_get_link_count,
|
||||
|
||||
.register_dai = intel_register_dai,
|
||||
|
||||
.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->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);
|
||||
|
||||
/* Set ops */
|
||||
|
||||
@@ -388,6 +388,7 @@ struct sdw_intel;
|
||||
/* struct intel_sdw_hw_ops - SoundWire ops for Intel platforms.
|
||||
* @debugfs_init: initialize all 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
|
||||
* @check_clock_stop: throw error message if clock is not stopped.
|
||||
* @start_bus: normal start
|
||||
@@ -412,6 +413,8 @@ struct sdw_intel_hw_ops {
|
||||
void (*debugfs_init)(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);
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Max number of links supported in hardware
|
||||
*/
|
||||
#define SDW_INTEL_MAX_LINKS 5
|
||||
|
||||
#endif
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
#define ACI_SET_EQ7 0x46 /* ... to Treble */
|
||||
|
||||
struct snd_miro_aci {
|
||||
struct snd_card *card;
|
||||
unsigned long aci_port;
|
||||
int aci_vendor;
|
||||
int aci_product;
|
||||
|
||||
@@ -110,18 +110,22 @@
|
||||
#define IEC958_AES2_CON_SOURCE_UNSPEC (0<<0) /* unspecified */
|
||||
#define IEC958_AES2_CON_CHANNEL (15<<4) /* mask - channel number */
|
||||
#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_NOTID (1<<0) /* non indicated */
|
||||
#define IEC958_AES3_CON_FS_48000 (2<<0) /* 48kHz */
|
||||
#define IEC958_AES3_CON_FS_32000 (3<<0) /* 32kHz */
|
||||
#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_88200 (8<<0) /* 88.2kHz */
|
||||
#define IEC958_AES3_CON_FS_768000 (9<<0) /* 768kHz */
|
||||
#define IEC958_AES3_CON_FS_96000 (10<<0) /* 96kHz */
|
||||
#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_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_1000PPM (0<<4) /* 1000 ppm */
|
||||
#define IEC958_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */
|
||||
|
||||
+1
-26
@@ -81,7 +81,7 @@ struct snd_kcontrol {
|
||||
unsigned long private_value;
|
||||
void *private_data;
|
||||
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)
|
||||
@@ -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);
|
||||
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);
|
||||
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_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);
|
||||
|
||||
/**
|
||||
@@ -167,29 +165,6 @@ snd_ctl_find_id_mixer(struct snd_card *card, const char *name)
|
||||
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_register_ioctl(snd_kctl_ioctl_func_t fcn);
|
||||
|
||||
+1
-68
@@ -99,7 +99,7 @@ struct snd_card {
|
||||
struct device *ctl_dev; /* control device */
|
||||
unsigned int last_numid; /* last used numeric ID */
|
||||
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 */
|
||||
size_t user_ctl_alloc_size; // current memory allocation by user controls.
|
||||
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
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@@ -392,12 +354,6 @@ void __snd_printk(unsigned int level, const char *file, int line,
|
||||
*/
|
||||
#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
|
||||
* @cond: condition to evaluate
|
||||
@@ -409,11 +365,6 @@ void __snd_printk(unsigned int level, const char *file, int line,
|
||||
|
||||
#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_ON(condition) ({ \
|
||||
@@ -421,26 +372,8 @@ static inline void _snd_printd(int level, const char *format, ...) {}
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
|
||||
static inline bool snd_printd_ratelimit(void) { return false; }
|
||||
|
||||
#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 */
|
||||
|
||||
/* for easier backward-porting */
|
||||
|
||||
@@ -282,9 +282,9 @@ static inline bool cs35l56_is_otp_register(unsigned int reg)
|
||||
return (reg >> 16) == 3;
|
||||
}
|
||||
|
||||
extern struct regmap_config cs35l56_regmap_i2c;
|
||||
extern struct regmap_config cs35l56_regmap_spi;
|
||||
extern struct regmap_config cs35l56_regmap_sdw;
|
||||
extern const struct regmap_config cs35l56_regmap_i2c;
|
||||
extern const struct regmap_config cs35l56_regmap_spi;
|
||||
extern const struct regmap_config cs35l56_regmap_sdw;
|
||||
|
||||
extern const struct cirrus_amp_cal_controls cs35l56_calibration_controls;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define ES1688_HW_UNDEF 0x0003
|
||||
|
||||
struct snd_es1688 {
|
||||
struct snd_card *card;
|
||||
unsigned long port; /* port of ESS chip */
|
||||
struct resource *res_port;
|
||||
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_NONCOHERENT 9 /* non-coherent buffer */
|
||||
#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 */
|
||||
#else
|
||||
#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
|
||||
#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
|
||||
|
||||
+7
-42
@@ -123,6 +123,10 @@ struct snd_pcm_ops {
|
||||
#define SNDRV_PCM_RATE_384000 (1U<<14) /* 384000Hz */
|
||||
#define SNDRV_PCM_RATE_705600 (1U<<15) /* 705600Hz */
|
||||
#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_KNOT (1U<<31) /* supports more non-continuous rates */
|
||||
@@ -498,6 +502,9 @@ struct snd_pcm_substream {
|
||||
/* misc flags */
|
||||
unsigned int hw_opened: 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)
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
/**
|
||||
|
||||
@@ -86,10 +86,6 @@ static inline size_t snd_seq_event_packet_size(struct snd_seq_event *ev)
|
||||
/* interface for OSS emulation */
|
||||
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 */
|
||||
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);
|
||||
|
||||
@@ -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_release (struct snd_hwdep *, struct file *);
|
||||
|
||||
/* prefix in all snd_printk() delivered messages */
|
||||
|
||||
#define LOGNAME "WaveFront: "
|
||||
|
||||
#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_lnl_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_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_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_ptl_sdw_machines[];
|
||||
|
||||
/*
|
||||
* 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
|
||||
* @codec_mask: used for HDAudio support
|
||||
* @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
|
||||
* @links: array of SoundWire link _ADR descriptors, null terminated
|
||||
* @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
|
||||
* @subsystem_vendor: optional PCI SSID vendor 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_vendor and subsystem_device.
|
||||
* @bt_link_mask: BT offload link enabled on the board
|
||||
*/
|
||||
struct snd_soc_acpi_mach_params {
|
||||
u32 acpi_ipc_irq_index;
|
||||
const char *platform;
|
||||
u32 codec_mask;
|
||||
u32 dmic_num;
|
||||
bool common_hdmi_codec_drv;
|
||||
u32 link_mask;
|
||||
const struct snd_soc_acpi_link_adr *links;
|
||||
u32 i2s_link_mask;
|
||||
@@ -86,7 +86,9 @@ struct snd_soc_acpi_mach_params {
|
||||
struct snd_soc_dai_driver *dai_drivers;
|
||||
unsigned short subsystem_vendor;
|
||||
unsigned short subsystem_device;
|
||||
unsigned short subsystem_rev;
|
||||
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,
|
||||
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,
|
||||
struct snd_soc_jack *jack);
|
||||
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 */
|
||||
struct snd_kcontrol *snd_soc_component_get_kcontrol(struct snd_soc_component *component,
|
||||
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,
|
||||
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,
|
||||
struct snd_soc_pcm_runtime *rtd, int num);
|
||||
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,
|
||||
int stream, int action);
|
||||
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_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
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,
|
||||
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,
|
||||
struct snd_soc_dai *);
|
||||
int (*bespoke_trigger)(struct snd_pcm_substream *, int,
|
||||
struct snd_soc_dai *);
|
||||
|
||||
/*
|
||||
* For hardware based FIFO caused delay reporting.
|
||||
* Optional.
|
||||
|
||||
@@ -58,7 +58,6 @@ enum snd_soc_dpcm_state {
|
||||
enum snd_soc_dpcm_trigger {
|
||||
SND_SOC_DPCM_TRIGGER_PRE = 0,
|
||||
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) \
|
||||
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 */
|
||||
struct snd_pcm_substream *
|
||||
|
||||
+4
-3
@@ -815,6 +815,7 @@ struct snd_soc_dai_link {
|
||||
/* This DAI link can route to other DAI links at runtime (Frontend)*/
|
||||
unsigned int dynamic:1;
|
||||
|
||||
/* REMOVE ME */
|
||||
/* DPCM capture and Playback support */
|
||||
unsigned int dpcm_capture:1;
|
||||
unsigned int dpcm_playback:1;
|
||||
@@ -1206,11 +1207,11 @@ struct snd_soc_pcm_runtime {
|
||||
/* bit field */
|
||||
unsigned int pop_wait:1;
|
||||
unsigned int fe_compr:1; /* for Dynamic PCM */
|
||||
unsigned int initialized:1;
|
||||
|
||||
bool initialized;
|
||||
|
||||
/* CPU/Codec/Platform */
|
||||
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() */
|
||||
|
||||
@@ -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 */
|
||||
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);
|
||||
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);
|
||||
int snd_soundfont_close_check(struct snd_sf_list *sflist, int client);
|
||||
|
||||
|
||||
@@ -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(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
|
||||
|
||||
+67
-4
@@ -49,12 +49,59 @@
|
||||
/*I2C Checksum */
|
||||
#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 */
|
||||
#define TAS2563_DVC_LVL TASDEVICE_REG(0x00, 0x02, 0x0C)
|
||||
#define TAS2781_DVC_LVL TASDEVICE_REG(0x0, 0x0, 0x1A)
|
||||
#define TAS2781_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x03)
|
||||
#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_BURST 0x2
|
||||
#define TASDEVICE_CMD_DELAY 0x3
|
||||
@@ -70,7 +117,15 @@ enum device_catlog_id {
|
||||
OTHERS
|
||||
};
|
||||
|
||||
struct bulk_reg_val {
|
||||
int reg;
|
||||
unsigned char val[4];
|
||||
unsigned char val_len;
|
||||
bool is_locked;
|
||||
};
|
||||
|
||||
struct tasdevice {
|
||||
struct bulk_reg_val *cali_data_backup;
|
||||
struct tasdevice_fw *cali_data_fmw;
|
||||
unsigned int dev_addr;
|
||||
unsigned int err_code;
|
||||
@@ -81,19 +136,23 @@ struct tasdevice {
|
||||
bool is_loaderr;
|
||||
};
|
||||
|
||||
struct tasdevice_irqinfo {
|
||||
int irq_gpio;
|
||||
int irq;
|
||||
struct cali_reg {
|
||||
unsigned int r0_reg;
|
||||
unsigned int r0_low_reg;
|
||||
unsigned int invr0_reg;
|
||||
unsigned int pow_reg;
|
||||
unsigned int tlimit_reg;
|
||||
};
|
||||
|
||||
struct calidata {
|
||||
unsigned char *data;
|
||||
unsigned long total_sz;
|
||||
struct cali_reg cali_reg_array;
|
||||
unsigned int cali_dat_sz_per_dev;
|
||||
};
|
||||
|
||||
struct tasdevice_priv {
|
||||
struct tasdevice tasdevice[TASDEVICE_MAX_CHANNELS];
|
||||
struct tasdevice_irqinfo irq_info;
|
||||
struct tasdevice_rca rcabin;
|
||||
struct calidata cali_data;
|
||||
struct tasdevice_fw *fmw;
|
||||
@@ -115,6 +174,7 @@ struct tasdevice_priv {
|
||||
unsigned int chip_id;
|
||||
unsigned int sysclk;
|
||||
|
||||
int irq;
|
||||
int cur_prog;
|
||||
int cur_conf;
|
||||
int fw_state;
|
||||
@@ -124,6 +184,7 @@ struct tasdevice_priv {
|
||||
bool force_fwload_status;
|
||||
bool playback_started;
|
||||
bool isacpi;
|
||||
bool is_user_space_calidata;
|
||||
unsigned int global_addr;
|
||||
|
||||
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);
|
||||
int tasdevice_save_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,
|
||||
unsigned short chn, unsigned int reg, unsigned int *value);
|
||||
int tasdevice_dev_write(struct tasdevice_priv *tas_priv,
|
||||
|
||||
@@ -13,6 +13,15 @@ struct snd_ump_ops;
|
||||
struct ump_cvt_to_ump;
|
||||
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_rawmidi core; /* raw UMP access */
|
||||
|
||||
@@ -41,6 +50,8 @@ struct snd_ump_endpoint {
|
||||
|
||||
struct mutex open_mutex;
|
||||
|
||||
struct snd_ump_group groups[SNDRV_UMP_MAX_GROUPS]; /* table of groups */
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
|
||||
spinlock_t legacy_locks[2];
|
||||
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_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
|
||||
|
||||
@@ -155,7 +155,6 @@ struct vx_core {
|
||||
unsigned int chip_status;
|
||||
unsigned int pcm_running;
|
||||
|
||||
struct device *dev;
|
||||
struct snd_hwdep *hwdep;
|
||||
|
||||
struct vx_rmh irq_rmh; /* RMH used in interrupts */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/tracepoint.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/pcm.h>
|
||||
|
||||
#define DAPM_DIRECT "(direct)"
|
||||
#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",
|
||||
__entry->stream ? "capture" : "playback", __entry->paths)
|
||||
snd_pcm_direction_name(__entry->stream), __entry->paths)
|
||||
);
|
||||
|
||||
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_TIME_REAL (1<<2)
|
||||
|
||||
#define SNDRV_SEQ_PORT_FLG_IS_MIDI1 (1<<3) /* Keep MIDI 1.0 protocol */
|
||||
|
||||
/* port direction */
|
||||
#define SNDRV_SEQ_PORT_DIR_UNKNOWN 0
|
||||
#define SNDRV_SEQ_PORT_DIR_INPUT 1
|
||||
|
||||
@@ -869,7 +869,7 @@ struct snd_ump_block_info {
|
||||
* 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 {
|
||||
SNDRV_TIMER_CLASS_NONE = -1,
|
||||
@@ -894,6 +894,7 @@ enum {
|
||||
#define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */
|
||||
#define SNDRV_TIMER_GLOBAL_HPET 2
|
||||
#define SNDRV_TIMER_GLOBAL_HRTIMER 3
|
||||
#define SNDRV_TIMER_GLOBAL_UDRIVEN 4
|
||||
|
||||
/* info flags */
|
||||
#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
|
||||
@@ -974,6 +975,18 @@ struct snd_timer_status {
|
||||
};
|
||||
#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_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
|
||||
#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_PAUSE _IO('T', 0xa3)
|
||||
#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
|
||||
#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)
|
||||
{
|
||||
struct device_node *np = NULL;
|
||||
struct device_node *np;
|
||||
int got = 0, err;
|
||||
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;
|
||||
}
|
||||
|
||||
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") ||
|
||||
of_device_is_compatible(np, "i2s-modem")) {
|
||||
got += i2sbus_add_dev(dev, control, np);
|
||||
|
||||
+10
-9
@@ -175,15 +175,6 @@ config SND_VERBOSE_PROCFS
|
||||
useful information to developers when a problem occurs). On the
|
||||
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
|
||||
bool "Fast lookup of control elements" if EXPERT
|
||||
default y
|
||||
@@ -251,6 +242,16 @@ config SND_JACK_INJECTION_DEBUG
|
||||
Say Y if you are debugging via jack injection interface.
|
||||
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
|
||||
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));
|
||||
if (IS_ERR(params))
|
||||
return PTR_ERR(no_free_ptr(params));
|
||||
return PTR_ERR(params);
|
||||
|
||||
retval = snd_compress_check_input(params);
|
||||
if (retval)
|
||||
|
||||
+96
-116
@@ -79,7 +79,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
|
||||
ctl->preferred_subdevice[i] = -1;
|
||||
ctl->pid = get_pid(task_pid(current));
|
||||
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);
|
||||
snd_card_unref(card);
|
||||
return 0;
|
||||
@@ -117,7 +117,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
|
||||
file->private_data = NULL;
|
||||
card = ctl->card;
|
||||
|
||||
scoped_guard(write_lock_irqsave, &card->ctl_files_rwlock)
|
||||
scoped_guard(write_lock_irqsave, &card->controls_rwlock)
|
||||
list_del(&ctl->list);
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
guard(read_lock_irqsave)(&card->ctl_files_rwlock);
|
||||
guard(read_lock_irqsave)(&card->controls_rwlock);
|
||||
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
|
||||
card->mixer_oss_change_count++;
|
||||
#endif
|
||||
@@ -237,11 +237,11 @@ static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count,
|
||||
if (!*kctl)
|
||||
return -ENOMEM;
|
||||
|
||||
(*kctl)->count = count;
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
(*kctl)->vd[idx].access = access;
|
||||
(*kctl)->vd[idx].owner = file;
|
||||
}
|
||||
(*kctl)->count = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -470,7 +470,7 @@ static int __snd_ctl_add_replace(struct snd_card *card,
|
||||
if (id.index > UINT_MAX - kcontrol->count)
|
||||
return -EINVAL;
|
||||
|
||||
old = snd_ctl_find_id_locked(card, &id);
|
||||
old = snd_ctl_find_id(card, &id);
|
||||
if (!old) {
|
||||
if (mode == CTL_REPLACE)
|
||||
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)
|
||||
return -ENOMEM;
|
||||
|
||||
list_add_tail(&kcontrol->list, &card->controls);
|
||||
card->controls_count += kcontrol->count;
|
||||
kcontrol->id.numid = card->last_numid + 1;
|
||||
card->last_numid += kcontrol->count;
|
||||
scoped_guard(write_lock_irq, &card->controls_rwlock) {
|
||||
list_add_tail(&kcontrol->list, &card->controls);
|
||||
card->controls_count += kcontrol->count;
|
||||
kcontrol->id.numid = card->last_numid + 1;
|
||||
card->last_numid += kcontrol->count;
|
||||
}
|
||||
|
||||
add_hash_entries(card, kcontrol);
|
||||
|
||||
@@ -579,12 +581,15 @@ static int __snd_ctl_remove(struct snd_card *card,
|
||||
|
||||
if (snd_BUG_ON(!card || !kcontrol))
|
||||
return -EINVAL;
|
||||
list_del(&kcontrol->list);
|
||||
|
||||
if (remove_hash)
|
||||
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++)
|
||||
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_REMOVE, kcontrol, idx);
|
||||
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;
|
||||
|
||||
guard(rwsem_write)(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
if (kctl == NULL)
|
||||
return -ENOENT;
|
||||
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;
|
||||
|
||||
guard(rwsem_write)(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
if (kctl == NULL)
|
||||
return -ENOENT;
|
||||
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;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
if (kctl == NULL) {
|
||||
ret = -ENOENT;
|
||||
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;
|
||||
|
||||
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)
|
||||
return -ENOENT;
|
||||
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;
|
||||
|
||||
guard(read_lock_irqsave)(&card->controls_rwlock);
|
||||
list_for_each_entry(kctl, &card->controls, list) {
|
||||
if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid)
|
||||
return kctl;
|
||||
@@ -795,32 +801,6 @@ snd_ctl_find_numid_slow(struct snd_card *card, unsigned int numid)
|
||||
}
|
||||
#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
|
||||
* @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.
|
||||
*
|
||||
* 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,
|
||||
unsigned int numid)
|
||||
{
|
||||
guard(rwsem_read)(&card->controls_rwsem);
|
||||
return snd_ctl_find_numid_locked(card, numid);
|
||||
if (snd_BUG_ON(!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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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.
|
||||
*
|
||||
* 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,
|
||||
const struct snd_ctl_elem_id *id)
|
||||
{
|
||||
guard(rwsem_read)(&card->controls_rwsem);
|
||||
return snd_ctl_find_id_locked(card, id);
|
||||
struct snd_kcontrol *kctl;
|
||||
|
||||
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);
|
||||
|
||||
@@ -1167,10 +1134,7 @@ static int __snd_ctl_elem_info(struct snd_card *card,
|
||||
#ifdef CONFIG_SND_DEBUG
|
||||
info->access = 0;
|
||||
#endif
|
||||
result = snd_power_ref_and_wait(card);
|
||||
if (!result)
|
||||
result = kctl->info(kctl, info);
|
||||
snd_power_unref(card);
|
||||
result = kctl->info(kctl, info);
|
||||
if (result >= 0) {
|
||||
snd_BUG_ON(info->access);
|
||||
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;
|
||||
|
||||
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)
|
||||
return -ENOENT;
|
||||
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,
|
||||
struct snd_ctl_elem_info __user *_info)
|
||||
{
|
||||
struct snd_card *card = ctl->card;
|
||||
struct snd_ctl_elem_info info;
|
||||
int result;
|
||||
|
||||
if (copy_from_user(&info, _info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
result = snd_power_ref_and_wait(card);
|
||||
if (result)
|
||||
return result;
|
||||
result = snd_ctl_elem_info(ctl, &info);
|
||||
snd_power_unref(card);
|
||||
if (result < 0)
|
||||
return result;
|
||||
/* drop internal access flags */
|
||||
@@ -1235,7 +1204,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
||||
int ret;
|
||||
|
||||
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)
|
||||
return -ENOENT;
|
||||
|
||||
@@ -1257,10 +1226,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
||||
|
||||
if (!snd_ctl_skip_validation(&info))
|
||||
fill_remaining_elem_value(control, &info, pattern);
|
||||
ret = snd_power_ref_and_wait(card);
|
||||
if (!ret)
|
||||
ret = kctl->get(kctl, control);
|
||||
snd_power_unref(card);
|
||||
ret = kctl->get(kctl, control);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
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));
|
||||
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);
|
||||
snd_power_unref(card);
|
||||
if (result < 0)
|
||||
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_volatile *vd;
|
||||
unsigned int index_offset;
|
||||
int result;
|
||||
int result = 0;
|
||||
|
||||
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) {
|
||||
up_write(&card->controls_rwsem);
|
||||
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);
|
||||
result = snd_power_ref_and_wait(card);
|
||||
/* 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;
|
||||
|
||||
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)
|
||||
result = kctl->put(kctl, control);
|
||||
snd_power_unref(card);
|
||||
if (result < 0) {
|
||||
up_write(&card->controls_rwsem);
|
||||
return result;
|
||||
@@ -1358,10 +1326,14 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
|
||||
|
||||
control = memdup_user(_control, sizeof(*control));
|
||||
if (IS_ERR(control))
|
||||
return PTR_ERR(no_free_ptr(control));
|
||||
return PTR_ERR(control);
|
||||
|
||||
card = file->card;
|
||||
result = snd_power_ref_and_wait(card);
|
||||
if (result < 0)
|
||||
return result;
|
||||
result = snd_ctl_elem_write(card, file, control);
|
||||
snd_power_unref(card);
|
||||
if (result < 0)
|
||||
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)))
|
||||
return -EFAULT;
|
||||
guard(rwsem_write)(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id_locked(card, &id);
|
||||
kctl = snd_ctl_find_id(card, &id);
|
||||
if (!kctl)
|
||||
return -ENOENT;
|
||||
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)))
|
||||
return -EFAULT;
|
||||
guard(rwsem_write)(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id_locked(card, &id);
|
||||
kctl = snd_ctl_find_id(card, &id);
|
||||
if (!kctl)
|
||||
return -ENOENT;
|
||||
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},
|
||||
};
|
||||
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. */
|
||||
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)
|
||||
return -EPERM;
|
||||
|
||||
ret = snd_power_ref_and_wait(file->card);
|
||||
if (!ret)
|
||||
ret = kctl->tlv.c(kctl, op_flag, size, buf);
|
||||
snd_power_unref(file->card);
|
||||
return ret;
|
||||
return kctl->tlv.c(kctl, op_flag, size, buf);
|
||||
}
|
||||
|
||||
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 = buf->tlv;
|
||||
|
||||
kctl = snd_ctl_find_numid_locked(file->card, header.numid);
|
||||
kctl = snd_ctl_find_numid(file->card, header.numid);
|
||||
if (kctl == NULL)
|
||||
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:
|
||||
return snd_ctl_subscribe_events(ctl, ip);
|
||||
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);
|
||||
snd_power_unref(card);
|
||||
return err;
|
||||
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);
|
||||
snd_power_unref(card);
|
||||
return err;
|
||||
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);
|
||||
snd_power_unref(card);
|
||||
return err;
|
||||
case SNDRV_CTL_IOCTL_POWER:
|
||||
return -ENOPROTOOPT;
|
||||
@@ -2178,7 +2158,7 @@ int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
|
||||
struct snd_ctl_file *kctl;
|
||||
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) {
|
||||
if (kctl->pid == task_pid(current)) {
|
||||
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_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) {
|
||||
wake_up(&ctl->change_sleep);
|
||||
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,
|
||||
struct snd_ctl_elem_info32 __user *data32)
|
||||
{
|
||||
struct snd_card *card = ctl->card;
|
||||
struct snd_ctl_elem_info *data __free(kfree) = NULL;
|
||||
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))
|
||||
return -EFAULT;
|
||||
|
||||
err = snd_power_ref_and_wait(card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = snd_ctl_elem_info(ctl, data);
|
||||
snd_power_unref(card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* 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;
|
||||
|
||||
guard(rwsem_read)(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
if (!kctl)
|
||||
return -ENOENT;
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (info == NULL)
|
||||
return -ENOMEM;
|
||||
info->id = *id;
|
||||
err = snd_power_ref_and_wait(card);
|
||||
if (!err)
|
||||
err = kctl->info(kctl, info);
|
||||
snd_power_unref(card);
|
||||
err = kctl->info(kctl, info);
|
||||
if (err >= 0) {
|
||||
err = info->type;
|
||||
*countp = info->count;
|
||||
@@ -275,8 +277,8 @@ static int copy_ctl_value_to_user(void __user *userdata,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctl_elem_read_user(struct snd_card *card,
|
||||
void __user *userdata, void __user *valuep)
|
||||
static int __ctl_elem_read_user(struct snd_card *card,
|
||||
void __user *userdata, void __user *valuep)
|
||||
{
|
||||
struct snd_ctl_elem_value *data __free(kfree) = NULL;
|
||||
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);
|
||||
}
|
||||
|
||||
static int ctl_elem_write_user(struct snd_ctl_file *file,
|
||||
void __user *userdata, void __user *valuep)
|
||||
static int ctl_elem_read_user(struct snd_card *card,
|
||||
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_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);
|
||||
}
|
||||
|
||||
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,
|
||||
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)
|
||||
return -ENXIO;
|
||||
guard(rwsem_write)(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
if (!kctl)
|
||||
return -ENOENT;
|
||||
ioff = snd_ctl_get_ioff(kctl, id);
|
||||
@@ -677,7 +677,7 @@ static void snd_ctl_led_sysfs_add(struct snd_card *card)
|
||||
cerr:
|
||||
put_device(&led_card->dev);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -315,7 +315,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
|
||||
card->module = module;
|
||||
INIT_LIST_HEAD(&card->devices);
|
||||
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->ctl_files);
|
||||
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
|
||||
|
||||
+88
-126
@@ -17,7 +17,17 @@
|
||||
#include <asm/set_memory.h>
|
||||
#endif
|
||||
#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 \
|
||||
(GFP_KERNEL | \
|
||||
@@ -26,10 +36,6 @@
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
*/
|
||||
/* x86-specific allocations */
|
||||
#ifdef CONFIG_SND_DMA_SGBUF
|
||||
/* x86-specific allocations */
|
||||
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)
|
||||
{
|
||||
dma_unmap_single(dmab->dev.dev, dmab->addr, dmab->bytes,
|
||||
DMA_BIDIRECTIONAL);
|
||||
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)
|
||||
{
|
||||
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
|
||||
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,
|
||||
dmab->area, dmab->addr, dmab->bytes);
|
||||
}
|
||||
#endif /* CONFIG_SND_DMA_SGBUF */
|
||||
#endif
|
||||
|
||||
static const struct snd_malloc_ops snd_dma_wc_ops = {
|
||||
.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;
|
||||
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,
|
||||
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)
|
||||
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,
|
||||
};
|
||||
|
||||
/* x86-specific SG-buffer with WC pages */
|
||||
#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 */
|
||||
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;
|
||||
struct page **pages;
|
||||
/* DMA address array; the first page contains #pages in ~PAGE_MASK */
|
||||
dma_addr_t *addrs;
|
||||
unsigned int *npages;
|
||||
};
|
||||
|
||||
static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
|
||||
struct snd_dma_sg_fallback *sgbuf)
|
||||
{
|
||||
bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG;
|
||||
size_t i, size;
|
||||
|
||||
if (sgbuf->pages && sgbuf->addrs) {
|
||||
if (sgbuf->pages && sgbuf->npages) {
|
||||
i = 0;
|
||||
while (i < sgbuf->count) {
|
||||
if (!sgbuf->pages[i] || !sgbuf->addrs[i])
|
||||
size = sgbuf->npages[i];
|
||||
if (!size)
|
||||
break;
|
||||
size = sgbuf->addrs[i] & ~PAGE_MASK;
|
||||
if (WARN_ON(!size))
|
||||
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);
|
||||
do_free_pages(page_address(sgbuf->pages[i]),
|
||||
size << PAGE_SHIFT, wc);
|
||||
i += size;
|
||||
}
|
||||
}
|
||||
kvfree(sgbuf->pages);
|
||||
kvfree(sgbuf->addrs);
|
||||
kvfree(sgbuf->npages);
|
||||
kfree(sgbuf);
|
||||
}
|
||||
|
||||
/* fallback manual S/G buffer allocations */
|
||||
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 page **pagep, *curp;
|
||||
size_t chunk, npages;
|
||||
dma_addr_t *addrp;
|
||||
size_t chunk;
|
||||
dma_addr_t addr;
|
||||
unsigned int idx, npages;
|
||||
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);
|
||||
if (!sgbuf)
|
||||
return NULL;
|
||||
sgbuf->use_dma_alloc_coherent = cpu_feature_enabled(X86_FEATURE_XENPV);
|
||||
size = PAGE_ALIGN(size);
|
||||
sgbuf->count = size >> PAGE_SHIFT;
|
||||
sgbuf->pages = kvcalloc(sgbuf->count, sizeof(*sgbuf->pages), GFP_KERNEL);
|
||||
sgbuf->addrs = kvcalloc(sgbuf->count, sizeof(*sgbuf->addrs), GFP_KERNEL);
|
||||
if (!sgbuf->pages || !sgbuf->addrs)
|
||||
sgbuf->npages = kvcalloc(sgbuf->count, sizeof(*sgbuf->npages), GFP_KERNEL);
|
||||
if (!sgbuf->pages || !sgbuf->npages)
|
||||
goto error;
|
||||
|
||||
pagep = sgbuf->pages;
|
||||
addrp = sgbuf->addrs;
|
||||
chunk = (PAGE_SIZE - 1) << PAGE_SHIFT; /* to fit in low bits in addrs */
|
||||
chunk = size;
|
||||
idx = 0;
|
||||
while (size > 0) {
|
||||
chunk = min(size, chunk);
|
||||
if (sgbuf->use_dma_alloc_coherent)
|
||||
p = dma_alloc_coherent(dmab->dev.dev, chunk, &addr, DEFAULT_GFP);
|
||||
else
|
||||
p = do_alloc_pages(dmab->dev.dev, chunk, &addr, false);
|
||||
p = do_alloc_pages(dmab->dev.dev, chunk, &addr, wc);
|
||||
if (!p) {
|
||||
if (chunk <= PAGE_SIZE)
|
||||
goto error;
|
||||
@@ -797,27 +746,33 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||
size -= chunk;
|
||||
/* fill pages */
|
||||
npages = chunk >> PAGE_SHIFT;
|
||||
*addrp = npages; /* store in lower bits */
|
||||
sgbuf->npages[idx] = npages;
|
||||
idx += npages;
|
||||
curp = virt_to_page(p);
|
||||
while (npages--) {
|
||||
while (npages--)
|
||||
*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);
|
||||
if (!p)
|
||||
goto error;
|
||||
|
||||
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
|
||||
set_pages_array_wc(sgbuf->pages, sgbuf->count);
|
||||
goto error_vmap;
|
||||
|
||||
dmab->private_data = sgbuf;
|
||||
/* store the first page address for convenience */
|
||||
dmab->addr = sgbuf->addrs[0] & PAGE_MASK;
|
||||
dmab->addr = snd_sgbuf_get_addr(dmab, 0);
|
||||
return p;
|
||||
|
||||
error_vmap:
|
||||
dma_unmap_sgtable(dmab->dev.dev, &sgbuf->sgt, DMA_BIDIRECTIONAL, 0);
|
||||
error_dma_map:
|
||||
sg_free_table(&sgbuf->sgt);
|
||||
error:
|
||||
__snd_dma_sg_fallback_free(dmab, sgbuf);
|
||||
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;
|
||||
|
||||
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
|
||||
set_pages_array_wb(sgbuf->pages, sgbuf->count);
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
struct vm_area_struct *area)
|
||||
{
|
||||
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);
|
||||
return vm_map_pages(area, sgbuf->pages, sgbuf->count);
|
||||
}
|
||||
|
||||
static const struct snd_malloc_ops snd_dma_sg_fallback_ops = {
|
||||
.alloc = snd_dma_sg_fallback_alloc,
|
||||
static void *snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||
{
|
||||
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,
|
||||
.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 */
|
||||
.get_page = snd_dma_vmalloc_get_page,
|
||||
.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_NONCOHERENT] = &snd_dma_noncoherent_ops,
|
||||
#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
|
||||
#ifdef CONFIG_GENERIC_ALLOCATOR
|
||||
[SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops,
|
||||
#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 */
|
||||
};
|
||||
|
||||
|
||||
@@ -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 <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)
|
||||
{
|
||||
if (res) {
|
||||
@@ -36,63 +22,6 @@ void release_and_free_resource(struct resource *res)
|
||||
}
|
||||
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
|
||||
#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;
|
||||
strscpy(id.name, name, sizeof(id.name));
|
||||
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,
|
||||
@@ -526,7 +526,7 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
||||
if (numid == ID_UNKNOWN)
|
||||
return;
|
||||
guard(rwsem_read)(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
||||
kctl = snd_ctl_find_numid(card, numid);
|
||||
if (!kctl)
|
||||
return;
|
||||
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)
|
||||
return;
|
||||
guard(rwsem_read)(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
||||
kctl = snd_ctl_find_numid(card, numid);
|
||||
if (!kctl)
|
||||
return;
|
||||
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)
|
||||
return;
|
||||
guard(rwsem_read)(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
||||
kctl = snd_ctl_find_numid(card, numid);
|
||||
if (!kctl)
|
||||
return;
|
||||
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)
|
||||
return;
|
||||
guard(rwsem_read)(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
||||
kctl = snd_ctl_find_numid(card, numid);
|
||||
if (!kctl)
|
||||
return;
|
||||
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
||||
|
||||
@@ -74,7 +74,6 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *handle,
|
||||
size_t extra,
|
||||
struct snd_pcm_plugin **ret);
|
||||
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);
|
||||
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);
|
||||
@@ -139,8 +138,6 @@ int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel,
|
||||
size_t dst_offset,
|
||||
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
|
||||
|
||||
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);
|
||||
|
||||
#ifdef PLUGIN_DEBUG
|
||||
#define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args)
|
||||
#define pdprintf(fmt, args...) pr_debug("plugin: " fmt, ##args)
|
||||
#else
|
||||
#define pdprintf(fmt, args...)
|
||||
#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, "hw_ptr : %ld\n", runtime->status->hw_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
|
||||
@@ -970,6 +973,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
|
||||
substream->pid = get_pid(task_pid(current));
|
||||
pstr->substream_opened++;
|
||||
*rsubstream = substream;
|
||||
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
||||
substream->xrun_counter = 0;
|
||||
#endif /* CONFIG_SND_PCM_XRUN_DEBUG */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -184,6 +184,9 @@ void __snd_pcm_xrun(struct snd_pcm_substream *substream)
|
||||
pcm_warn(substream->pcm, "XRUN: %s\n", name);
|
||||
dump_stack_on_xrun(substream);
|
||||
}
|
||||
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
||||
substream->xrun_counter++;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
|
||||
|
||||
+6
-62
@@ -9,7 +9,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/export.h>
|
||||
#include <sound/core.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_card *card = substream->pcm->card;
|
||||
char line[64], str[64];
|
||||
size_t size;
|
||||
unsigned long size;
|
||||
struct snd_dma_buffer new_dmab;
|
||||
|
||||
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))) {
|
||||
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) {
|
||||
buffer->error = -EINVAL;
|
||||
return;
|
||||
@@ -210,7 +212,7 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
|
||||
substream->stream,
|
||||
size, &new_dmab) < 0) {
|
||||
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->stream ? 'c' : 'p', substream->number,
|
||||
substream->pcm->name, size);
|
||||
@@ -497,61 +499,3 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
|
||||
+10
-8
@@ -494,18 +494,20 @@ EXPORT_SYMBOL(snd_pcm_format_set_silence);
|
||||
int snd_pcm_hw_limit_rates(struct snd_pcm_hardware *hw)
|
||||
{
|
||||
int i;
|
||||
unsigned int rmin, rmax;
|
||||
|
||||
rmin = UINT_MAX;
|
||||
rmax = 0;
|
||||
for (i = 0; i < (int)snd_pcm_known_rates.count; i++) {
|
||||
if (hw->rates & (1 << i)) {
|
||||
hw->rate_min = snd_pcm_known_rates.list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
rmin = min(rmin, snd_pcm_known_rates.list[i]);
|
||||
rmax = max(rmax, snd_pcm_known_rates.list[i]);
|
||||
}
|
||||
}
|
||||
if (rmin > rmax)
|
||||
return -EINVAL;
|
||||
hw->rate_min = rmin;
|
||||
hw->rate_max = rmax;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_pcm_hw_limit_rates);
|
||||
|
||||
+11
-7
@@ -582,7 +582,7 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
|
||||
|
||||
params = memdup_user(_params, sizeof(*params));
|
||||
if (IS_ERR(params))
|
||||
return PTR_ERR(no_free_ptr(params));
|
||||
return PTR_ERR(params);
|
||||
|
||||
err = snd_pcm_hw_refine(substream, params);
|
||||
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));
|
||||
if (IS_ERR(params))
|
||||
return PTR_ERR(no_free_ptr(params));
|
||||
return PTR_ERR(params);
|
||||
|
||||
err = snd_pcm_hw_params(substream, params);
|
||||
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);
|
||||
}
|
||||
|
||||
#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"
|
||||
#endif
|
||||
|
||||
/* NOTE: the list is unsorted! */
|
||||
static const unsigned int rates[] = {
|
||||
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 = {
|
||||
@@ -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);
|
||||
if (IS_ERR(bufs))
|
||||
return PTR_ERR(no_free_ptr(bufs));
|
||||
return PTR_ERR(bufs);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
|
||||
else
|
||||
@@ -4032,7 +4036,7 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
|
||||
|
||||
oparams = memdup_user(_oparams, sizeof(*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);
|
||||
err = snd_pcm_hw_refine(substream, params);
|
||||
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));
|
||||
if (IS_ERR(oparams))
|
||||
return PTR_ERR(no_free_ptr(oparams));
|
||||
return PTR_ERR(oparams);
|
||||
|
||||
snd_pcm_hw_convert_from_old_params(params, oparams);
|
||||
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)
|
||||
return;
|
||||
sprintf(timer->name, "PCM %s %i-%i-%i",
|
||||
substream->stream == SNDRV_PCM_STREAM_CAPTURE ?
|
||||
"capture" : "playback",
|
||||
snd_pcm_direction_name(substream->stream),
|
||||
tid.card, tid.device, tid.subdevice);
|
||||
timer->hw = snd_pcm_timer;
|
||||
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_process_queue(struct seq_oss_devinfo *dp, abstime_t time);
|
||||
|
||||
|
||||
/* proc interface */
|
||||
void snd_seq_oss_system_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);
|
||||
static int snd_seq_deliver_single_event(struct snd_seq_client *client,
|
||||
struct snd_seq_event *event,
|
||||
int filter, int atomic, int hop);
|
||||
int atomic, int hop);
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
|
||||
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
|
||||
* if filter is non-zero, client filter bitmap is tested.
|
||||
*/
|
||||
static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event,
|
||||
int filter)
|
||||
static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event)
|
||||
{
|
||||
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) &&
|
||||
! test_bit(event->type, dest->event_filter))
|
||||
goto __not_avail;
|
||||
if (filter && !(dest->filter & filter))
|
||||
goto __not_avail;
|
||||
|
||||
return dest; /* ok - accessible */
|
||||
__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.event = event;
|
||||
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) {
|
||||
client->event_lost++;
|
||||
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,
|
||||
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_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);
|
||||
|
||||
dest = get_event_dest_client(event, filter);
|
||||
dest = get_event_dest_client(event);
|
||||
if (dest == NULL)
|
||||
goto __skip;
|
||||
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 */
|
||||
update_timestamp_of_queue(event, subs->info.queue,
|
||||
subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL);
|
||||
err = snd_seq_deliver_single_event(client, event,
|
||||
0, atomic, hop);
|
||||
err = snd_seq_deliver_single_event(client, event, atomic, hop);
|
||||
if (err < 0) {
|
||||
/* save first error that occurs and continue */
|
||||
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)
|
||||
result = deliver_to_subscribers(client, event, atomic, hop);
|
||||
else
|
||||
result = snd_seq_deliver_single_event(client, event, 0, atomic, hop);
|
||||
result = snd_seq_deliver_single_event(client, event, atomic, hop);
|
||||
|
||||
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) {
|
||||
if (p->capability & SNDRV_SEQ_PORT_CAP_INACTIVE)
|
||||
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,
|
||||
FLAG_PERM_RD(p->capability),
|
||||
FLAG_PERM_WR(p->capability),
|
||||
FLAG_PERM_EX(p->capability),
|
||||
FLAG_PERM_DUPLEX(p->capability),
|
||||
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_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->is_midi1 = !!(info->flags & SNDRV_SEQ_PORT_FLG_IS_MIDI1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -399,6 +401,9 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port,
|
||||
info->time_queue = port->time_queue;
|
||||
}
|
||||
|
||||
if (port->is_midi1)
|
||||
info->flags |= SNDRV_SEQ_PORT_FLG_IS_MIDI1;
|
||||
|
||||
/* UMP direction and group */
|
||||
info->direction = port->direction;
|
||||
info->ump_group = port->ump_group;
|
||||
|
||||
@@ -77,6 +77,8 @@ struct snd_seq_client_port {
|
||||
unsigned char direction;
|
||||
unsigned char ump_group;
|
||||
|
||||
bool is_midi1; /* keep MIDI 1.0 protocol */
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
|
||||
struct ump_cvt_to_ump_bank midi2_bank[16]; /* per channel */
|
||||
#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_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_locked(int queueid, int client, int locked);
|
||||
int snd_seq_queue_timer_open(int queueid);
|
||||
int snd_seq_queue_timer_close(int queueid);
|
||||
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;
|
||||
int snd_seq_timer_open(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_reset(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
|
||||
};
|
||||
|
||||
/* 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 */
|
||||
struct seq_ump_input_buffer {
|
||||
unsigned char len; /* total length in words */
|
||||
@@ -48,7 +39,6 @@ struct seq_ump_client {
|
||||
int opened[2]; /* current opens for each direction */
|
||||
struct snd_rawmidi_file out_rfile; /* rawmidi for output */
|
||||
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 */
|
||||
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 */
|
||||
static void fill_port_info(struct snd_seq_port_info *port,
|
||||
struct seq_ump_client *client,
|
||||
struct seq_ump_group *group)
|
||||
struct snd_ump_group *group)
|
||||
{
|
||||
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;
|
||||
if (!group->active)
|
||||
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 |
|
||||
SNDRV_SEQ_PORT_TYPE_MIDI_UMP |
|
||||
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 */
|
||||
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 &&
|
||||
(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 */
|
||||
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_callback pcallbacks;
|
||||
|
||||
@@ -233,7 +225,7 @@ static int seq_ump_group_init(struct seq_ump_client *client, int group_index)
|
||||
return -ENOMEM;
|
||||
|
||||
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));
|
||||
pcallbacks.owner = THIS_MODULE;
|
||||
pcallbacks.private_data = client;
|
||||
@@ -261,7 +253,7 @@ static void update_port_infos(struct seq_ump_client *client)
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
old->addr.client = client->seq_client;
|
||||
@@ -271,7 +263,7 @@ static void update_port_infos(struct seq_ump_client *client)
|
||||
old);
|
||||
if (err < 0)
|
||||
return;
|
||||
fill_port_info(new, client, &client->groups[i]);
|
||||
fill_port_info(new, client, &client->ump->groups[i]);
|
||||
if (old->capability == new->capability &&
|
||||
!strcmp(old->name, new->name))
|
||||
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 */
|
||||
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;
|
||||
filter = ~(1U << 0); /* always allow groupless messages */
|
||||
for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) {
|
||||
if (client->groups[p].active)
|
||||
if (client->ump->groups[p].active)
|
||||
filter &= ~(1U << (p + 1));
|
||||
}
|
||||
cptr->group_filter = filter;
|
||||
@@ -445,7 +386,6 @@ static void handle_group_notify(struct work_struct *work)
|
||||
struct seq_ump_client *client =
|
||||
container_of(work, struct seq_ump_client, group_notify_work);
|
||||
|
||||
update_group_attrs(client);
|
||||
update_port_infos(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;
|
||||
|
||||
setup_client_midi_version(client);
|
||||
update_group_attrs(client);
|
||||
|
||||
for (p = 0; p < SNDRV_UMP_MAX_GROUPS; 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]);
|
||||
|
||||
if (snd_seq_client_is_ump(dest)) {
|
||||
if (snd_seq_client_is_midi2(dest) &&
|
||||
type == UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE)
|
||||
bool is_midi2 = snd_seq_client_is_midi2(dest) &&
|
||||
!dest_port->is_midi1;
|
||||
|
||||
if (is_midi2 && type == UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE)
|
||||
return cvt_ump_midi1_to_midi2(dest, dest_port,
|
||||
event, atomic, hop);
|
||||
else if (!snd_seq_client_is_midi2(dest) &&
|
||||
type == UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE)
|
||||
else if (!is_midi2 && type == UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE)
|
||||
return cvt_ump_midi2_to_midi1(dest, dest_port,
|
||||
event, atomic, hop);
|
||||
/* 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 */
|
||||
if (event->type == SNDRV_SEQ_EVENT_SYSEX)
|
||||
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);
|
||||
else
|
||||
return cvt_to_ump_midi1(dest, dest_port, event, atomic, hop);
|
||||
|
||||
+227
-2
@@ -13,6 +13,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/anon_inodes.h>
|
||||
#include <linux/idr.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/timer.h>
|
||||
#include <sound/control.h>
|
||||
@@ -109,6 +111,16 @@ struct snd_timer_status64 {
|
||||
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)
|
||||
|
||||
/* 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 =
|
||||
{
|
||||
.flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_WORK,
|
||||
.resolution = 1000000000L / HZ,
|
||||
.resolution = NSEC_PER_SEC / HZ,
|
||||
.ticks = 10000000L,
|
||||
.close = snd_timer_s_close,
|
||||
.start = snd_timer_s_start,
|
||||
@@ -1603,7 +1615,7 @@ static int snd_timer_user_ginfo(struct file *file,
|
||||
|
||||
ginfo = memdup_user(_ginfo, sizeof(*ginfo));
|
||||
if (IS_ERR(ginfo))
|
||||
return PTR_ERR(no_free_ptr(ginfo));
|
||||
return PTR_ERR(ginfo);
|
||||
|
||||
tid = ginfo->tid;
|
||||
memset(ginfo, 0, sizeof(*ginfo));
|
||||
@@ -2009,6 +2021,217 @@ enum {
|
||||
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,
|
||||
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_OLD:
|
||||
return snd_timer_user_pause(file);
|
||||
case SNDRV_TIMER_IOCTL_CREATE:
|
||||
return snd_utimer_ioctl_create(file, argp);
|
||||
}
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
+99
-21
@@ -489,11 +489,7 @@ static void snd_ump_proc_read(struct snd_info_entry *entry,
|
||||
ump->info.manufacturer_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, "SW Revision: 0x%02x%02x%02x%02x\n",
|
||||
ump->info.sw_revision[0],
|
||||
ump->info.sw_revision[1],
|
||||
ump->info.sw_revision[2],
|
||||
ump->info.sw_revision[3]);
|
||||
snd_iprintf(buffer, "SW Revision: 0x%4phN\n", ump->info.sw_revision);
|
||||
}
|
||||
snd_iprintf(buffer, "Static Blocks: %s\n",
|
||||
(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
|
||||
*/
|
||||
@@ -602,6 +654,17 @@ static int ump_append_string(struct snd_ump_endpoint *ump, char *dest,
|
||||
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 */
|
||||
static int ump_handle_ep_info_msg(struct snd_ump_endpoint *ump,
|
||||
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->info.version, ump->info.num_blocks, ump->info.protocol_caps);
|
||||
|
||||
ump->info.protocol &= ump->info.protocol_caps;
|
||||
choose_default_protocol(ump);
|
||||
|
||||
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[2] = (buf->device_info.sw_revision >> 8) & 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.family_id,
|
||||
ump->info.model_id,
|
||||
ump->info.sw_revision[0],
|
||||
ump->info.sw_revision[1],
|
||||
ump->info.sw_revision[2],
|
||||
ump->info.sw_revision[3]);
|
||||
ump->info.sw_revision);
|
||||
return 1; /* finished */
|
||||
}
|
||||
|
||||
@@ -792,8 +856,10 @@ static int ump_handle_fb_info_msg(struct snd_ump_endpoint *ump,
|
||||
|
||||
if (fb) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
buf->raw, 3);
|
||||
/* 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);
|
||||
}
|
||||
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");
|
||||
|
||||
/* If no protocol is set by some reason, assume the valid one */
|
||||
if (!(ump->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK)) {
|
||||
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;
|
||||
}
|
||||
choose_default_protocol(ump);
|
||||
|
||||
/* Query and create blocks from Function Blocks */
|
||||
for (blk = 0; blk < ump->info.num_blocks; blk++) {
|
||||
@@ -995,6 +1058,9 @@ int snd_ump_parse_endpoint(struct snd_ump_endpoint *ump)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* initialize group attributions */
|
||||
snd_ump_update_group_attrs(ump);
|
||||
|
||||
error:
|
||||
ump->parsed = true;
|
||||
ump_request_close(ump);
|
||||
@@ -1097,6 +1163,7 @@ static int process_legacy_output(struct snd_ump_endpoint *ump,
|
||||
struct snd_rawmidi_substream *substream;
|
||||
struct ump_cvt_to_ump *ctx;
|
||||
const int dir = SNDRV_RAWMIDI_STREAM_OUTPUT;
|
||||
unsigned int protocol;
|
||||
unsigned char c;
|
||||
int group, size = 0;
|
||||
|
||||
@@ -1109,9 +1176,13 @@ static int process_legacy_output(struct snd_ump_endpoint *ump,
|
||||
if (!substream)
|
||||
continue;
|
||||
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 &&
|
||||
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) {
|
||||
size = ctx->ump_bytes;
|
||||
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_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)",
|
||||
ump->legacy_mapping[s->number] + 1, ump->info.name);
|
||||
idx + 1, name);
|
||||
}
|
||||
}
|
||||
|
||||
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.subdevice);
|
||||
snd_iprintf(buffer, " timer open:\t\t%s\n",
|
||||
(cable->snd_timer.stream == SNDRV_PCM_STREAM_CAPTURE) ?
|
||||
"capture" : "playback");
|
||||
snd_pcm_direction_name(cable->snd_timer.stream));
|
||||
}
|
||||
|
||||
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) {
|
||||
tid->card = card_idx;
|
||||
tid->device = dev;
|
||||
@@ -1897,7 +1898,7 @@ static int __init alsa_card_loopback_init(void)
|
||||
}
|
||||
if (!cards) {
|
||||
#ifdef MODULE
|
||||
printk(KERN_ERR "aloop: No loopback enabled\n");
|
||||
pr_err("aloop: No loopback enabled\n");
|
||||
#endif
|
||||
loopback_unregister_all();
|
||||
return -ENODEV;
|
||||
|
||||
@@ -1033,8 +1033,7 @@ static int snd_dummy_probe(struct platform_device *devptr)
|
||||
dummy->card = card;
|
||||
for (mdl = dummy_models; *mdl && model[dev]; mdl++) {
|
||||
if (strcmp(model[dev], (*mdl)->name) == 0) {
|
||||
printk(KERN_INFO
|
||||
"snd-dummy: Using model '%s' for card %i\n",
|
||||
pr_info("snd-dummy: Using model '%s' for card %i\n",
|
||||
(*mdl)->name, card->number);
|
||||
m = dummy->model = *mdl;
|
||||
break;
|
||||
@@ -1168,7 +1167,7 @@ static int __init alsa_card_dummy_init(void)
|
||||
}
|
||||
if (!cards) {
|
||||
#ifdef MODULE
|
||||
printk(KERN_ERR "Dummy soundcard not found or device busy\n");
|
||||
pr_err("Dummy soundcard not found or device busy\n");
|
||||
#endif
|
||||
snd_dummy_unregister_all();
|
||||
return -ENODEV;
|
||||
|
||||
@@ -56,7 +56,7 @@ static int snd_mpu401_create(struct device *devptr, int dev,
|
||||
int err;
|
||||
|
||||
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;
|
||||
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,
|
||||
irq[dev], NULL);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -90,11 +90,11 @@ static int snd_mpu401_probe(struct platform_device *devptr)
|
||||
struct snd_card *card;
|
||||
|
||||
if (port[dev] == SNDRV_AUTO_PORT) {
|
||||
snd_printk(KERN_ERR "specify port\n");
|
||||
dev_err(&devptr->dev, "specify port\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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) ||
|
||||
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;
|
||||
}
|
||||
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),
|
||||
IO_EXTENT);
|
||||
return -ENODEV;
|
||||
@@ -146,7 +146,7 @@ static int snd_mpu401_pnp(int dev, struct pnp_dev *device,
|
||||
|
||||
if (!pnp_irq_valid(device, 0) ||
|
||||
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;
|
||||
} else {
|
||||
irq[dev] = pnp_irq(device, 0);
|
||||
@@ -234,7 +234,7 @@ static int __init alsa_card_mpu401_init(void)
|
||||
|
||||
if (!snd_mpu401_devices) {
|
||||
#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
|
||||
snd_mpu401_unregister_all();
|
||||
return -ENODEV;
|
||||
|
||||
@@ -73,8 +73,9 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu)
|
||||
mpu->read(mpu, MPU401D(mpu));
|
||||
#ifdef CONFIG_SND_DEBUG
|
||||
if (timeout <= 0)
|
||||
snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n",
|
||||
mpu->read(mpu, MPU401C(mpu)));
|
||||
dev_err(mpu->rmidi->dev,
|
||||
"cmd: clear rx timeout (status = 0x%x)\n",
|
||||
mpu->read(mpu, MPU401C(mpu)));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -224,8 +225,9 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
|
||||
udelay(10);
|
||||
#ifdef CONFIG_SND_DEBUG
|
||||
if (!timeout)
|
||||
snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n",
|
||||
mpu->read(mpu, MPU401C(mpu)));
|
||||
dev_err(mpu->rmidi->dev,
|
||||
"cmd: tx timeout (status = 0x%x)\n",
|
||||
mpu->read(mpu, MPU401C(mpu)));
|
||||
#endif
|
||||
}
|
||||
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;
|
||||
spin_unlock_irqrestore(&mpu->input_lock, flags);
|
||||
if (!ok) {
|
||||
snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx "
|
||||
"(status = 0x%x, data = 0x%x)\n", cmd, mpu->port,
|
||||
mpu->read(mpu, MPU401C(mpu)),
|
||||
mpu->read(mpu, MPU401D(mpu)));
|
||||
dev_err(mpu->rmidi->dev,
|
||||
"cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n",
|
||||
cmd, mpu->port,
|
||||
mpu->read(mpu, MPU401C(mpu)),
|
||||
mpu->read(mpu, MPU401D(mpu)));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -546,13 +549,14 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
|
||||
spin_lock_init(&mpu->timer_lock);
|
||||
mpu->hardware = hardware;
|
||||
mpu->irq = -1;
|
||||
mpu->rmidi = rmidi;
|
||||
if (! (info_flags & MPU401_INFO_INTEGRATED)) {
|
||||
int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
|
||||
mpu->res = request_region(port, res_size, "MPU401 UART");
|
||||
if (!mpu->res) {
|
||||
snd_printk(KERN_ERR "mpu401_uart: "
|
||||
"unable to grab port 0x%lx size %d\n",
|
||||
port, res_size);
|
||||
dev_err(rmidi->dev,
|
||||
"mpu401_uart: unable to grab port 0x%lx size %d\n",
|
||||
port, res_size);
|
||||
err = -EBUSY;
|
||||
goto free_device;
|
||||
}
|
||||
@@ -572,8 +576,8 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
|
||||
if (irq >= 0) {
|
||||
if (request_irq(irq, snd_mpu401_uart_interrupt, 0,
|
||||
"MPU401 UART", (void *) mpu)) {
|
||||
snd_printk(KERN_ERR "mpu401_uart: "
|
||||
"unable to grab IRQ %d\n", irq);
|
||||
dev_err(rmidi->dev,
|
||||
"mpu401_uart: unable to grab IRQ %d\n", irq);
|
||||
err = -EBUSY;
|
||||
goto free_device;
|
||||
}
|
||||
@@ -599,7 +603,6 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
|
||||
if (out_enable)
|
||||
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
|
||||
}
|
||||
mpu->rmidi = rmidi;
|
||||
if (rrawmidi)
|
||||
*rrawmidi = rmidi;
|
||||
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, portp->hwport);
|
||||
/*
|
||||
snd_printk(KERN_DEBUG "new outport: 0x%x\n",
|
||||
(unsigned int) portp->hwport);
|
||||
*/
|
||||
if (!(outbyte & 0x80) && 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);
|
||||
|
||||
/* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */
|
||||
|
||||
if (!(sbyt & SIGS_BYTE))
|
||||
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,
|
||||
"MotuMTPAV MIDI");
|
||||
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;
|
||||
}
|
||||
mcard->port = port;
|
||||
if (devm_request_irq(mcard->card->dev, irq, snd_mtpav_irqh, 0,
|
||||
"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;
|
||||
}
|
||||
mcard->irq = irq;
|
||||
@@ -717,7 +711,9 @@ static int snd_mtpav_probe(struct platform_device *dev)
|
||||
card->private_free = snd_mtpav_free;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -652,8 +652,8 @@ static int snd_mts64_ctl_create(struct snd_card *card,
|
||||
for (i = 0; control[i]; ++i) {
|
||||
err = snd_ctl_add(card, snd_ctl_new1(control[i], mts));
|
||||
if (err < 0) {
|
||||
snd_printd("Cannot create control: %s\n",
|
||||
control[i]->name);
|
||||
dev_dbg(card->dev, "Cannot create control: %s\n",
|
||||
control[i]->name);
|
||||
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,
|
||||
0, &card);
|
||||
if (err < 0) {
|
||||
snd_printd("Cannot create card\n");
|
||||
dev_dbg(&pdev->dev, "Cannot create card\n");
|
||||
return err;
|
||||
}
|
||||
strcpy(card->driver, DRIVER_NAME);
|
||||
@@ -940,21 +940,21 @@ static int snd_mts64_probe(struct platform_device *pdev)
|
||||
&mts64_cb, /* callbacks */
|
||||
pdev->id); /* device number */
|
||||
if (!pardev) {
|
||||
snd_printd("Cannot register pardevice\n");
|
||||
dev_dbg(card->dev, "Cannot register pardevice\n");
|
||||
err = -EIO;
|
||||
goto __err;
|
||||
}
|
||||
|
||||
/* claim parport */
|
||||
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;
|
||||
goto free_pardev;
|
||||
}
|
||||
|
||||
err = snd_mts64_create(card, pardev, &mts);
|
||||
if (err < 0) {
|
||||
snd_printd("Cannot create main component\n");
|
||||
dev_dbg(card->dev, "Cannot create main component\n");
|
||||
goto release_pardev;
|
||||
}
|
||||
card->private_data = mts;
|
||||
@@ -968,7 +968,7 @@ static int snd_mts64_probe(struct platform_device *pdev)
|
||||
|
||||
err = snd_mts64_rawmidi_create(card);
|
||||
if (err < 0) {
|
||||
snd_printd("Creating Rawmidi component failed\n");
|
||||
dev_dbg(card->dev, "Creating Rawmidi component failed\n");
|
||||
goto __err;
|
||||
}
|
||||
|
||||
@@ -982,11 +982,11 @@ static int snd_mts64_probe(struct platform_device *pdev)
|
||||
/* At this point card will be usable */
|
||||
err = snd_card_register(card);
|
||||
if (err < 0) {
|
||||
snd_printd("Cannot register card\n");
|
||||
dev_dbg(card->dev, "Cannot register card\n");
|
||||
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;
|
||||
|
||||
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);
|
||||
signature = stat1 = inb(opl3->l_port); /* Status register */
|
||||
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;
|
||||
}
|
||||
/* Set timer1 to 0xff */
|
||||
@@ -108,7 +108,7 @@ static int snd_opl3_detect(struct snd_opl3 * opl3)
|
||||
/* Reset the IRQ of the FM chip */
|
||||
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -289,9 +289,6 @@ void snd_opl3_interrupt(struct snd_hwdep * hw)
|
||||
|
||||
opl3 = hw->private_data;
|
||||
status = inb(opl3->l_port);
|
||||
#if 0
|
||||
snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status);
|
||||
#endif
|
||||
if (!(status & 0x80))
|
||||
return;
|
||||
|
||||
@@ -365,7 +362,8 @@ EXPORT_SYMBOL(snd_opl3_new);
|
||||
int snd_opl3_init(struct snd_opl3 *opl3)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -405,14 +403,14 @@ int snd_opl3_create(struct snd_card *card,
|
||||
if (! integrated) {
|
||||
opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)");
|
||||
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);
|
||||
return -EBUSY;
|
||||
}
|
||||
if (r_port != 0) {
|
||||
opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)");
|
||||
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);
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -432,8 +430,8 @@ int snd_opl3_create(struct snd_card *card,
|
||||
opl3->command = &snd_opl2_command;
|
||||
err = snd_opl3_detect(opl3);
|
||||
if (err < 0) {
|
||||
snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n",
|
||||
opl3->l_port, opl3->r_port);
|
||||
dev_dbg(card->dev, "OPL2/3 chip not detected at 0x%lx/0x%lx\n",
|
||||
opl3->l_port, opl3->r_port);
|
||||
snd_device_free(card, opl3);
|
||||
return err;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user