mirror of
https://github.com/torvalds/linux.git
synced 2025-04-09 14:45:27 +00:00
sound updates for 6.15-rc1
We've received lots of commits at this time, as a result of various cleanup and refactoring works as well as a few new drivers and the generic SoundWire support. Most of changes are device-specific, little about the core changes. Some highlights below: Core: * A couple of (rather minor) race fixes in ALSA sequencer code * A regression fix in ALSA timer code that may lead to a deadlock ASoC: * A large series of code conversion to use modern terminology for the clocking configuration * Conversions of PM ops with the modern macros in all ASoC drivers * Clarification of the control operations * Prepartory work for more generic SoundWire SCDA controls * Support for AMD ACP 7.x, AWINC WM88166, Everest ES8388, Intel AVS PEAKVOL and GAIN DSP modules Mediatek MT8188 DMIC, NXP i.MX95, nVidia Tegra interconnects, Rockchip RK3588 S/PDIF, Texas Instruments SN012776 and TAS5770L, and Wolfson WM8904 DMICs Others: * Conversions of PM ops with the modern macros in the rest drivers * USB-audio quirks and fixes for Presonus Studio, DJM-A9, CME * HD-audio quirks and fixes ASUS, HP, Lenovo, and others Note that the PR contains some changes from the tip tree for AMD code, and it might give some merge conflict due to the rebase afterwards. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmfi3o0OHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE+mhQ//QPp4w4pegFco3//6lc6tTX1n61Ab8m9Vl1CF ALPN/zI7tkaI8S3cVNA3uXlzWSdmYzJOHvy8LrUAWG4e/cPQqTy9+oyZjnVrIthL lszAIh51fR7whtKabBQADdHzBPSPWwX5HmeiBlBP8TriCtM5wprZ4Wi8gaVrPw2G u4JqpRCpFQGf2S4WGnVGvV/7fyRM+R9LUhAX7BAFmSdtoz4oyg3Mt8R3MdAQkNOi eHX1n342b06UG9MRjv258RSW+ilf1ccPdMRVCayuVt789lgUUdo9DKhQiM6vPlT9 FHtCbLGXkaYwxOsRuWGkPiRxc2xPLtvuSLhmiTomR1va/FnH+VW0Ghk5cwg0i31U mBNqdtgxYglb6Vp41OYRCImRa3dhFjR/SIHN1OokQpkzY4vsl1nu1kDXxHQttc9d qfXwWmviFN/Wg8hXFsEeGo26ISU+GQAmZksKfvF3YHJy/kz/amS8zSXDmUgL5WD9 ttK25orLxptZ80sRVTywoPH25b8H4wgwRLdwvYCPqOLx8jv7V86n32gudWAibBz5 Yua0TmWxd2r2LZVt3TdJgAhJSHXCDTdoybcwGoDn1p+jDRqcJDCpyL23TH+eAQUg whqQRTYVH/E/Cd1V2oATxeLwUsILkUOiHXqc7s12KMdU1rmL/S/rsASDuumxow7V viUoVAM= =NaAN -----END PGP SIGNATURE----- Merge tag 'sound-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "We've received lots of commits at this time, as a result of various cleanup and refactoring works as well as a few new drivers and the generic SoundWire support. Most of changes are device-specific, little about the core changes. Some highlights below: Core: - A couple of (rather minor) race fixes in ALSA sequencer code - A regression fix in ALSA timer code that may lead to a deadlock ASoC: - A large series of code conversion to use modern terminology for the clocking configuration - Conversions of PM ops with the modern macros in all ASoC drivers - Clarification of the control operations - Prepartory work for more generic SoundWire SCDA controls - Support for AMD ACP 7.x, AWINC WM88166, Everest ES8388, Intel AVS PEAKVOL and GAIN DSP modules Mediatek MT8188 DMIC, NXP i.MX95, nVidia Tegra interconnects, Rockchip RK3588 S/PDIF, Texas Instruments SN012776 and TAS5770L, and Wolfson WM8904 DMICs Others: - Conversions of PM ops with the modern macros in the rest drivers - USB-audio quirks and fixes for Presonus Studio, DJM-A9, CME - HD-audio quirks and fixes ASUS, HP, Lenovo, and others" * tag 'sound-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (651 commits) ALSA: hda: tas2781-i2c: Remove unnecessary NULL check before release_firmware() ALSA: hda: cs35l56: Remove unnecessary NULL check before release_firmware() ALSA: hda/realtek: Bass speaker fixup for ASUS UM5606KA ALSA: hda/realtek: Fix built-in mic assignment on ASUS VivoBook X515UA ALSA: hda/realtek: Add support for various HP Laptops using CS35L41 HDA ALSA: timer: Don't take register_mutex with copy_from/to_user() ASoC: SDCA: Correct handling of selected mode DisCo property ASoC: amd: yc: update quirk data for new Lenovo model ALSA: hda/realtek: fix micmute LEDs on HP Laptops with ALC3247 ALSA: hda/realtek: fix micmute LEDs on HP Laptops with ALC3315 ASoC: SOF: mediatek: Commonize duplicated functions ASoC: dmic: Fix NULL pointer dereference ASoC: wm8904: add DMIC support ASoC: wm8904: get platform data from DT ASoC: dt-bindings: wm8904: Add DMIC, GPIO, MIC and EQ support ASoC: wm8904: Don't touch GPIO configs set to 0xFFFF of: Add of_property_read_u16_index ALSA: oxygen: Fix dependency on CONFIG_PM_SLEEP ASoC: ops: Apply platform_max after deciding control type ASoC: ops: Remove some unnecessary local variables ...
This commit is contained in:
commit
e50da555ca
@ -31,6 +31,10 @@ node must be named "audio-codec".
|
||||
Required properties for the audio-codec subnode:
|
||||
|
||||
- #sound-dai-cells = <1>;
|
||||
- interrupts : should contain jack detection interrupts, with headset
|
||||
detect interrupt matching "hs" and microphone bias 2
|
||||
detect interrupt matching "mb2" in interrupt-names.
|
||||
- interrupt-names : Contains "hs", "mb2"
|
||||
|
||||
The audio-codec provides two DAIs. The first one is connected to the
|
||||
Stereo HiFi DAC and the second one is connected to the Voice DAC.
|
||||
@ -52,6 +56,8 @@ Example:
|
||||
|
||||
audio-codec {
|
||||
#sound-dai-cells = <1>;
|
||||
interrupts-extended = <&cpcap 9 0>, <&cpcap 10 0>;
|
||||
interrupt-names = "hs", "mb2";
|
||||
|
||||
/* HiFi */
|
||||
port@0 {
|
||||
|
@ -1,50 +0,0 @@
|
||||
* Atmel SSC driver.
|
||||
|
||||
Required properties:
|
||||
- compatible: "atmel,at91rm9200-ssc" or "atmel,at91sam9g45-ssc"
|
||||
- atmel,at91rm9200-ssc: support pdc transfer
|
||||
- atmel,at91sam9g45-ssc: support dma transfer
|
||||
- reg: Should contain SSC registers location and length
|
||||
- interrupts: Should contain SSC interrupt
|
||||
- clock-names: tuple listing input clock names.
|
||||
Required elements: "pclk"
|
||||
- clocks: phandles to input clocks.
|
||||
|
||||
|
||||
Required properties for devices compatible with "atmel,at91sam9g45-ssc":
|
||||
- dmas: DMA specifier, consisting of a phandle to DMA controller node,
|
||||
the memory interface and SSC DMA channel ID (for tx and rx).
|
||||
See Documentation/devicetree/bindings/dma/atmel-dma.txt for details.
|
||||
- dma-names: Must be "tx", "rx".
|
||||
|
||||
Optional properties:
|
||||
- atmel,clk-from-rk-pin: bool property.
|
||||
- When SSC works in slave mode, according to the hardware design, the
|
||||
clock can get from TK pin, and also can get from RK pin. So, add
|
||||
this parameter to choose where the clock from.
|
||||
- By default the clock is from TK pin, if the clock from RK pin, this
|
||||
property is needed.
|
||||
- #sound-dai-cells: Should contain <0>.
|
||||
- This property makes the SSC into an automatically registered DAI.
|
||||
|
||||
Examples:
|
||||
- PDC transfer:
|
||||
ssc0: ssc@fffbc000 {
|
||||
compatible = "atmel,at91rm9200-ssc";
|
||||
reg = <0xfffbc000 0x4000>;
|
||||
interrupts = <14 4 5>;
|
||||
clocks = <&ssc0_clk>;
|
||||
clock-names = "pclk";
|
||||
};
|
||||
|
||||
- DMA transfer:
|
||||
ssc0: ssc@f0010000 {
|
||||
compatible = "atmel,at91sam9g45-ssc";
|
||||
reg = <0xf0010000 0x4000>;
|
||||
interrupts = <28 4 5>;
|
||||
dmas = <&dma0 1 13>,
|
||||
<&dma0 1 14>;
|
||||
dma-names = "tx", "rx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
|
||||
};
|
@ -102,6 +102,10 @@ properties:
|
||||
maxItems: 1
|
||||
description: GPIO to enable the external amplifier
|
||||
|
||||
hp-det-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO for headphone/line-out detection
|
||||
|
||||
required:
|
||||
- "#sound-dai-cells"
|
||||
- compatible
|
||||
@ -251,8 +255,10 @@ allOf:
|
||||
allwinner,audio-routing:
|
||||
items:
|
||||
enum:
|
||||
- Headphone
|
||||
- LINEOUT
|
||||
- Line Out
|
||||
- Speaker
|
||||
|
||||
dmas:
|
||||
items:
|
||||
|
104
Documentation/devicetree/bindings/sound/atmel,at91-ssc.yaml
Normal file
104
Documentation/devicetree/bindings/sound/atmel,at91-ssc.yaml
Normal file
@ -0,0 +1,104 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/atmel,at91-ssc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Atmel Serial Synchronous Serial (SSC)
|
||||
|
||||
maintainers:
|
||||
- Andrei Simion <andrei.simion@microchip.com>
|
||||
|
||||
description:
|
||||
The Atmel Synchronous Serial Controller (SSC) provides a versatile
|
||||
synchronous communication link for audio and telecom applications,
|
||||
supporting protocols like I2S, Short Frame Sync, and Long Frame Sync.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- atmel,at91rm9200-ssc
|
||||
- atmel,at91sam9g45-ssc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: TX DMA Channel
|
||||
- description: RX DMA Channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
atmel,clk-from-rk-pin:
|
||||
description:
|
||||
Specify the clock source for the SSC (Synchronous Serial Controller)
|
||||
when operating in slave mode. By default, the clock is sourced from
|
||||
the TK pin.
|
||||
type: boolean
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- atmel,at91sam9g45-ssc
|
||||
then:
|
||||
required:
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/at91.h>
|
||||
#include <dt-bindings/dma/at91.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
ssc@100000 {
|
||||
compatible = "atmel,at91sam9g45-ssc";
|
||||
reg = <0x100000 0x4000>;
|
||||
interrupts = <28 IRQ_TYPE_LEVEL_HIGH 5>;
|
||||
dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
|
||||
AT91_XDMAC_DT_PERID(38))>,
|
||||
<&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
|
||||
AT91_XDMAC_DT_PERID(39))>;
|
||||
dma-names = "tx", "rx";
|
||||
clocks = <&pmc PMC_TYPE_PERIPHERAL 28>;
|
||||
clock-names = "pclk";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
|
||||
ssc@c00000 {
|
||||
compatible = "atmel,at91rm9200-ssc";
|
||||
reg = <0xc00000 0x4000>;
|
||||
interrupts = <14 IRQ_TYPE_LEVEL_HIGH 5>;
|
||||
clocks = <&pmc PMC_TYPE_PERIPHERAL 14>;
|
||||
clock-names = "pclk";
|
||||
};
|
@ -0,0 +1,72 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/atmel,at91sam9g20ek-wm8731.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Atmel at91sam9g20ek wm8731 audio complex
|
||||
|
||||
maintainers:
|
||||
- Balakrishnan Sambath <balakrishnan.s@microchip.com>
|
||||
|
||||
description:
|
||||
The audio complex configuration for Atmel at91sam9g20ek with WM8731 audio codec.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: atmel,at91sam9g20ek-wm8731-audio
|
||||
|
||||
atmel,model:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: The user-visible name of this sound complex.
|
||||
|
||||
atmel,audio-routing:
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
description: A list of the connections between audio components.
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
items:
|
||||
enum:
|
||||
# Board Connectors
|
||||
- Ext Spk
|
||||
- Int Mic
|
||||
|
||||
# CODEC Pins
|
||||
- LOUT
|
||||
- ROUT
|
||||
- LHPOUT
|
||||
- RHPOUT
|
||||
- LLINEIN
|
||||
- RLINEIN
|
||||
- MICIN
|
||||
|
||||
atmel,ssc-controller:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: The phandle of the SSC controller.
|
||||
|
||||
atmel,audio-codec:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: The phandle of WM8731 audio codec.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- atmel,model
|
||||
- atmel,audio-routing
|
||||
- atmel,ssc-controller
|
||||
- atmel,audio-codec
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sound {
|
||||
compatible = "atmel,at91sam9g20ek-wm8731-audio";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_pck0_as_mck>;
|
||||
atmel,model = "wm8731 @ AT91SAMG20EK";
|
||||
atmel,audio-routing =
|
||||
"Ext Spk", "LHPOUT",
|
||||
"Int Mic", "MICIN";
|
||||
atmel,ssc-controller = <&ssc0>;
|
||||
atmel,audio-codec = <&wm8731>;
|
||||
};
|
@ -1,26 +0,0 @@
|
||||
* Atmel at91sam9g20ek wm8731 audio complex
|
||||
|
||||
Required properties:
|
||||
- compatible: "atmel,at91sam9g20ek-wm8731-audio"
|
||||
- atmel,model: The user-visible name of this sound complex.
|
||||
- atmel,audio-routing: A list of the connections between audio components.
|
||||
- atmel,ssc-controller: The phandle of the SSC controller
|
||||
- atmel,audio-codec: The phandle of the WM8731 audio codec
|
||||
Optional properties:
|
||||
- pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt
|
||||
|
||||
Example:
|
||||
sound {
|
||||
compatible = "atmel,at91sam9g20ek-wm8731-audio";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_pck0_as_mck>;
|
||||
|
||||
atmel,model = "wm8731 @ AT91SAMG20EK";
|
||||
|
||||
atmel,audio-routing =
|
||||
"Ext Spk", "LHPOUT",
|
||||
"Int MIC", "MICIN";
|
||||
|
||||
atmel,ssc-controller = <&ssc0>;
|
||||
atmel,audio-codec = <&wm8731>;
|
||||
};
|
@ -37,6 +37,10 @@ properties:
|
||||
codec2codec:
|
||||
type: object
|
||||
description: Codec to Codec node
|
||||
hp-det-gpios:
|
||||
$ref: audio-graph.yaml#/properties/hp-det-gpios
|
||||
widgets:
|
||||
$ref: audio-graph.yaml#/properties/widgets
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -19,6 +19,7 @@ properties:
|
||||
enum:
|
||||
- awinic,aw88081
|
||||
- awinic,aw88083
|
||||
- awinic,aw88166
|
||||
- awinic,aw88261
|
||||
- awinic,aw88395
|
||||
- awinic,aw88399
|
||||
|
@ -19,6 +19,9 @@ properties:
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
vref-supply:
|
||||
description: Phandle to the digital microphone reference supply
|
||||
|
||||
dmicen-gpios:
|
||||
description: GPIO specifier for DMIC to control start and stop
|
||||
maxItems: 1
|
||||
|
@ -24,9 +24,13 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- everest,es8328
|
||||
- everest,es8388
|
||||
oneOf:
|
||||
- enum:
|
||||
- everest,es8328
|
||||
- items:
|
||||
- enum:
|
||||
- everest,es8388
|
||||
- const: everest,es8328
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -56,6 +60,7 @@ properties:
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- DVDD-supply
|
||||
- AVDD-supply
|
||||
|
@ -61,13 +61,26 @@ properties:
|
||||
- description: serial audio input 2
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
patternProperties:
|
||||
'^port@[0-1]':
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: Input port from SAI TX
|
||||
|
||||
properties:
|
||||
port@2:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: Output port to SAI RX
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
- dais
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
@ -80,4 +93,50 @@ examples:
|
||||
clock-names = "ipg";
|
||||
power-domains = <&pd_audmix>;
|
||||
dais = <&sai4>, <&sai5>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
playback-only;
|
||||
|
||||
amix_endpoint0: endpoint {
|
||||
dai-tdm-slot-num = <8>;
|
||||
dai-tdm-slot-width = <32>;
|
||||
dai-tdm-slot-width-map = <32 8 32>;
|
||||
dai-format = "dsp_a";
|
||||
remote-endpoint = <&be00_ep>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
playback-only;
|
||||
|
||||
amix_endpoint1: endpoint {
|
||||
dai-tdm-slot-num = <8>;
|
||||
dai-tdm-slot-width = <32>;
|
||||
dai-tdm-slot-width-map = <32 8 32>;
|
||||
dai-format = "dsp_a";
|
||||
remote-endpoint = <&be01_ep>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
capture-only;
|
||||
|
||||
amix_endpoint2: endpoint {
|
||||
dai-tdm-slot-num = <8>;
|
||||
dai-tdm-slot-width = <32>;
|
||||
dai-tdm-slot-width-map = <32 8 32>;
|
||||
dai-format = "dsp_a";
|
||||
bitclock-master;
|
||||
frame-master;
|
||||
remote-endpoint = <&be02_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -80,7 +80,10 @@ required:
|
||||
- fsl,asrc-rate
|
||||
- fsl,asrc-format
|
||||
|
||||
additionalProperties: false
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -77,6 +77,10 @@ properties:
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
fsl,asrc-rate:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: The mutual sample rate used by DPCM Back Ends
|
||||
@ -120,6 +124,7 @@ required:
|
||||
- fsl,asrc-width
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
@ -145,7 +150,7 @@ allOf:
|
||||
required:
|
||||
- power-domains
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
@ -173,4 +178,12 @@ examples:
|
||||
"txa", "txb", "txc";
|
||||
fsl,asrc-rate = <48000>;
|
||||
fsl,asrc-width = <16>;
|
||||
|
||||
port {
|
||||
playback-only;
|
||||
|
||||
asrc_endpoint: endpoint {
|
||||
remote-endpoint = <&fe00_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/fsl,imx95-cm7-sof.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP imx95 CM7 core
|
||||
|
||||
maintainers:
|
||||
- Daniel Baluta <daniel.baluta@nxp.com>
|
||||
|
||||
description: NXP imx95 CM7 core used for audio processing
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,imx95-cm7-sof
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reg-names:
|
||||
const: sram
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
|
||||
memory-region-names:
|
||||
const: dma
|
||||
|
||||
port:
|
||||
description: SAI3 port
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- memory-region
|
||||
- memory-region-names
|
||||
- port
|
||||
|
||||
allOf:
|
||||
- $ref: fsl,sof-cpu.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
cm7-cpu@80000000 {
|
||||
compatible = "fsl,imx95-cm7-sof";
|
||||
reg = <0x80000000 0x6100000>;
|
||||
reg-names = "sram";
|
||||
mboxes = <&mu7 2 0>, <&mu7 2 1>, <&mu7 3 0>, <&mu7 3 1>;
|
||||
mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1";
|
||||
memory-region = <&adma_res>;
|
||||
memory-region-names = "dma";
|
||||
port {
|
||||
/* SAI3-WM8962 link */
|
||||
endpoint {
|
||||
remote-endpoint = <&wm8962_ep>;
|
||||
};
|
||||
};
|
||||
};
|
@ -41,6 +41,10 @@ properties:
|
||||
- fsl,imx93-sai
|
||||
- fsl,imx95-sai
|
||||
- fsl,vf610-sai
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx94-sai
|
||||
- const: fsl,imx95-sai
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -93,6 +97,24 @@ properties:
|
||||
items:
|
||||
- description: receive and transmit interrupt
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
properties:
|
||||
port@0:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: port for TX and RX
|
||||
|
||||
port@1:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: port for TX only
|
||||
|
||||
port@2:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: port for RX only
|
||||
|
||||
big-endian:
|
||||
description: |
|
||||
required if all the SAI registers are big-endian rather than little-endian.
|
||||
@ -204,4 +226,37 @@ examples:
|
||||
dma-names = "rx", "tx";
|
||||
fsl,dataline = <1 0xff 0xff 2 0xff 0x11>;
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
playback-only;
|
||||
|
||||
sai1_endpoint0: endpoint {
|
||||
dai-tdm-slot-num = <8>;
|
||||
dai-tdm-slot-width = <32>;
|
||||
dai-tdm-slot-width-map = <32 8 32>;
|
||||
dai-format = "dsp_a";
|
||||
bitclock-master;
|
||||
frame-master;
|
||||
remote-endpoint = <&mcodec01_ep>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
capture-only;
|
||||
|
||||
sai1_endpoint1: endpoint {
|
||||
dai-tdm-slot-num = <8>;
|
||||
dai-tdm-slot-width = <32>;
|
||||
dai-tdm-slot-width-map = <32 8 32>;
|
||||
dai-format = "dsp_a";
|
||||
remote-endpoint = <&fe02_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
27
Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml
Normal file
27
Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/fsl,sof-cpu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP audio processor common properties
|
||||
|
||||
maintainers:
|
||||
- Daniel Baluta <daniel.baluta@nxp.com>
|
||||
|
||||
properties:
|
||||
mboxes:
|
||||
maxItems: 4
|
||||
|
||||
mbox-names:
|
||||
items:
|
||||
- const: txdb0
|
||||
- const: txdb1
|
||||
- const: rxdb0
|
||||
- const: rxdb1
|
||||
|
||||
required:
|
||||
- mboxes
|
||||
- mbox-names
|
||||
|
||||
additionalProperties: true
|
@ -46,6 +46,14 @@ patternProperties:
|
||||
description: see tdm-slot.txt.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
playback-only:
|
||||
description: link is used only for playback
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
capture-only:
|
||||
description: link is used only for capture
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
cpu:
|
||||
description: Holds subnode which indicates cpu dai.
|
||||
type: object
|
||||
@ -71,6 +79,12 @@ patternProperties:
|
||||
- link-name
|
||||
- cpu
|
||||
|
||||
allOf:
|
||||
- not:
|
||||
required:
|
||||
- playback-only
|
||||
- capture-only
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
|
@ -40,6 +40,14 @@ properties:
|
||||
hardware that provides additional audio functionalities if present.
|
||||
The AFE will link to ADSP when the phandle is provided.
|
||||
|
||||
mediatek,accdet:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
The phandle to the MT6359 accessory detection block, which detects audio
|
||||
jack insertion and removal. This property should only be present if the
|
||||
accdet block is actually wired to the audio jack pins and to be used for
|
||||
jack detection.
|
||||
|
||||
patternProperties:
|
||||
"^dai-link-[0-9]+$":
|
||||
type: object
|
||||
@ -62,6 +70,7 @@ patternProperties:
|
||||
- PCM1_BE
|
||||
- DL_SRC_BE
|
||||
- UL_SRC_BE
|
||||
- DMIC_BE
|
||||
|
||||
codec:
|
||||
description: Holds subnode which indicates codec dai.
|
||||
|
@ -58,6 +58,40 @@ properties:
|
||||
items:
|
||||
enum: [1, 2, 3, 4, 5]
|
||||
|
||||
qcom,tx-channel-mapping:
|
||||
description: |
|
||||
Specifies static channel mapping between slave and master tx port
|
||||
channels.
|
||||
In the order of slave port channels which is adc1, adc2, adc3,
|
||||
dmic0, dmic1, mbhc, dmic2, dmic3, dmci4, dmic5, dmic6, dmic7.
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
minItems: 12
|
||||
maxItems: 12
|
||||
additionalItems: false
|
||||
items:
|
||||
enum:
|
||||
- 1 # WCD9370_SWRM_CH1
|
||||
- 2 # WCD9370_SWRM_CH2
|
||||
- 3 # WCD9370_SWRM_CH3
|
||||
- 4 # WCD9370_SWRM_CH4
|
||||
|
||||
qcom,rx-channel-mapping:
|
||||
description: |
|
||||
Specifies static channels mapping between slave and master rx port
|
||||
channels.
|
||||
In the order of slave port channels, which is
|
||||
hph_l, hph_r, clsh, comp_l, comp_r, lo, dsd_r, dsd_l.
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
minItems: 8
|
||||
maxItems: 8
|
||||
additionalItems: false
|
||||
items:
|
||||
enum:
|
||||
- 1 # WCD9370_SWRM_CH1
|
||||
- 2 # WCD9370_SWRM_CH2
|
||||
- 3 # WCD9370_SWRM_CH3
|
||||
- 4 # WCD9370_SWRM_CH4
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -74,6 +108,7 @@ examples:
|
||||
compatible = "sdw20217010a00";
|
||||
reg = <0 4>;
|
||||
qcom,rx-port-mapping = <1 2 3 4 5>;
|
||||
qcom,rx-channel-mapping = /bits/ 8 <1 2 1 1 2 1 1 2>;
|
||||
};
|
||||
};
|
||||
|
||||
@ -85,6 +120,7 @@ examples:
|
||||
compatible = "sdw20217010a00";
|
||||
reg = <0 3>;
|
||||
qcom,tx-port-mapping = <2 2 3 4>;
|
||||
qcom,tx-channel-mapping = /bits/ 8 <1 2 1 1 2 3 3 4 1 2 3 4>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,10 @@ properties:
|
||||
- rockchip,rk3288-spdif
|
||||
- rockchip,rk3308-spdif
|
||||
- const: rockchip,rk3066-spdif
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,rk3588-spdif
|
||||
- const: rockchip,rk3568-spdif
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -23,6 +23,7 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,tas2770
|
||||
- ti,tas5770l # Apple variant
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -24,6 +24,7 @@ properties:
|
||||
enum:
|
||||
- ti,tas2764
|
||||
- ti,tas2780
|
||||
- ti,sn012776 # Apple variant of TAS2764
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -38,6 +38,82 @@ properties:
|
||||
DCVDD-supply: true
|
||||
MICVDD-supply: true
|
||||
|
||||
wlf,in1l-as-dmicdat1:
|
||||
type: boolean
|
||||
description:
|
||||
Use IN1L/DMICDAT1 as DMICDAT1, enabling the DMIC input path.
|
||||
Can be used separately or together with wlf,in1r-as-dmicdat2.
|
||||
|
||||
wlf,in1r-as-dmicdat2:
|
||||
type: boolean
|
||||
description:
|
||||
Use IN1R/DMICDAT2 as DMICDAT2, enabling the DMIC input path.
|
||||
Can be used separately or together with wlf,in1l-as-dmicdat1.
|
||||
|
||||
wlf,gpio-cfg:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
description:
|
||||
Default register values for R121/122/123/124 (GPIO Control).
|
||||
If any entry has the value 0xFFFF, the related register won't be set.
|
||||
default: [0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF]
|
||||
|
||||
wlf,micbias-cfg:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
description:
|
||||
Default register values for R6/R7 (Mic Bias Control).
|
||||
default: [0, 0]
|
||||
|
||||
wlf,drc-cfg-names:
|
||||
$ref: /schemas/types.yaml#/definitions/string-array
|
||||
description:
|
||||
List of strings for the available DRC modes.
|
||||
If absent, DRC is disabled.
|
||||
|
||||
wlf,drc-cfg-regs:
|
||||
$ref: /schemas/types.yaml#/definitions/uint16-matrix
|
||||
description:
|
||||
Sets of default register values for R40/41/42/43 (DRC).
|
||||
Each set corresponds to a DRC mode, so the number of sets should equal
|
||||
the length of wlf,drc-cfg-names.
|
||||
If absent, DRC is disabled.
|
||||
items:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
|
||||
wlf,retune-mobile-cfg-names:
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
description:
|
||||
List of strings for the available retune modes.
|
||||
If absent, retune is disabled.
|
||||
|
||||
wlf,retune-mobile-cfg-hz:
|
||||
description:
|
||||
The list must be the same length as wlf,retune-mobile-cfg-names.
|
||||
If absent, retune is disabled.
|
||||
|
||||
wlf,retune-mobile-cfg-regs:
|
||||
$ref: /schemas/types.yaml#/definitions/uint16-matrix
|
||||
description:
|
||||
Sets of default register values for R134/.../157 (EQ).
|
||||
Each set corresponds to a retune mode, so the number of sets should equal
|
||||
the length of wlf,retune-mobile-cfg-names.
|
||||
If absent, retune is disabled.
|
||||
items:
|
||||
minItems: 24
|
||||
maxItems: 24
|
||||
|
||||
dependencies:
|
||||
wlf,drc-cfg-names: [ 'wlf,drc-cfg-regs' ]
|
||||
wlf,drc-cfg-regs: [ 'wlf,drc-cfg-names' ]
|
||||
|
||||
wlf,retune-mobile-cfg-names: [ 'wlf,retune-mobile-cfg-hz', 'wlf,retune-mobile-cfg-regs' ]
|
||||
wlf,retune-mobile-cfg-regs: [ 'wlf,retune-mobile-cfg-names', 'wlf,retune-mobile-cfg-hz' ]
|
||||
wlf,retune-mobile-cfg-hz: [ 'wlf,retune-mobile-cfg-names', 'wlf,retune-mobile-cfg-regs' ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -70,5 +146,58 @@ examples:
|
||||
DBVDD-supply = <®_1p8v>;
|
||||
DCVDD-supply = <®_1p8v>;
|
||||
MICVDD-supply = <®_1p8v>;
|
||||
|
||||
wlf,drc-cfg-names = "default", "peaklimiter", "tradition", "soft",
|
||||
"music";
|
||||
/*
|
||||
* Config registers per name, respectively:
|
||||
* KNEE_IP = 0, KNEE_OP = 0, HI_COMP = 1, LO_COMP = 1
|
||||
* KNEE_IP = -24, KNEE_OP = -6, HI_COMP = 1/4, LO_COMP = 1
|
||||
* KNEE_IP = -42, KNEE_OP = -3, HI_COMP = 0, LO_COMP = 1
|
||||
* KNEE_IP = -45, KNEE_OP = -9, HI_COMP = 1/8, LO_COMP = 1
|
||||
* KNEE_IP = -30, KNEE_OP = -10.5, HI_COMP = 1/4, LO_COMP = 1
|
||||
*/
|
||||
wlf,drc-cfg-regs = /bits/ 16 <0x01af 0x3248 0x0000 0x0000>,
|
||||
/bits/ 16 <0x04af 0x324b 0x0010 0x0408>,
|
||||
/bits/ 16 <0x04af 0x324b 0x0028 0x0704>,
|
||||
/bits/ 16 <0x04af 0x324b 0x0018 0x078c>,
|
||||
/bits/ 16 <0x04af 0x324b 0x0010 0x050e>;
|
||||
|
||||
/* GPIO1 = DMIC_CLK, don't touch others */
|
||||
wlf,gpio-cfg = <0x0018>, <0xffff>, <0xffff>, <0xffff>;
|
||||
|
||||
/* Use IN1R as DMICDAT2, leave IN1L as an analog input path */
|
||||
wlf,in1r-as-dmicdat2;
|
||||
|
||||
wlf,retune-mobile-cfg-names = "bassboost", "bassboost", "treble";
|
||||
wlf,retune-mobile-cfg-hz = <48000>, <44100>, <48000>;
|
||||
/*
|
||||
* Config registers per name, respectively:
|
||||
* EQ_ENA, 100 Hz, 300 Hz, 875 Hz, 2400 Hz, 6900 Hz
|
||||
* 1, +6 dB, +3 dB, 0 dB, 0 dB, 0 dB
|
||||
* 1, +6 dB, +3 dB, 0 dB, 0 dB, 0 dB
|
||||
* 1, -2 dB, -2 dB, 0 dB, 0 dB, +3 dB
|
||||
* Each one uses the defaults for ReTune Mobile registers 140-157
|
||||
*/
|
||||
wlf,retune-mobile-cfg-regs = /bits/ 16 <0x1 0x12 0xf 0xc 0xc 0xc
|
||||
0x0fca 0x0400 0x00d8 0x1eb5
|
||||
0xf145 0x0bd5 0x0075 0x1c58
|
||||
0xf3d3 0x0a54 0x0568 0x168e
|
||||
0xf829 0x07ad 0x1103 0x0564
|
||||
0x0559 0x4000>,
|
||||
|
||||
/bits/ 16 <0x1 0x12 0xf 0xc 0xc 0xc
|
||||
0x0fca 0x0400 0x00d8 0x1eb5
|
||||
0xf145 0x0bd5 0x0075 0x1c58
|
||||
0xf3d3 0x0a54 0x0568 0x168e
|
||||
0xf829 0x07ad 0x1103 0x0564
|
||||
0x0559 0x4000>,
|
||||
|
||||
/bits/ 16 <0x1 0xa 0xa 0xc 0xc 0xf
|
||||
0x0fca 0x0400 0x00d8 0x1eb5
|
||||
0xf145 0x0bd5 0x0075 0x1c58
|
||||
0xf3d3 0x0a54 0x0568 0x168e
|
||||
0xf829 0x07ad 0x1103 0x0564
|
||||
0x0559 0x4000>;
|
||||
};
|
||||
};
|
||||
|
@ -75,6 +75,10 @@ properties:
|
||||
enable DACLRC pin. If shared-lrclk is present, no need to enable DAC for
|
||||
captrue.
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -1,29 +0,0 @@
|
||||
Device-Tree bindings for Xilinx PL audio formatter
|
||||
|
||||
The IP core supports DMA, data formatting(AES<->PCM conversion)
|
||||
of audio samples.
|
||||
|
||||
Required properties:
|
||||
- compatible: "xlnx,audio-formatter-1.0"
|
||||
- interrupt-names: Names specified to list of interrupts in same
|
||||
order mentioned under "interrupts".
|
||||
List of supported interrupt names are:
|
||||
"irq_mm2s" : interrupt from MM2S block
|
||||
"irq_s2mm" : interrupt from S2MM block
|
||||
- interrupts-parent: Phandle for interrupt controller.
|
||||
- interrupts: List of Interrupt numbers.
|
||||
- reg: Base address and size of the IP core instance.
|
||||
- clock-names: List of input clocks.
|
||||
Required elements: "s_axi_lite_aclk", "aud_mclk"
|
||||
- clocks: Input clock specifier. Refer to common clock bindings.
|
||||
|
||||
Example:
|
||||
audio_ss_0_audio_formatter_0: audio_formatter@80010000 {
|
||||
compatible = "xlnx,audio-formatter-1.0";
|
||||
interrupt-names = "irq_mm2s", "irq_s2mm";
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 104 4>, <0 105 4>;
|
||||
reg = <0x0 0x80010000 0x0 0x1000>;
|
||||
clock-names = "s_axi_lite_aclk", "aud_mclk";
|
||||
clocks = <&clk 71>, <&clk_wiz_1 0>;
|
||||
};
|
@ -0,0 +1,72 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/xlnx,audio-formatter.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Xilinx PL audio formatter
|
||||
|
||||
description:
|
||||
The IP core supports DMA, data formatting(AES<->PCM conversion)
|
||||
of audio samples.
|
||||
|
||||
maintainers:
|
||||
- Vincenzo Frascino <vincenzo.frascino@arm.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- xlnx,audio-formatter-1.0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: irq_mm2s
|
||||
- const: irq_s2mm
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: interrupt from MM2S block
|
||||
- description: interrupt from S2MM block
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: s_axi_lite_aclk
|
||||
- const: aud_mclk
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: clock for the axi data stream
|
||||
- description: clock for the MEMS microphone data stream
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupt-names
|
||||
- interrupts
|
||||
- clock-names
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
audio_formatter@80010000 {
|
||||
compatible = "xlnx,audio-formatter-1.0";
|
||||
reg = <0x80010000 0x1000>;
|
||||
interrupt-names = "irq_mm2s", "irq_s2mm";
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 104 4>, <0 105 4>;
|
||||
clock-names = "s_axi_lite_aclk", "aud_mclk";
|
||||
clocks = <&clk 71>, <&clk_wiz_1 0>;
|
||||
};
|
||||
...
|
@ -1,28 +0,0 @@
|
||||
Device-Tree bindings for Xilinx I2S PL block
|
||||
|
||||
The IP supports I2S based playback/capture audio
|
||||
|
||||
Required property:
|
||||
- compatible: "xlnx,i2s-transmitter-1.0" for playback and
|
||||
"xlnx,i2s-receiver-1.0" for capture
|
||||
|
||||
Required property common to both I2S playback and capture:
|
||||
- reg: Base address and size of the IP core instance.
|
||||
- xlnx,dwidth: sample data width. Can be any of 16, 24.
|
||||
- xlnx,num-channels: Number of I2S streams. Can be any of 1, 2, 3, 4.
|
||||
supported channels = 2 * xlnx,num-channels
|
||||
|
||||
Example:
|
||||
|
||||
i2s_receiver@a0080000 {
|
||||
compatible = "xlnx,i2s-receiver-1.0";
|
||||
reg = <0x0 0xa0080000 0x0 0x10000>;
|
||||
xlnx,dwidth = <0x18>;
|
||||
xlnx,num-channels = <1>;
|
||||
};
|
||||
i2s_transmitter@a0090000 {
|
||||
compatible = "xlnx,i2s-transmitter-1.0";
|
||||
reg = <0x0 0xa0090000 0x0 0x10000>;
|
||||
xlnx,dwidth = <0x18>;
|
||||
xlnx,num-channels = <1>;
|
||||
};
|
65
Documentation/devicetree/bindings/sound/xlnx,i2s.yaml
Normal file
65
Documentation/devicetree/bindings/sound/xlnx,i2s.yaml
Normal file
@ -0,0 +1,65 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/xlnx,i2s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Xilinx I2S PL block
|
||||
|
||||
description:
|
||||
The IP supports I2S based playback/capture audio.
|
||||
|
||||
maintainers:
|
||||
- Vincenzo Frascino <vincenzo.frascino@arm.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- xlnx,i2s-receiver-1.0
|
||||
- xlnx,i2s-transmitter-1.0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
xlnx,dwidth:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 16
|
||||
- 24
|
||||
description: |
|
||||
Sample data width.
|
||||
|
||||
xlnx,num-channels:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 1
|
||||
maximum: 4
|
||||
description: |
|
||||
Number of I2S streams.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- xlnx,dwidth
|
||||
- xlnx,num-channels
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2s@a0080000 {
|
||||
compatible = "xlnx,i2s-receiver-1.0";
|
||||
reg = <0xa0080000 0x10000>;
|
||||
xlnx,dwidth = <0x18>;
|
||||
xlnx,num-channels = <1>;
|
||||
};
|
||||
i2s@a0090000 {
|
||||
compatible = "xlnx,i2s-transmitter-1.0";
|
||||
reg = <0xa0090000 0x10000>;
|
||||
xlnx,dwidth = <0x18>;
|
||||
xlnx,num-channels = <1>;
|
||||
};
|
||||
|
||||
...
|
@ -1,28 +0,0 @@
|
||||
Device-Tree bindings for Xilinx SPDIF IP
|
||||
|
||||
The IP supports playback and capture of SPDIF audio
|
||||
|
||||
Required properties:
|
||||
- compatible: "xlnx,spdif-2.0"
|
||||
- clock-names: List of input clocks.
|
||||
Required elements: "s_axi_aclk", "aud_clk_i"
|
||||
- clocks: Input clock specifier. Refer to common clock bindings.
|
||||
- reg: Base address and address length of the IP core instance.
|
||||
- interrupts-parent: Phandle for interrupt controller.
|
||||
- interrupts: List of Interrupt numbers.
|
||||
- xlnx,spdif-mode: 0 :- receiver mode
|
||||
1 :- transmitter mode
|
||||
- xlnx,aud_clk_i: input audio clock value.
|
||||
|
||||
Example:
|
||||
spdif_0: spdif@80010000 {
|
||||
clock-names = "aud_clk_i", "s_axi_aclk";
|
||||
clocks = <&misc_clk_0>, <&clk 71>;
|
||||
compatible = "xlnx,spdif-2.0";
|
||||
interrupt-names = "spdif_interrupt";
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 91 4>;
|
||||
reg = <0x0 0x80010000 0x0 0x10000>;
|
||||
xlnx,spdif-mode = <1>;
|
||||
xlnx,aud_clk_i = <49152913>;
|
||||
};
|
77
Documentation/devicetree/bindings/sound/xlnx,spdif.yaml
Normal file
77
Documentation/devicetree/bindings/sound/xlnx,spdif.yaml
Normal file
@ -0,0 +1,77 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/xlnx,spdif.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Xilinx SPDIF IP
|
||||
|
||||
description:
|
||||
The IP supports playback and capture of SPDIF audio.
|
||||
|
||||
maintainers:
|
||||
- Vincenzo Frascino <vincenzo.frascino@arm.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- xlnx,spdif-2.0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: SPDIF audio interrupt
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: aud_clk_i
|
||||
- const: s_axi_aclk
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: input audio clock
|
||||
- description: clock for the AXI data stream
|
||||
|
||||
xlnx,spdif-mode:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
description: |
|
||||
0 - receiver
|
||||
1 - transmitter
|
||||
|
||||
xlnx,aud_clk_i:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
Input audio clock frequency. It affects the sampling rate.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clock-names
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spdif@80010000 {
|
||||
compatible = "xlnx,spdif-2.0";
|
||||
reg = <0x80010000 0x10000>;
|
||||
clock-names = "aud_clk_i", "s_axi_aclk";
|
||||
clocks = <&misc_clk_0>, <&clk 71>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 91 4>;
|
||||
xlnx,spdif-mode = <1>;
|
||||
xlnx,aud_clk_i = <49152913>;
|
||||
};
|
||||
|
||||
...
|
@ -58,7 +58,7 @@ debug
|
||||
2 = verbose debug messages);
|
||||
This option appears only when ``CONFIG_SND_DEBUG=y``.
|
||||
This option can be dynamically changed via sysfs
|
||||
/sys/modules/snd/parameters/debug file.
|
||||
/sys/module/snd/parameters/debug file.
|
||||
|
||||
Module snd-pcm-oss
|
||||
------------------
|
||||
|
@ -25,15 +25,15 @@ operations.
|
||||
The ``power_save`` option is exported as writable. This means you can
|
||||
adjust the value via sysfs on the fly. For example, to turn on the
|
||||
automatic power-save mode with 10 seconds, write to
|
||||
``/sys/modules/snd_ac97_codec/parameters/power_save`` (usually as root):
|
||||
``/sys/module/snd_ac97_codec/parameters/power_save`` (usually as root):
|
||||
::
|
||||
|
||||
# echo 10 > /sys/modules/snd_ac97_codec/parameters/power_save
|
||||
# echo 10 > /sys/module/snd_ac97_codec/parameters/power_save
|
||||
|
||||
|
||||
Note that you might hear click noise/pop when changing the power
|
||||
state. Also, it often takes certain time to wake up from the
|
||||
power-down to the active state. These are often hardly to fix, so
|
||||
power-down to the active state. These are often hard to fix, so
|
||||
don't report extra bug reports unless you have a fix patch ;-)
|
||||
|
||||
For HD-audio interface, there is another module option,
|
||||
|
@ -68,7 +68,7 @@ file:
|
||||
.codec_dai_name = "codec-2-dai_name",
|
||||
.platform_name = "samsung-i2s.0",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
| SND_SOC_DAIFMT_CBP_CFP,
|
||||
.ignore_suspend = 1,
|
||||
.c2c_params = &dsp_codec_params,
|
||||
.num_c2c_params = 1,
|
||||
@ -80,7 +80,7 @@ file:
|
||||
.codec_name = "codec-3,
|
||||
.codec_dai_name = "codec-3-dai_name",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
| SND_SOC_DAIFMT_CBP_CFP,
|
||||
.ignore_suspend = 1,
|
||||
.c2c_params = &dsp_codec_params,
|
||||
.num_c2c_params = 1,
|
||||
|
@ -147,14 +147,16 @@ For the example above we have to define 4 FE DAI links and 6 BE DAI links. The
|
||||
FE DAI links are defined as follows :-
|
||||
::
|
||||
|
||||
SND_SOC_DAILINK_DEFS(pcm0,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("System Pin")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_PLATFORM("dsp-audio")));
|
||||
|
||||
static struct snd_soc_dai_link machine_dais[] = {
|
||||
{
|
||||
.name = "PCM0 System",
|
||||
.stream_name = "System Playback",
|
||||
.cpu_dai_name = "System Pin",
|
||||
.platform_name = "dsp-audio",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
SND_SOC_DAILINK_REG(pcm0),
|
||||
.dynamic = 1,
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
|
||||
},
|
||||
@ -174,15 +176,16 @@ dynamic and will change depending on runtime config.
|
||||
The BE DAIs are configured as follows :-
|
||||
::
|
||||
|
||||
SND_SOC_DAILINK_DEFS(headset,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("ssp-dai.0")),
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("rt5640.0-001c", "rt5640-aif1")));
|
||||
|
||||
static struct snd_soc_dai_link machine_dais[] = {
|
||||
.....< FE DAI links here >
|
||||
{
|
||||
.name = "Codec Headset",
|
||||
.cpu_dai_name = "ssp-dai.0",
|
||||
.platform_name = "snd-soc-dummy",
|
||||
SND_SOC_DAILINK_REG(headset),
|
||||
.no_pcm = 1,
|
||||
.codec_name = "rt5640.0-001c",
|
||||
.codec_dai_name = "rt5640-aif1",
|
||||
.ignore_suspend = 1,
|
||||
.ignore_pmdown_time = 1,
|
||||
.be_hw_params_fixup = hswult_ssp0_fixup,
|
||||
@ -362,7 +365,7 @@ The machine driver sets some additional parameters to the DAI link i.e.
|
||||
.codec_dai_name = "modem-aif1",
|
||||
.codec_name = "modem",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
| SND_SOC_DAIFMT_CBP_CFP,
|
||||
.c2c_params = &dai_params,
|
||||
.num_c2c_params = 1,
|
||||
}
|
||||
|
11
MAINTAINERS
11
MAINTAINERS
@ -15695,7 +15695,7 @@ M: Claudiu Beznea <claudiu.beznea@tuxon.dev>
|
||||
M: Andrei Simion <andrei.simion@microchip.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/misc/atmel-ssc.txt
|
||||
F: Documentation/devicetree/bindings/sound/atmel,at91-ssc.yaml
|
||||
F: drivers/misc/atmel-ssc.c
|
||||
F: include/linux/atmel-ssc.h
|
||||
|
||||
@ -19291,6 +19291,7 @@ F: Documentation/devicetree/bindings/soc/qcom/qcom,apr*
|
||||
F: Documentation/devicetree/bindings/sound/qcom,*
|
||||
F: drivers/soc/qcom/apr.c
|
||||
F: include/dt-bindings/sound/qcom,wcd9335.h
|
||||
F: include/dt-bindings/sound/qcom,wcd934x.h
|
||||
F: sound/soc/codecs/lpass-rx-macro.*
|
||||
F: sound/soc/codecs/lpass-tx-macro.*
|
||||
F: sound/soc/codecs/lpass-va-macro.c
|
||||
@ -26141,6 +26142,14 @@ S: Maintained
|
||||
F: drivers/pwm/pwm-xilinx.c
|
||||
F: include/clocksource/timer-xilinx.h
|
||||
|
||||
XILINX SOUND DRIVERS
|
||||
M: Vincenzo Frascino <vincenzo.frascino@arm.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/xlnx,i2s.yaml
|
||||
F: Documentation/devicetree/bindings/sound/xlnx,audio-formatter.yaml
|
||||
F: Documentation/devicetree/bindings/sound/xlnx,spdif.yaml
|
||||
F: sound/soc/xilinx/*
|
||||
|
||||
XILINX SD-FEC IP CORES
|
||||
M: Derek Kiernan <derek.kiernan@amd.com>
|
||||
M: Dragan Cvetic <dragan.cvetic@amd.com>
|
||||
|
@ -21,6 +21,37 @@ static const struct regcache_ops *cache_types[] = {
|
||||
®cache_flat_ops,
|
||||
};
|
||||
|
||||
static int regcache_defaults_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct reg_default *x = a;
|
||||
const struct reg_default *y = b;
|
||||
|
||||
if (x->reg > y->reg)
|
||||
return 1;
|
||||
else if (x->reg < y->reg)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void regcache_defaults_swap(void *a, void *b, int size)
|
||||
{
|
||||
struct reg_default *x = a;
|
||||
struct reg_default *y = b;
|
||||
struct reg_default tmp;
|
||||
|
||||
tmp = *x;
|
||||
*x = *y;
|
||||
*y = tmp;
|
||||
}
|
||||
|
||||
void regcache_sort_defaults(struct reg_default *defaults, unsigned int ndefaults)
|
||||
{
|
||||
sort(defaults, ndefaults, sizeof(*defaults),
|
||||
regcache_defaults_cmp, regcache_defaults_swap);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regcache_sort_defaults);
|
||||
|
||||
static int regcache_hw_init(struct regmap *map)
|
||||
{
|
||||
int i, j;
|
||||
|
@ -534,11 +534,6 @@ static int cs_dsp_bin_err_test_adsp2_16bit_init(struct kunit *test)
|
||||
return cs_dsp_bin_err_test_common_init(test, dsp, 1);
|
||||
}
|
||||
|
||||
static struct kunit_case cs_dsp_bin_err_test_cases_halo[] = {
|
||||
|
||||
{ } /* terminator */
|
||||
};
|
||||
|
||||
static void cs_dsp_bin_err_block_types_desc(const struct cs_dsp_bin_test_param *param,
|
||||
char *desc)
|
||||
{
|
||||
@ -560,7 +555,7 @@ KUNIT_ARRAY_PARAM(bin_test_block_types,
|
||||
bin_test_block_types_cases,
|
||||
cs_dsp_bin_err_block_types_desc);
|
||||
|
||||
static struct kunit_case cs_dsp_bin_err_test_cases_adsp2[] = {
|
||||
static struct kunit_case cs_dsp_bin_err_test_cases[] = {
|
||||
KUNIT_CASE(bin_load_with_unknown_blocks),
|
||||
KUNIT_CASE(bin_err_wrong_magic),
|
||||
KUNIT_CASE(bin_err_too_short_for_header),
|
||||
@ -578,21 +573,21 @@ static struct kunit_suite cs_dsp_bin_err_test_halo = {
|
||||
.name = "cs_dsp_bin_err_halo",
|
||||
.init = cs_dsp_bin_err_test_halo_init,
|
||||
.exit = cs_dsp_bin_err_test_exit,
|
||||
.test_cases = cs_dsp_bin_err_test_cases_halo,
|
||||
.test_cases = cs_dsp_bin_err_test_cases,
|
||||
};
|
||||
|
||||
static struct kunit_suite cs_dsp_bin_err_test_adsp2_32bit = {
|
||||
.name = "cs_dsp_bin_err_adsp2_32bit",
|
||||
.init = cs_dsp_bin_err_test_adsp2_32bit_init,
|
||||
.exit = cs_dsp_bin_err_test_exit,
|
||||
.test_cases = cs_dsp_bin_err_test_cases_adsp2,
|
||||
.test_cases = cs_dsp_bin_err_test_cases,
|
||||
};
|
||||
|
||||
static struct kunit_suite cs_dsp_bin_err_test_adsp2_16bit = {
|
||||
.name = "cs_dsp_bin_err_adsp2_16bit",
|
||||
.init = cs_dsp_bin_err_test_adsp2_16bit_init,
|
||||
.exit = cs_dsp_bin_err_test_exit,
|
||||
.test_cases = cs_dsp_bin_err_test_cases_adsp2,
|
||||
.test_cases = cs_dsp_bin_err_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suites(&cs_dsp_bin_err_test_halo,
|
||||
|
@ -73,6 +73,18 @@ static const struct cs_dsp_mock_coeff_def mock_coeff_template = {
|
||||
.length_bytes = 4,
|
||||
};
|
||||
|
||||
static char *cs_dsp_ctl_alloc_test_string(struct kunit *test, char c, size_t len)
|
||||
{
|
||||
char *str;
|
||||
|
||||
str = kunit_kmalloc(test, len + 1, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str);
|
||||
memset(str, c, len);
|
||||
str[len] = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/* Algorithm info block without controls should load */
|
||||
static void cs_dsp_ctl_parse_no_coeffs(struct kunit *test)
|
||||
{
|
||||
@ -160,12 +172,8 @@ static void cs_dsp_ctl_parse_max_v1_name(struct kunit *test)
|
||||
struct cs_dsp_mock_coeff_def def = mock_coeff_template;
|
||||
struct cs_dsp_coeff_ctl *ctl;
|
||||
struct firmware *wmfw;
|
||||
char *name;
|
||||
|
||||
name = kunit_kzalloc(test, 256, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, name);
|
||||
memset(name, 'A', 255);
|
||||
def.fullname = name;
|
||||
def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255);
|
||||
|
||||
cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
|
||||
cs_dsp_ctl_parse_test_algs[0].id,
|
||||
@ -252,14 +260,9 @@ static void cs_dsp_ctl_parse_max_short_name(struct kunit *test)
|
||||
struct cs_dsp_test_local *local = priv->local;
|
||||
struct cs_dsp_mock_coeff_def def = mock_coeff_template;
|
||||
struct cs_dsp_coeff_ctl *ctl;
|
||||
char *name;
|
||||
struct firmware *wmfw;
|
||||
|
||||
name = kunit_kmalloc(test, 255, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, name);
|
||||
memset(name, 'A', 255);
|
||||
|
||||
def.shortname = name;
|
||||
def.shortname = cs_dsp_ctl_alloc_test_string(test, 'A', 255);
|
||||
|
||||
cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
|
||||
cs_dsp_ctl_parse_test_algs[0].id,
|
||||
@ -273,7 +276,7 @@ static void cs_dsp_ctl_parse_max_short_name(struct kunit *test)
|
||||
ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
|
||||
KUNIT_ASSERT_NOT_NULL(test, ctl);
|
||||
KUNIT_EXPECT_EQ(test, ctl->subname_len, 255);
|
||||
KUNIT_EXPECT_MEMEQ(test, ctl->subname, name, ctl->subname_len);
|
||||
KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
|
||||
KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
|
||||
KUNIT_EXPECT_EQ(test, ctl->type, def.type);
|
||||
KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
|
||||
@ -323,12 +326,8 @@ static void cs_dsp_ctl_parse_with_max_fullname(struct kunit *test)
|
||||
struct cs_dsp_mock_coeff_def def = mock_coeff_template;
|
||||
struct cs_dsp_coeff_ctl *ctl;
|
||||
struct firmware *wmfw;
|
||||
char *fullname;
|
||||
|
||||
fullname = kunit_kmalloc(test, 255, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fullname);
|
||||
memset(fullname, 'A', 255);
|
||||
def.fullname = fullname;
|
||||
def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255);
|
||||
|
||||
cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
|
||||
cs_dsp_ctl_parse_test_algs[0].id,
|
||||
@ -392,12 +391,8 @@ static void cs_dsp_ctl_parse_with_max_description(struct kunit *test)
|
||||
struct cs_dsp_mock_coeff_def def = mock_coeff_template;
|
||||
struct cs_dsp_coeff_ctl *ctl;
|
||||
struct firmware *wmfw;
|
||||
char *description;
|
||||
|
||||
description = kunit_kmalloc(test, 65535, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, description);
|
||||
memset(description, 'A', 65535);
|
||||
def.description = description;
|
||||
def.description = cs_dsp_ctl_alloc_test_string(test, 'A', 65535);
|
||||
|
||||
cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
|
||||
cs_dsp_ctl_parse_test_algs[0].id,
|
||||
@ -429,17 +424,9 @@ static void cs_dsp_ctl_parse_with_max_fullname_and_description(struct kunit *tes
|
||||
struct cs_dsp_mock_coeff_def def = mock_coeff_template;
|
||||
struct cs_dsp_coeff_ctl *ctl;
|
||||
struct firmware *wmfw;
|
||||
char *fullname, *description;
|
||||
|
||||
fullname = kunit_kmalloc(test, 255, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fullname);
|
||||
memset(fullname, 'A', 255);
|
||||
def.fullname = fullname;
|
||||
|
||||
description = kunit_kmalloc(test, 65535, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, description);
|
||||
memset(description, 'A', 65535);
|
||||
def.description = description;
|
||||
def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255);
|
||||
def.description = cs_dsp_ctl_alloc_test_string(test, 'A', 65535);
|
||||
|
||||
cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
|
||||
cs_dsp_ctl_parse_test_algs[0].id,
|
||||
|
@ -147,6 +147,39 @@ static void *of_find_property_value_of_size(const struct device_node *np,
|
||||
return prop->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_property_read_u16_index - Find and read a u16 from a multi-value property.
|
||||
*
|
||||
* @np: device node from which the property value is to be read.
|
||||
* @propname: name of the property to be searched.
|
||||
* @index: index of the u16 in the list of values
|
||||
* @out_value: pointer to return value, modified only if no error.
|
||||
*
|
||||
* Search for a property in a device node and read nth 16-bit value from
|
||||
* it.
|
||||
*
|
||||
* Return: 0 on success, -EINVAL if the property does not exist,
|
||||
* -ENODATA if property does not have a value, and -EOVERFLOW if the
|
||||
* property data isn't large enough.
|
||||
*
|
||||
* The out_value is modified only if a valid u16 value can be decoded.
|
||||
*/
|
||||
int of_property_read_u16_index(const struct device_node *np,
|
||||
const char *propname,
|
||||
u32 index, u16 *out_value)
|
||||
{
|
||||
const u16 *val = of_find_property_value_of_size(np, propname,
|
||||
((index + 1) * sizeof(*out_value)),
|
||||
0, NULL);
|
||||
|
||||
if (IS_ERR(val))
|
||||
return PTR_ERR(val);
|
||||
|
||||
*out_value = be16_to_cpup(((__be16 *)val) + index);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_property_read_u16_index);
|
||||
|
||||
/**
|
||||
* of_property_read_u32_index - Find and read a u32 from a multi-value property.
|
||||
*
|
||||
|
@ -156,6 +156,7 @@ struct qcom_swrm_port_config {
|
||||
u8 word_length;
|
||||
u8 blk_group_count;
|
||||
u8 lane_control;
|
||||
u8 ch_mask;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1048,9 +1049,13 @@ static int qcom_swrm_port_enable(struct sdw_bus *bus,
|
||||
{
|
||||
u32 reg = SWRM_DP_PORT_CTRL_BANK(enable_ch->port_num, bank);
|
||||
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
|
||||
struct qcom_swrm_port_config *pcfg;
|
||||
u32 val;
|
||||
|
||||
pcfg = &ctrl->pconfig[enable_ch->port_num];
|
||||
ctrl->reg_read(ctrl, reg, &val);
|
||||
if (pcfg->ch_mask != SWR_INVALID_PARAM && pcfg->ch_mask != 0)
|
||||
enable_ch->ch_mask = pcfg->ch_mask;
|
||||
|
||||
if (enable_ch->enable)
|
||||
val |= (enable_ch->ch_mask << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT);
|
||||
@ -1270,6 +1275,26 @@ static void *qcom_swrm_get_sdw_stream(struct snd_soc_dai *dai, int direction)
|
||||
return ctrl->sruntime[dai->id];
|
||||
}
|
||||
|
||||
static int qcom_swrm_set_channel_map(struct snd_soc_dai *dai,
|
||||
unsigned int tx_num, const unsigned int *tx_slot,
|
||||
unsigned int rx_num, const unsigned int *rx_slot)
|
||||
{
|
||||
struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev);
|
||||
int i;
|
||||
|
||||
if (tx_slot) {
|
||||
for (i = 0; i < tx_num; i++)
|
||||
ctrl->pconfig[i].ch_mask = tx_slot[i];
|
||||
}
|
||||
|
||||
if (rx_slot) {
|
||||
for (i = 0; i < rx_num; i++)
|
||||
ctrl->pconfig[i].ch_mask = rx_slot[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_swrm_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
@ -1306,6 +1331,7 @@ static const struct snd_soc_dai_ops qcom_swrm_pdm_dai_ops = {
|
||||
.shutdown = qcom_swrm_shutdown,
|
||||
.set_stream = qcom_swrm_set_sdw_stream,
|
||||
.get_stream = qcom_swrm_get_sdw_stream,
|
||||
.set_channel_map = qcom_swrm_set_channel_map,
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver qcom_swrm_dai_component = {
|
||||
|
16
include/dt-bindings/sound/qcom,wcd934x.h
Normal file
16
include/dt-bindings/sound/qcom,wcd934x.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||
|
||||
#ifndef __DT_SOUND_QCOM_WCD934x_H
|
||||
#define __DT_SOUND_QCOM_WCD934x_H
|
||||
|
||||
#define AIF1_PB 0
|
||||
#define AIF1_CAP 1
|
||||
#define AIF2_PB 2
|
||||
#define AIF2_CAP 3
|
||||
#define AIF3_PB 4
|
||||
#define AIF3_CAP 5
|
||||
#define AIF4_PB 6
|
||||
#define AIF4_VIFEED 7
|
||||
#define AIF4_MAD_TX 8
|
||||
|
||||
#endif
|
@ -314,6 +314,9 @@ extern struct property *of_find_property(const struct device_node *np,
|
||||
extern bool of_property_read_bool(const struct device_node *np, const char *propname);
|
||||
extern int of_property_count_elems_of_size(const struct device_node *np,
|
||||
const char *propname, int elem_size);
|
||||
extern int of_property_read_u16_index(const struct device_node *np,
|
||||
const char *propname,
|
||||
u32 index, u16 *out_value);
|
||||
extern int of_property_read_u32_index(const struct device_node *np,
|
||||
const char *propname,
|
||||
u32 index, u32 *out_value);
|
||||
@ -627,6 +630,12 @@ static inline int of_property_count_elems_of_size(const struct device_node *np,
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int of_property_read_u16_index(const struct device_node *np,
|
||||
const char *propname, u32 index, u16 *out_value)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int of_property_read_u32_index(const struct device_node *np,
|
||||
const char *propname, u32 index, u32 *out_value)
|
||||
{
|
||||
|
@ -1352,6 +1352,7 @@ bool regmap_can_raw_write(struct regmap *map);
|
||||
size_t regmap_get_raw_read_max(struct regmap *map);
|
||||
size_t regmap_get_raw_write_max(struct regmap *map);
|
||||
|
||||
void regcache_sort_defaults(struct reg_default *defaults, unsigned int ndefaults);
|
||||
int regcache_sync(struct regmap *map);
|
||||
int regcache_sync_region(struct regmap *map, unsigned int min,
|
||||
unsigned int max);
|
||||
@ -2043,6 +2044,12 @@ static inline bool regmap_might_sleep(struct regmap *map)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void regcache_sort_defaults(struct reg_default *defaults,
|
||||
unsigned int ndefaults)
|
||||
{
|
||||
WARN_ONCE(1, "regmap API is disabled");
|
||||
}
|
||||
|
||||
static inline int regcache_sync(struct regmap *map)
|
||||
{
|
||||
WARN_ONCE(1, "regmap API is disabled");
|
||||
|
@ -62,6 +62,12 @@ struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid);
|
||||
|
||||
int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable);
|
||||
|
||||
/* microphone privacy specific function supported by ACE3+ architecture */
|
||||
void hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid,
|
||||
unsigned long mask);
|
||||
bool hdac_bus_eml_is_mic_privacy_changed(struct hdac_bus *bus, bool alt, int elid);
|
||||
bool hdac_bus_eml_get_mic_privacy_state(struct hdac_bus *bus, bool alt, int elid);
|
||||
|
||||
#else
|
||||
|
||||
static inline int
|
||||
@ -185,4 +191,23 @@ hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enabl
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid,
|
||||
unsigned long mask)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hdac_bus_eml_is_mic_privacy_changed(struct hdac_bus *bus, bool alt, int elid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hdac_bus_eml_get_mic_privacy_state(struct hdac_bus *bus, bool alt, int elid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SND_SOC_SOF_HDA_MLINK */
|
||||
|
@ -195,6 +195,7 @@ struct hda_codec {
|
||||
/* beep device */
|
||||
struct hda_beep *beep;
|
||||
unsigned int beep_mode;
|
||||
bool beep_just_power_on;
|
||||
|
||||
/* widget capabilities cache */
|
||||
u32 *wcaps;
|
||||
|
@ -2,6 +2,97 @@
|
||||
#ifndef __SOUND_PCM_DRM_ELD_H
|
||||
#define __SOUND_PCM_DRM_ELD_H
|
||||
|
||||
enum eld_versions {
|
||||
ELD_VER_CEA_861D = 2,
|
||||
ELD_VER_PARTIAL = 31,
|
||||
};
|
||||
|
||||
enum cea_audio_coding_types {
|
||||
AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0,
|
||||
AUDIO_CODING_TYPE_LPCM = 1,
|
||||
AUDIO_CODING_TYPE_AC3 = 2,
|
||||
AUDIO_CODING_TYPE_MPEG1 = 3,
|
||||
AUDIO_CODING_TYPE_MP3 = 4,
|
||||
AUDIO_CODING_TYPE_MPEG2 = 5,
|
||||
AUDIO_CODING_TYPE_AACLC = 6,
|
||||
AUDIO_CODING_TYPE_DTS = 7,
|
||||
AUDIO_CODING_TYPE_ATRAC = 8,
|
||||
AUDIO_CODING_TYPE_SACD = 9,
|
||||
AUDIO_CODING_TYPE_EAC3 = 10,
|
||||
AUDIO_CODING_TYPE_DTS_HD = 11,
|
||||
AUDIO_CODING_TYPE_MLP = 12,
|
||||
AUDIO_CODING_TYPE_DST = 13,
|
||||
AUDIO_CODING_TYPE_WMAPRO = 14,
|
||||
AUDIO_CODING_TYPE_REF_CXT = 15,
|
||||
/* also include valid xtypes below */
|
||||
AUDIO_CODING_TYPE_HE_AAC = 15,
|
||||
AUDIO_CODING_TYPE_HE_AAC2 = 16,
|
||||
AUDIO_CODING_TYPE_MPEG_SURROUND = 17,
|
||||
};
|
||||
|
||||
enum cea_audio_coding_xtypes {
|
||||
AUDIO_CODING_XTYPE_HE_REF_CT = 0,
|
||||
AUDIO_CODING_XTYPE_HE_AAC = 1,
|
||||
AUDIO_CODING_XTYPE_HE_AAC2 = 2,
|
||||
AUDIO_CODING_XTYPE_MPEG_SURROUND = 3,
|
||||
AUDIO_CODING_XTYPE_FIRST_RESERVED = 4,
|
||||
};
|
||||
|
||||
/*
|
||||
* CEA Short Audio Descriptor data
|
||||
*/
|
||||
struct snd_cea_sad {
|
||||
int channels;
|
||||
int format; /* (format == 0) indicates invalid SAD */
|
||||
int rates;
|
||||
int sample_bits; /* for LPCM */
|
||||
int max_bitrate; /* for AC3...ATRAC */
|
||||
int profile; /* for WMAPRO */
|
||||
};
|
||||
|
||||
#define ELD_FIXED_BYTES 20
|
||||
#define ELD_MAX_SIZE 256
|
||||
#define ELD_MAX_MNL 16
|
||||
#define ELD_MAX_SAD 16
|
||||
|
||||
#define ELD_PCM_BITS_8 BIT(0)
|
||||
#define ELD_PCM_BITS_16 BIT(1)
|
||||
#define ELD_PCM_BITS_20 BIT(2)
|
||||
#define ELD_PCM_BITS_24 BIT(3)
|
||||
#define ELD_PCM_BITS_32 BIT(4)
|
||||
|
||||
/*
|
||||
* ELD: EDID Like Data
|
||||
*/
|
||||
struct snd_parsed_hdmi_eld {
|
||||
/*
|
||||
* all fields will be cleared before updating ELD
|
||||
*/
|
||||
int baseline_len;
|
||||
int eld_ver;
|
||||
int cea_edid_ver;
|
||||
char monitor_name[ELD_MAX_MNL + 1];
|
||||
int manufacture_id;
|
||||
int product_id;
|
||||
u64 port_id;
|
||||
int support_hdcp;
|
||||
int support_ai;
|
||||
int conn_type;
|
||||
int aud_synch_delay;
|
||||
int spk_alloc;
|
||||
int sad_count;
|
||||
struct snd_cea_sad sad[ELD_MAX_SAD];
|
||||
};
|
||||
|
||||
int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld);
|
||||
|
||||
int snd_parse_eld(struct device *dev, struct snd_parsed_hdmi_eld *e,
|
||||
const unsigned char *buf, int size);
|
||||
void snd_show_eld(struct device *dev, struct snd_parsed_hdmi_eld *e);
|
||||
|
||||
#ifdef CONFIG_SND_PROC_FS
|
||||
void snd_print_eld_info(struct snd_parsed_hdmi_eld *eld,
|
||||
struct snd_info_buffer *buffer);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -17,29 +17,31 @@ struct sdw_slave;
|
||||
#define SDCA_MAX_FUNCTION_COUNT 8
|
||||
|
||||
/**
|
||||
* sdca_device_desc - short descriptor for an SDCA Function
|
||||
* @adr: ACPI address (used for SDCA register access)
|
||||
* @type: Function topology type
|
||||
* @name: human-readable string
|
||||
* struct sdca_function_desc - short descriptor for an SDCA Function
|
||||
* @node: firmware node for the Function.
|
||||
* @name: Human-readable string.
|
||||
* @type: Function topology type.
|
||||
* @adr: ACPI address (used for SDCA register access).
|
||||
*/
|
||||
struct sdca_function_desc {
|
||||
struct fwnode_handle *node;
|
||||
const char *name;
|
||||
u32 type;
|
||||
u8 adr;
|
||||
};
|
||||
|
||||
/**
|
||||
* sdca_device_data - structure containing all SDCA related information
|
||||
* @sdca_interface_revision: value read from _DSD property, mainly to check
|
||||
* for changes between silicon versions
|
||||
* @num_functions: total number of supported SDCA functions. Invalid/unsupported
|
||||
* struct sdca_device_data - structure containing all SDCA related information
|
||||
* @interface_revision: Value read from _DSD property, mainly to check
|
||||
* for changes between silicon versions.
|
||||
* @num_functions: Total number of supported SDCA functions. Invalid/unsupported
|
||||
* functions will be skipped.
|
||||
* @sdca_func: array of function descriptors
|
||||
* @function: Array of function descriptors.
|
||||
*/
|
||||
struct sdca_device_data {
|
||||
u32 interface_revision;
|
||||
int num_functions;
|
||||
struct sdca_function_desc sdca_func[SDCA_MAX_FUNCTION_COUNT];
|
||||
struct sdca_function_desc function[SDCA_MAX_FUNCTION_COUNT];
|
||||
};
|
||||
|
||||
enum sdca_quirk {
|
||||
|
File diff suppressed because it is too large
Load Diff
31
include/sound/sdca_regmap.h
Normal file
31
include/sound/sdca_regmap.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* The MIPI SDCA specification is available for public downloads at
|
||||
* https://www.mipi.org/mipi-sdca-v1-0-download
|
||||
*
|
||||
* Copyright (C) 2025 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __SDCA_REGMAP_H__
|
||||
#define __SDCA_REGMAP_H__
|
||||
|
||||
struct device;
|
||||
struct sdca_function_data;
|
||||
struct regmap;
|
||||
struct reg_default;
|
||||
|
||||
bool sdca_regmap_readable(struct sdca_function_data *function, unsigned int reg);
|
||||
bool sdca_regmap_writeable(struct sdca_function_data *function, unsigned int reg);
|
||||
bool sdca_regmap_volatile(struct sdca_function_data *function, unsigned int reg);
|
||||
bool sdca_regmap_deferrable(struct sdca_function_data *function, unsigned int reg);
|
||||
int sdca_regmap_mbq_size(struct sdca_function_data *function, unsigned int reg);
|
||||
|
||||
int sdca_regmap_count_constants(struct device *dev, struct sdca_function_data *function);
|
||||
int sdca_regmap_populate_constants(struct device *dev, struct sdca_function_data *function,
|
||||
struct reg_default *consts);
|
||||
|
||||
int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap,
|
||||
struct sdca_function_data *function);
|
||||
|
||||
#endif // __SDCA_REGMAP_H__
|
@ -142,14 +142,14 @@ int simple_util_parse_daifmt(struct device *dev,
|
||||
struct device_node *codec,
|
||||
char *prefix,
|
||||
unsigned int *retfmt);
|
||||
int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np,
|
||||
int simple_util_parse_tdm_width_map(struct simple_util_priv *priv, struct device_node *np,
|
||||
struct simple_util_dai *dai);
|
||||
|
||||
__printf(3, 4)
|
||||
int simple_util_set_dailink_name(struct device *dev,
|
||||
int simple_util_set_dailink_name(struct simple_util_priv *priv,
|
||||
struct snd_soc_dai_link *dai_link,
|
||||
const char *fmt, ...);
|
||||
int simple_util_parse_card_name(struct snd_soc_card *card,
|
||||
int simple_util_parse_card_name(struct simple_util_priv *priv,
|
||||
char *prefix);
|
||||
|
||||
int simple_util_parse_clk(struct device *dev,
|
||||
@ -201,7 +201,7 @@ void simple_util_remove(struct platform_device *pdev);
|
||||
|
||||
int graph_util_card_probe(struct snd_soc_card *card);
|
||||
int graph_util_is_ports0(struct device_node *port);
|
||||
int graph_util_parse_dai(struct device *dev, struct device_node *ep,
|
||||
int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep,
|
||||
struct snd_soc_dai_link_component *dlc, int *is_single_link);
|
||||
|
||||
void graph_util_parse_link_direction(struct device_node *np,
|
||||
|
@ -118,12 +118,6 @@ struct snd_compr_stream;
|
||||
#define SND_SOC_DAIFMT_CBP_CFC (3 << 12) /* codec clk provider & frame consumer */
|
||||
#define SND_SOC_DAIFMT_CBC_CFC (4 << 12) /* codec clk consumer & frame consumer */
|
||||
|
||||
/* previous definitions kept for backwards-compatibility, do not use in new contributions */
|
||||
#define SND_SOC_DAIFMT_CBM_CFM SND_SOC_DAIFMT_CBP_CFP
|
||||
#define SND_SOC_DAIFMT_CBS_CFM SND_SOC_DAIFMT_CBC_CFP
|
||||
#define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC
|
||||
#define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC
|
||||
|
||||
/* when passed to set_fmt directly indicate if the device is provider or consumer */
|
||||
#define SND_SOC_DAIFMT_BP_FP SND_SOC_DAIFMT_CBP_CFP
|
||||
#define SND_SOC_DAIFMT_BC_FP SND_SOC_DAIFMT_CBC_CFP
|
||||
@ -199,7 +193,7 @@ int snd_soc_dai_prepare(struct snd_soc_dai *dai,
|
||||
/* Digital Audio Interface mute */
|
||||
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
|
||||
int direction);
|
||||
|
||||
int snd_soc_dai_mute_is_ctrled_at_trigger(struct snd_soc_dai *dai);
|
||||
|
||||
int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai,
|
||||
unsigned int *tx_num, unsigned int *tx_slot,
|
||||
|
@ -326,55 +326,44 @@ struct soc_enum;
|
||||
|
||||
/* dapm kcontrol types */
|
||||
#define SOC_DAPM_DOUBLE(xname, reg, lshift, rshift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_VALUE(reg, lshift, rshift, max, invert, 0) }
|
||||
SOC_DOUBLE_EXT(xname, reg, lshift, rshift, max, invert, \
|
||||
snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw)
|
||||
#define SOC_DAPM_DOUBLE_R(xname, lreg, rreg, shift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_R_VALUE(lreg, rreg, shift, max, invert) }
|
||||
SOC_DOUBLE_R_EXT(xname, lreg, rreg, shift, max, invert, \
|
||||
snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw)
|
||||
#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||
SOC_SINGLE_EXT(xname, reg, shift, max, invert, \
|
||||
snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw)
|
||||
#define SOC_DAPM_SINGLE_VIRT(xname, max) \
|
||||
SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0)
|
||||
#define SOC_DAPM_DOUBLE_R_TLV(xname, lreg, rreg, shift, max, invert, tlv_array) \
|
||||
SOC_DOUBLE_R_EXT_TLV(xname, lreg, rreg, shift, max, invert, \
|
||||
snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw, \
|
||||
tlv_array)
|
||||
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||
SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \
|
||||
snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw, \
|
||||
tlv_array)
|
||||
#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \
|
||||
SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array)
|
||||
#define SOC_DAPM_ENUM(xname, xenum) \
|
||||
SOC_ENUM_EXT(xname, xenum, snd_soc_dapm_get_enum_double, \
|
||||
snd_soc_dapm_put_enum_double)
|
||||
#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \
|
||||
SOC_ENUM_EXT(xname, xenum, xget, xput)
|
||||
|
||||
#define SOC_DAPM_SINGLE_AUTODISABLE(xname, reg, shift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
|
||||
#define SOC_DAPM_SINGLE_VIRT(xname, max) \
|
||||
SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0)
|
||||
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 1) }
|
||||
#define SOC_DAPM_SINGLE_TLV_AUTODISABLE(xname, reg, shift, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
|
||||
#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \
|
||||
SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array)
|
||||
#define SOC_DAPM_ENUM(xname, xenum) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_enum_double, \
|
||||
.get = snd_soc_dapm_get_enum_double, \
|
||||
.put = snd_soc_dapm_put_enum_double, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_enum_double, \
|
||||
.get = xget, \
|
||||
.put = xput, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 1) }
|
||||
#define SOC_DAPM_PIN_SWITCH(xname) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \
|
||||
.info = snd_soc_dapm_info_pin_switch, \
|
||||
@ -514,8 +503,6 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char
|
||||
int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin);
|
||||
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, const char *pin);
|
||||
unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol);
|
||||
|
||||
/* Mostly internal - should not normally be used */
|
||||
void dapm_mark_endpoints_dirty(struct snd_soc_card *card);
|
||||
|
||||
/* dapm path query */
|
||||
|
@ -132,8 +132,8 @@ static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
|
||||
int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
|
||||
int stream, struct snd_soc_dapm_widget_list **list_);
|
||||
void dpcm_path_put(struct snd_soc_dapm_widget_list **list);
|
||||
int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
|
||||
int stream, struct snd_soc_dapm_widget_list **list, int new);
|
||||
int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
|
||||
struct snd_soc_dapm_widget_list **list_);
|
||||
int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream,
|
||||
int do_hw_free, struct snd_soc_dpcm *last);
|
||||
@ -143,8 +143,8 @@ void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream);
|
||||
int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd);
|
||||
int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
|
||||
int event);
|
||||
void dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event);
|
||||
|
||||
bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, enum snd_soc_dapm_direction dir);
|
||||
int widget_in_list(struct snd_soc_dapm_widget_list *list,
|
||||
struct snd_soc_dapm_widget *widget);
|
||||
|
@ -39,47 +39,35 @@ struct platform_device;
|
||||
/*
|
||||
* Convenience kcontrol builders
|
||||
*/
|
||||
#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xreg, .shift = shift_left, \
|
||||
.rshift = shift_right, .max = xmax, \
|
||||
.invert = xinvert, .autodisable = xautodisable})
|
||||
#define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, xinvert, xautodisable) \
|
||||
#define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, \
|
||||
xinvert, xautodisable) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xreg, .shift = shift_left, \
|
||||
.rshift = shift_right, .min = xmin, .max = xmax, \
|
||||
.sign_bit = xsign_bit, .invert = xinvert, .autodisable = xautodisable})
|
||||
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \
|
||||
SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable)
|
||||
#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .max = xmax, .invert = xinvert})
|
||||
#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
|
||||
.max = xmax, .invert = xinvert})
|
||||
#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmin, xmax, xinvert, xautodisable) \
|
||||
SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, 0, xinvert, \
|
||||
xautodisable)
|
||||
#define SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, xautodisable) \
|
||||
SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmin, xmax, xinvert, xautodisable)
|
||||
#define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
|
||||
.max = xmax, .min = xmin, .sign_bit = xsign_bit, \
|
||||
.invert = xinvert})
|
||||
#define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
|
||||
.min = xmin, .max = xmax, .invert = xinvert})
|
||||
#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \
|
||||
SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, 0, xinvert)
|
||||
|
||||
#define SOC_SINGLE(xname, reg, shift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 0) }
|
||||
#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
|
||||
.put = snd_soc_put_volsw_range, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xreg, .shift = xshift, \
|
||||
.rshift = xshift, .min = xmin, .max = xmax, \
|
||||
.invert = xinvert} }
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) }
|
||||
#define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
@ -87,7 +75,7 @@ struct platform_device;
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 0) }
|
||||
#define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
||||
@ -96,27 +84,21 @@ struct platform_device;
|
||||
.info = snd_soc_info_volsw_sx, \
|
||||
.get = snd_soc_get_volsw_sx,\
|
||||
.put = snd_soc_put_volsw_sx, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xreg, \
|
||||
.shift = xshift, .rshift = xshift, \
|
||||
.max = xmax, .min = xmin} }
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, 0, 0) }
|
||||
#define SOC_SINGLE_RANGE_TLV(xname, xreg, xshift, xmin, xmax, xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_range, \
|
||||
.get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xreg, .shift = xshift, \
|
||||
.rshift = xshift, .min = xmin, .max = xmax, \
|
||||
.invert = xinvert} }
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) }
|
||||
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
|
||||
max, invert, 0) }
|
||||
0, max, invert, 0) }
|
||||
#define SOC_DOUBLE_STS(xname, reg, shift_left, shift_right, max, invert) \
|
||||
{ \
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
@ -124,19 +106,19 @@ struct platform_device;
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READ | \
|
||||
SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
|
||||
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
|
||||
max, invert, 0) }
|
||||
0, max, invert, 0) }
|
||||
#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
|
||||
xmax, xinvert) }
|
||||
0, xmax, xinvert) }
|
||||
#define SOC_DOUBLE_R_RANGE(xname, reg_left, reg_right, xshift, xmin, \
|
||||
xmax, xinvert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.info = snd_soc_info_volsw_range, \
|
||||
.get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \
|
||||
.private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \
|
||||
xshift, xmin, xmax, xinvert) }
|
||||
#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
@ -146,7 +128,7 @@ struct platform_device;
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
|
||||
max, invert, 0) }
|
||||
0, max, invert, 0) }
|
||||
#define SOC_DOUBLE_SX_TLV(xname, xreg, shift_left, shift_right, xmin, xmax, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
||||
@ -155,10 +137,8 @@ struct platform_device;
|
||||
.info = snd_soc_info_volsw_sx, \
|
||||
.get = snd_soc_get_volsw_sx, \
|
||||
.put = snd_soc_put_volsw_sx, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xreg, \
|
||||
.shift = shift_left, .rshift = shift_right, \
|
||||
.max = xmax, .min = xmin} }
|
||||
.private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
|
||||
xmin, xmax, 0, 0) }
|
||||
#define SOC_DOUBLE_RANGE_TLV(xname, xreg, xshift_left, xshift_right, xmin, xmax, \
|
||||
xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
@ -167,10 +147,8 @@ struct platform_device;
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xreg, \
|
||||
.shift = xshift_left, .rshift = xshift_right, \
|
||||
.min = xmin, .max = xmax, .invert = xinvert} }
|
||||
.private_value = SOC_DOUBLE_VALUE(xreg, xshift_left, xshift_right, \
|
||||
xmin, xmax, xinvert, 0) }
|
||||
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
@ -179,16 +157,16 @@ struct platform_device;
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
|
||||
xmax, xinvert) }
|
||||
0, xmax, xinvert) }
|
||||
#define SOC_DOUBLE_R_RANGE_TLV(xname, reg_left, reg_right, xshift, xmin, \
|
||||
xmax, xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_range, \
|
||||
.get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \
|
||||
.private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \
|
||||
xshift, xmin, xmax, xinvert) }
|
||||
#define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
@ -198,10 +176,7 @@ struct platform_device;
|
||||
.info = snd_soc_info_volsw_sx, \
|
||||
.get = snd_soc_get_volsw_sx, \
|
||||
.put = snd_soc_put_volsw_sx, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xrreg, \
|
||||
.shift = xshift, .rshift = xshift, \
|
||||
.max = xmax, .min = xmin} }
|
||||
.private_value = SOC_DOUBLE_R_VALUE(xreg, xrreg, xshift, xmin, xmax, 0) }
|
||||
#define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
@ -261,21 +236,21 @@ struct platform_device;
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) }
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, 0, xmax, xinvert, 0) }
|
||||
#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\
|
||||
xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = \
|
||||
SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) }
|
||||
SOC_DOUBLE_VALUE(reg, shift_left, shift_right, 0, max, invert, 0) }
|
||||
#define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\
|
||||
xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
|
||||
xmax, xinvert) }
|
||||
0, xmax, xinvert) }
|
||||
#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
|
||||
xhandler_get, xhandler_put, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
@ -284,19 +259,16 @@ struct platform_device;
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) }
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, 0, xmax, xinvert, 0) }
|
||||
#define SOC_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \
|
||||
xhandler_get, xhandler_put, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_range, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xreg, .shift = xshift, \
|
||||
.rshift = xshift, .min = xmin, .max = xmax, \
|
||||
.invert = xinvert} }
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) }
|
||||
#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\
|
||||
xhandler_get, xhandler_put, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
@ -306,7 +278,7 @@ struct platform_device;
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
|
||||
xmax, xinvert, 0) }
|
||||
0, xmax, xinvert, 0) }
|
||||
#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
|
||||
xhandler_get, xhandler_put, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
@ -316,7 +288,7 @@ struct platform_device;
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
|
||||
xmax, xinvert) }
|
||||
0, xmax, xinvert) }
|
||||
#define SOC_DOUBLE_R_S_EXT_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, \
|
||||
xsign_bit, xinvert, xhandler_get, xhandler_put, \
|
||||
tlv_array) \
|
||||
@ -522,16 +494,6 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
|
||||
int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
|
||||
unsigned int dai_fmt);
|
||||
|
||||
#ifdef CONFIG_DMI
|
||||
int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour);
|
||||
#else
|
||||
static inline int snd_soc_set_dmi_name(struct snd_soc_card *card,
|
||||
const char *flavour)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Utility functions to get clock rates from various things */
|
||||
int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
|
||||
int snd_soc_params_to_frame_size(const struct snd_pcm_hw_params *params);
|
||||
@ -539,6 +501,7 @@ int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots);
|
||||
int snd_soc_params_to_bclk(const struct snd_pcm_hw_params *parms);
|
||||
int snd_soc_tdm_params_to_bclk(const struct snd_pcm_hw_params *params,
|
||||
int tdm_width, int tdm_slots, int slot_multiple);
|
||||
int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...);
|
||||
|
||||
/* set runtime hw params */
|
||||
static inline int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
|
||||
@ -606,12 +569,6 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_limit_volume(struct snd_soc_card *card,
|
||||
const char *name, int max);
|
||||
int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
|
||||
@ -1115,7 +1072,6 @@ struct snd_soc_card {
|
||||
/* Generic DAPM context for the card */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
struct snd_soc_dapm_stats dapm_stats;
|
||||
struct snd_soc_dapm_update *update;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_card_root;
|
||||
@ -1267,6 +1223,7 @@ struct soc_mixer_control {
|
||||
int platform_max;
|
||||
int reg, rreg;
|
||||
unsigned int shift, rshift;
|
||||
u32 num_channels;
|
||||
unsigned int sign_bit;
|
||||
unsigned int invert:1;
|
||||
unsigned int autodisable:1;
|
||||
|
@ -396,6 +396,7 @@ enum sof_ipc4_base_fw_params {
|
||||
SOF_IPC4_FW_PARAM_MODULES_INFO_GET,
|
||||
SOF_IPC4_FW_PARAM_LIBRARIES_INFO_GET = 16,
|
||||
SOF_IPC4_FW_PARAM_SYSTEM_TIME = 20,
|
||||
SOF_IPC4_FW_PARAM_MIC_PRIVACY_STATE_CHANGE = 35,
|
||||
};
|
||||
|
||||
enum sof_ipc4_fw_config_params {
|
||||
@ -446,6 +447,18 @@ struct sof_ipc4_dx_state_info {
|
||||
uint32_t dx_mask;
|
||||
} __packed __aligned(4);
|
||||
|
||||
enum sof_ipc4_hw_config_params {
|
||||
SOF_IPC4_HW_CFG_INTEL_MIC_PRIVACY_CAPS = 11,
|
||||
};
|
||||
|
||||
#define SOF_IPC_INTEL_MIC_PRIVACY_VERSION_PTL 1
|
||||
|
||||
struct sof_ipc4_intel_mic_privacy_cap {
|
||||
uint32_t version;
|
||||
uint32_t capabilities_length;
|
||||
uint32_t capabilities[];
|
||||
} __packed;
|
||||
|
||||
/* Reply messages */
|
||||
|
||||
/*
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// ALSA SoC Texas Instruments TAS2781 Audio Smart Amplifier
|
||||
//
|
||||
// Copyright (C) 2022 - 2024 Texas Instruments Incorporated
|
||||
// Copyright (C) 2022 - 2025 Texas Instruments Incorporated
|
||||
// https://www.ti.com
|
||||
//
|
||||
// The TAS2781 driver implements a flexible and configurable
|
||||
@ -30,8 +30,10 @@
|
||||
#define PRE_DEVICE_C 0x12
|
||||
#define PRE_DEVICE_D 0x16
|
||||
|
||||
#define PPC3_VERSION 0x4100
|
||||
#define PPC3_VERSION_TAS2781 0x14600
|
||||
#define PPC3_VERSION_BASE 0x4100
|
||||
#define PPC3_VERSION_TAS2781_BASIC_MIN 0x14600
|
||||
#define PPC3_VERSION_TAS2781_ALPHA_MIN 0x4a00
|
||||
#define PPC3_VERSION_TAS2781_BETA_MIN 0x19400
|
||||
#define TASDEVICE_DEVICE_SUM 8
|
||||
#define TASDEVICE_CONFIG_SUM 64
|
||||
|
||||
@ -106,6 +108,27 @@ struct tasdevice_calibration {
|
||||
struct tasdevice_data dev_data;
|
||||
};
|
||||
|
||||
struct fct_param_address {
|
||||
/* Thermal data for PG 1.0 device */
|
||||
unsigned char thr[3];
|
||||
/* Thermal data for PG 2.0 device */
|
||||
unsigned char thr2[3];
|
||||
/* Pilot tone enable flag, usually the sine wave */
|
||||
unsigned char plt_flg[3];
|
||||
/* Pilot tone gain for calibration */
|
||||
unsigned char sin_gn[3];
|
||||
/* Pilot tone gain for calibration */
|
||||
unsigned char sin_gn2[3];
|
||||
/* high 32-bit of real-time spk impedance */
|
||||
unsigned char r0_reg[3];
|
||||
/* check spk connection */
|
||||
unsigned char tf_reg[3];
|
||||
/* check spk resonant frequency */
|
||||
unsigned char a1_reg[3];
|
||||
/* check spk resonant frequency */
|
||||
unsigned char a2_reg[3];
|
||||
};
|
||||
|
||||
struct tasdevice_fw {
|
||||
struct tasdevice_dspfw_hdr fw_hdr;
|
||||
unsigned short nr_programs;
|
||||
@ -114,6 +137,7 @@ struct tasdevice_fw {
|
||||
struct tasdevice_config *configs;
|
||||
unsigned short nr_calibrations;
|
||||
struct tasdevice_calibration *calibrations;
|
||||
struct fct_param_address fct_par_addr;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier
|
||||
//
|
||||
// Copyright (C) 2022 - 2024 Texas Instruments Incorporated
|
||||
// Copyright (C) 2022 - 2025 Texas Instruments Incorporated
|
||||
// https://www.ti.com
|
||||
//
|
||||
// The TAS2563/TAS2781 driver implements a flexible and configurable
|
||||
@ -11,6 +11,7 @@
|
||||
//
|
||||
// Author: Shenghao Ding <shenghao-ding@ti.com>
|
||||
// Author: Kevin Lu <kevin-lu@ti.com>
|
||||
// Author: Baojun Xu <baojun.xu@ti.com>
|
||||
//
|
||||
|
||||
#ifndef __TAS2781_H__
|
||||
@ -31,7 +32,7 @@
|
||||
SNDRV_PCM_FMTBIT_S24_LE | \
|
||||
SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
/*PAGE Control Register (available in page0 of each book) */
|
||||
/* PAGE Control Register (available in page0 of each book) */
|
||||
#define TASDEVICE_PAGE_SELECT 0x00
|
||||
#define TASDEVICE_BOOKCTL_PAGE 0x00
|
||||
#define TASDEVICE_BOOKCTL_REG 127
|
||||
@ -42,12 +43,12 @@
|
||||
#define TASDEVICE_REG(book, page, reg) (((book * 256 * 128) + \
|
||||
(page * 128)) + reg)
|
||||
|
||||
/*Software Reset */
|
||||
#define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0X0, 0x01)
|
||||
/* Software Reset */
|
||||
#define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0x0, 0x01)
|
||||
#define TASDEVICE_REG_SWRESET_RESET BIT(0)
|
||||
|
||||
/*I2C Checksum */
|
||||
#define TASDEVICE_I2CChecksum TASDEVICE_REG(0x0, 0x0, 0x7E)
|
||||
/* I2C Checksum */
|
||||
#define TASDEVICE_CHECKSUM_REG TASDEVICE_REG(0x0, 0x0, 0x7e)
|
||||
|
||||
/* XM_340 */
|
||||
#define TASDEVICE_XM_A1_REG TASDEVICE_REG(0x64, 0x63, 0x3c)
|
||||
@ -55,8 +56,8 @@
|
||||
#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 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)
|
||||
|
||||
@ -95,8 +96,8 @@
|
||||
#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_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)
|
||||
@ -112,6 +113,12 @@ enum audio_device {
|
||||
TAS2781,
|
||||
};
|
||||
|
||||
enum dspbin_type {
|
||||
TASDEV_BASIC,
|
||||
TASDEV_ALPHA,
|
||||
TASDEV_BETA,
|
||||
};
|
||||
|
||||
enum device_catlog_id {
|
||||
LENOVO = 0,
|
||||
OTHERS
|
||||
@ -126,6 +133,7 @@ struct bulk_reg_val {
|
||||
|
||||
struct tasdevice {
|
||||
struct bulk_reg_val *cali_data_backup;
|
||||
struct bulk_reg_val alp_cali_bckp;
|
||||
struct tasdevice_fw *cali_data_fmw;
|
||||
unsigned int dev_addr;
|
||||
unsigned int err_code;
|
||||
@ -161,7 +169,6 @@ struct tasdevice_priv {
|
||||
struct mutex codec_lock;
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
struct tm tm;
|
||||
|
||||
enum device_catlog_id catlog_id;
|
||||
unsigned char cal_binaryname[TASDEVICE_MAX_CHANNELS][64];
|
||||
@ -171,6 +178,7 @@ struct tasdevice_priv {
|
||||
unsigned char dev_name[32];
|
||||
const char *name_prefix;
|
||||
unsigned char ndev;
|
||||
unsigned int dspbin_typ;
|
||||
unsigned int magic_num;
|
||||
unsigned int chip_id;
|
||||
unsigned int sysclk;
|
||||
@ -196,6 +204,9 @@ struct tasdevice_priv {
|
||||
int (*fw_parse_configuration_data)(struct tasdevice_priv *tas_priv,
|
||||
struct tasdevice_fw *tas_fmw,
|
||||
const struct firmware *fmw, int offset);
|
||||
int (*fw_parse_fct_param_address)(struct tasdevice_priv *tas_priv,
|
||||
struct tasdevice_fw *tas_fmw,
|
||||
const struct firmware *fmw, int offset);
|
||||
int (*tasdevice_load_block)(struct tasdevice_priv *tas_priv,
|
||||
struct tasdev_blk *block);
|
||||
|
||||
|
@ -151,6 +151,9 @@ struct wm8904_pdata {
|
||||
int num_retune_mobile_cfgs;
|
||||
struct wm8904_retune_mobile_cfg *retune_mobile_cfgs;
|
||||
|
||||
bool in1l_as_dmicdat1;
|
||||
bool in1r_as_dmicdat2;
|
||||
|
||||
u32 gpio_cfg[WM8904_GPIO_REGS];
|
||||
u32 mic_cfg[WM8904_MIC_REGS];
|
||||
};
|
||||
|
@ -77,6 +77,17 @@ enum avs_tplg_token {
|
||||
AVS_TKN_MODCFG_UPDOWN_MIX_CHAN_MAP_U32 = 430,
|
||||
AVS_TKN_MODCFG_EXT_NUM_INPUT_PINS_U16 = 431,
|
||||
AVS_TKN_MODCFG_EXT_NUM_OUTPUT_PINS_U16 = 432,
|
||||
AVS_TKN_MODCFG_WHM_REF_AFMT_ID_U32 = 433,
|
||||
AVS_TKN_MODCFG_WHM_OUT_AFMT_ID_U32 = 434,
|
||||
AVS_TKN_MODCFG_WHM_WAKE_TICK_PERIOD_U32 = 435,
|
||||
AVS_TKN_MODCFG_WHM_VINDEX_U8 = 436,
|
||||
AVS_TKN_MODCFG_WHM_DMA_TYPE_U32 = 437,
|
||||
AVS_TKN_MODCFG_WHM_DMABUFF_SIZE_U32 = 438,
|
||||
AVS_TKN_MODCFG_WHM_BLOB_AFMT_ID_U32 = 439,
|
||||
AVS_TKN_MODCFG_PEAKVOL_VOLUME_U32 = 440,
|
||||
AVS_TKN_MODCFG_PEAKVOL_CHANNEL_ID_U32 = 441, /* reserved */
|
||||
AVS_TKN_MODCFG_PEAKVOL_CURVE_TYPE_U32 = 442,
|
||||
AVS_TKN_MODCFG_PEAKVOL_CURVE_DURATION_U32 = 443,
|
||||
|
||||
/* struct avs_tplg_pplcfg */
|
||||
AVS_TKN_PPLCFG_ID_U32 = 1401,
|
||||
|
@ -387,7 +387,6 @@ void snd_ac97_controller_unregister(struct ac97_controller *ac97_ctrl)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_ac97_controller_unregister);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ac97_pm_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct ac97_codec_device *codec = to_ac97_device(dev);
|
||||
@ -419,7 +418,6 @@ static int ac97_pm_runtime_resume(struct device *dev)
|
||||
|
||||
return pm_generic_runtime_resume(dev);
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct dev_pm_ops ac97_pm = {
|
||||
.suspend = pm_generic_suspend,
|
||||
@ -428,10 +426,7 @@ static const struct dev_pm_ops ac97_pm = {
|
||||
.thaw = pm_generic_thaw,
|
||||
.poweroff = pm_generic_poweroff,
|
||||
.restore = pm_generic_restore,
|
||||
SET_RUNTIME_PM_OPS(
|
||||
ac97_pm_runtime_suspend,
|
||||
ac97_pm_runtime_resume,
|
||||
NULL)
|
||||
RUNTIME_PM_OPS(ac97_pm_runtime_suspend, ac97_pm_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static int ac97_get_enable_clk(struct ac97_codec_device *adev)
|
||||
@ -535,7 +530,7 @@ const struct bus_type ac97_bus_type = {
|
||||
.name = "ac97bus",
|
||||
.dev_groups = ac97_dev_groups,
|
||||
.match = ac97_bus_match,
|
||||
.pm = &ac97_pm,
|
||||
.pm = pm_ptr(&ac97_pm),
|
||||
.probe = ac97_bus_probe,
|
||||
.remove = ac97_bus_remove,
|
||||
};
|
||||
|
@ -1061,7 +1061,7 @@ static void aaci_remove(struct amba_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static struct amba_id aaci_ids[] = {
|
||||
static const struct amba_id aaci_ids[] = {
|
||||
{
|
||||
.id = 0x00041041,
|
||||
.mask = 0x000fffff,
|
||||
|
@ -817,7 +817,6 @@ err_prepare_enable:
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int atmel_ac97c_suspend(struct device *pdev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(pdev);
|
||||
@ -836,11 +835,7 @@ static int atmel_ac97c_resume(struct device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume);
|
||||
#define ATMEL_AC97C_PM_OPS &atmel_ac97c_pm
|
||||
#else
|
||||
#define ATMEL_AC97C_PM_OPS NULL
|
||||
#endif
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume);
|
||||
|
||||
static void atmel_ac97c_remove(struct platform_device *pdev)
|
||||
{
|
||||
@ -864,7 +859,7 @@ static struct platform_driver atmel_ac97c_driver = {
|
||||
.remove = atmel_ac97c_remove,
|
||||
.driver = {
|
||||
.name = "atmel_ac97c",
|
||||
.pm = ATMEL_AC97C_PM_OPS,
|
||||
.pm = pm_ptr(&atmel_ac97c_pm),
|
||||
.of_match_table = atmel_ac97c_dt_ids,
|
||||
},
|
||||
};
|
||||
|
@ -592,7 +592,6 @@ static const struct attribute_group *pcm_dev_attr_groups[];
|
||||
* PM callbacks: we need to deal only with suspend here, as the resume is
|
||||
* triggered either from user-space or the driver's resume callback
|
||||
*/
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int do_pcm_suspend(struct device *dev)
|
||||
{
|
||||
struct snd_pcm_str *pstr = dev_get_drvdata(dev);
|
||||
@ -601,10 +600,9 @@ static int do_pcm_suspend(struct device *dev)
|
||||
snd_pcm_suspend_all(pstr->pcm);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops pcm_dev_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(do_pcm_suspend, NULL)
|
||||
SYSTEM_SLEEP_PM_OPS(do_pcm_suspend, NULL)
|
||||
};
|
||||
|
||||
/* device type for PCM -- basically only for passing PM callbacks */
|
||||
|
@ -5,8 +5,10 @@
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/hdmi.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_eld.h>
|
||||
#include <sound/info.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_drm_eld.h>
|
||||
|
||||
@ -162,3 +164,388 @@ int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld)
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_pcm_hw_constraint_eld);
|
||||
|
||||
#define SND_PRINT_RATES_ADVISED_BUFSIZE 80
|
||||
#define SND_PRINT_BITS_ADVISED_BUFSIZE 16
|
||||
#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
|
||||
|
||||
static const char * const eld_connection_type_names[4] = {
|
||||
"HDMI",
|
||||
"DisplayPort",
|
||||
"2-reserved",
|
||||
"3-reserved"
|
||||
};
|
||||
|
||||
static const char * const cea_audio_coding_type_names[] = {
|
||||
/* 0 */ "undefined",
|
||||
/* 1 */ "LPCM",
|
||||
/* 2 */ "AC-3",
|
||||
/* 3 */ "MPEG1",
|
||||
/* 4 */ "MP3",
|
||||
/* 5 */ "MPEG2",
|
||||
/* 6 */ "AAC-LC",
|
||||
/* 7 */ "DTS",
|
||||
/* 8 */ "ATRAC",
|
||||
/* 9 */ "DSD (One Bit Audio)",
|
||||
/* 10 */ "E-AC-3/DD+ (Dolby Digital Plus)",
|
||||
/* 11 */ "DTS-HD",
|
||||
/* 12 */ "MLP (Dolby TrueHD)",
|
||||
/* 13 */ "DST",
|
||||
/* 14 */ "WMAPro",
|
||||
/* 15 */ "HE-AAC",
|
||||
/* 16 */ "HE-AACv2",
|
||||
/* 17 */ "MPEG Surround",
|
||||
};
|
||||
|
||||
static const char * const cea_speaker_allocation_names[] = {
|
||||
/* 0 */ "FL/FR",
|
||||
/* 1 */ "LFE",
|
||||
/* 2 */ "FC",
|
||||
/* 3 */ "RL/RR",
|
||||
/* 4 */ "RC",
|
||||
/* 5 */ "FLC/FRC",
|
||||
/* 6 */ "RLC/RRC",
|
||||
/* 7 */ "FLW/FRW",
|
||||
/* 8 */ "FLH/FRH",
|
||||
/* 9 */ "TC",
|
||||
/* 10 */ "FCH",
|
||||
};
|
||||
|
||||
/*
|
||||
* SS1:SS0 index => sample size
|
||||
*/
|
||||
static const int cea_sample_sizes[4] = {
|
||||
0, /* 0: Refer to Stream Header */
|
||||
ELD_PCM_BITS_16, /* 1: 16 bits */
|
||||
ELD_PCM_BITS_20, /* 2: 20 bits */
|
||||
ELD_PCM_BITS_24, /* 3: 24 bits */
|
||||
};
|
||||
|
||||
/*
|
||||
* SF2:SF1:SF0 index => sampling frequency
|
||||
*/
|
||||
static const int cea_sampling_frequencies[8] = {
|
||||
0, /* 0: Refer to Stream Header */
|
||||
SNDRV_PCM_RATE_32000, /* 1: 32000Hz */
|
||||
SNDRV_PCM_RATE_44100, /* 2: 44100Hz */
|
||||
SNDRV_PCM_RATE_48000, /* 3: 48000Hz */
|
||||
SNDRV_PCM_RATE_88200, /* 4: 88200Hz */
|
||||
SNDRV_PCM_RATE_96000, /* 5: 96000Hz */
|
||||
SNDRV_PCM_RATE_176400, /* 6: 176400Hz */
|
||||
SNDRV_PCM_RATE_192000, /* 7: 192000Hz */
|
||||
};
|
||||
|
||||
#define GRAB_BITS(buf, byte, lowbit, bits) \
|
||||
({ \
|
||||
BUILD_BUG_ON(lowbit > 7); \
|
||||
BUILD_BUG_ON(bits > 8); \
|
||||
BUILD_BUG_ON(bits <= 0); \
|
||||
\
|
||||
(buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \
|
||||
})
|
||||
|
||||
static void hdmi_update_short_audio_desc(struct device *dev,
|
||||
struct snd_cea_sad *a,
|
||||
const unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
int val;
|
||||
|
||||
val = GRAB_BITS(buf, 1, 0, 7);
|
||||
a->rates = 0;
|
||||
for (i = 0; i < 7; i++)
|
||||
if (val & (1 << i))
|
||||
a->rates |= cea_sampling_frequencies[i + 1];
|
||||
|
||||
a->channels = GRAB_BITS(buf, 0, 0, 3);
|
||||
a->channels++;
|
||||
|
||||
a->sample_bits = 0;
|
||||
a->max_bitrate = 0;
|
||||
|
||||
a->format = GRAB_BITS(buf, 0, 3, 4);
|
||||
switch (a->format) {
|
||||
case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
|
||||
dev_info(dev, "HDMI: audio coding type 0 not expected\n");
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_LPCM:
|
||||
val = GRAB_BITS(buf, 2, 0, 3);
|
||||
for (i = 0; i < 3; i++)
|
||||
if (val & (1 << i))
|
||||
a->sample_bits |= cea_sample_sizes[i + 1];
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_AC3:
|
||||
case AUDIO_CODING_TYPE_MPEG1:
|
||||
case AUDIO_CODING_TYPE_MP3:
|
||||
case AUDIO_CODING_TYPE_MPEG2:
|
||||
case AUDIO_CODING_TYPE_AACLC:
|
||||
case AUDIO_CODING_TYPE_DTS:
|
||||
case AUDIO_CODING_TYPE_ATRAC:
|
||||
a->max_bitrate = GRAB_BITS(buf, 2, 0, 8);
|
||||
a->max_bitrate *= 8000;
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_SACD:
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_EAC3:
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_DTS_HD:
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_MLP:
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_DST:
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_WMAPRO:
|
||||
a->profile = GRAB_BITS(buf, 2, 0, 3);
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_REF_CXT:
|
||||
a->format = GRAB_BITS(buf, 2, 3, 5);
|
||||
if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
|
||||
a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
|
||||
dev_info(dev,
|
||||
"HDMI: audio coding xtype %d not expected\n",
|
||||
a->format);
|
||||
a->format = 0;
|
||||
} else
|
||||
a->format += AUDIO_CODING_TYPE_HE_AAC -
|
||||
AUDIO_CODING_XTYPE_HE_AAC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Be careful, ELD buf could be totally rubbish!
|
||||
*/
|
||||
int snd_parse_eld(struct device *dev, struct snd_parsed_hdmi_eld *e,
|
||||
const unsigned char *buf, int size)
|
||||
{
|
||||
int mnl;
|
||||
int i;
|
||||
|
||||
memset(e, 0, sizeof(*e));
|
||||
e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
|
||||
if (e->eld_ver != ELD_VER_CEA_861D &&
|
||||
e->eld_ver != ELD_VER_PARTIAL) {
|
||||
dev_info(dev, "HDMI: Unknown ELD version %d\n", e->eld_ver);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
e->baseline_len = GRAB_BITS(buf, 2, 0, 8);
|
||||
mnl = GRAB_BITS(buf, 4, 0, 5);
|
||||
e->cea_edid_ver = GRAB_BITS(buf, 4, 5, 3);
|
||||
|
||||
e->support_hdcp = GRAB_BITS(buf, 5, 0, 1);
|
||||
e->support_ai = GRAB_BITS(buf, 5, 1, 1);
|
||||
e->conn_type = GRAB_BITS(buf, 5, 2, 2);
|
||||
e->sad_count = GRAB_BITS(buf, 5, 4, 4);
|
||||
|
||||
e->aud_synch_delay = GRAB_BITS(buf, 6, 0, 8) * 2;
|
||||
e->spk_alloc = GRAB_BITS(buf, 7, 0, 7);
|
||||
|
||||
e->port_id = get_unaligned_le64(buf + 8);
|
||||
|
||||
/* not specified, but the spec's tendency is little endian */
|
||||
e->manufacture_id = get_unaligned_le16(buf + 16);
|
||||
e->product_id = get_unaligned_le16(buf + 18);
|
||||
|
||||
if (mnl > ELD_MAX_MNL) {
|
||||
dev_info(dev, "HDMI: MNL is reserved value %d\n", mnl);
|
||||
goto out_fail;
|
||||
} else if (ELD_FIXED_BYTES + mnl > size) {
|
||||
dev_info(dev, "HDMI: out of range MNL %d\n", mnl);
|
||||
goto out_fail;
|
||||
} else
|
||||
strscpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
|
||||
|
||||
for (i = 0; i < e->sad_count; i++) {
|
||||
if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
|
||||
dev_info(dev, "HDMI: out of range SAD %d\n", i);
|
||||
goto out_fail;
|
||||
}
|
||||
hdmi_update_short_audio_desc(dev, e->sad + i,
|
||||
buf + ELD_FIXED_BYTES + mnl + 3 * i);
|
||||
}
|
||||
|
||||
/*
|
||||
* HDMI sink's ELD info cannot always be retrieved for now, e.g.
|
||||
* in console or for audio devices. Assume the highest speakers
|
||||
* configuration, to _not_ prohibit multi-channel audio playback.
|
||||
*/
|
||||
if (!e->spk_alloc)
|
||||
e->spk_alloc = 0xffff;
|
||||
|
||||
return 0;
|
||||
|
||||
out_fail:
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_parse_eld);
|
||||
|
||||
/*
|
||||
* SNDRV_PCM_RATE_* and AC_PAR_PCM values don't match, print correct rates with
|
||||
* hdmi-specific routine.
|
||||
*/
|
||||
static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
|
||||
{
|
||||
static const unsigned int alsa_rates[] = {
|
||||
5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
|
||||
88200, 96000, 176400, 192000, 384000
|
||||
};
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++)
|
||||
if (pcm & (1 << i))
|
||||
j += scnprintf(buf + j, buflen - j, " %d",
|
||||
alsa_rates[i]);
|
||||
|
||||
buf[j] = '\0'; /* necessary when j == 0 */
|
||||
}
|
||||
|
||||
static void eld_print_pcm_bits(int pcm, char *buf, int buflen)
|
||||
{
|
||||
static const unsigned int bits[] = { 8, 16, 20, 24, 32 };
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
|
||||
if (pcm & (ELD_PCM_BITS_8 << i))
|
||||
j += scnprintf(buf + j, buflen - j, " %d", bits[i]);
|
||||
|
||||
buf[j] = '\0'; /* necessary when j == 0 */
|
||||
}
|
||||
|
||||
static void hdmi_show_short_audio_desc(struct device *dev,
|
||||
struct snd_cea_sad *a)
|
||||
{
|
||||
char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
|
||||
char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
|
||||
|
||||
if (!a->format)
|
||||
return;
|
||||
|
||||
hdmi_print_pcm_rates(a->rates, buf, sizeof(buf));
|
||||
|
||||
if (a->format == AUDIO_CODING_TYPE_LPCM)
|
||||
eld_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2) - 8);
|
||||
else if (a->max_bitrate)
|
||||
snprintf(buf2, sizeof(buf2),
|
||||
", max bitrate = %d", a->max_bitrate);
|
||||
else
|
||||
buf2[0] = '\0';
|
||||
|
||||
dev_dbg(dev,
|
||||
"HDMI: supports coding type %s: channels = %d, rates =%s%s\n",
|
||||
cea_audio_coding_type_names[a->format],
|
||||
a->channels, buf, buf2);
|
||||
}
|
||||
|
||||
static void snd_eld_print_channel_allocation(int spk_alloc, char *buf, int buflen)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) {
|
||||
if (spk_alloc & (1 << i))
|
||||
j += scnprintf(buf + j, buflen - j, " %s",
|
||||
cea_speaker_allocation_names[i]);
|
||||
}
|
||||
buf[j] = '\0'; /* necessary when j == 0 */
|
||||
}
|
||||
|
||||
void snd_show_eld(struct device *dev, struct snd_parsed_hdmi_eld *e)
|
||||
{
|
||||
int i;
|
||||
|
||||
dev_dbg(dev, "HDMI: detected monitor %s at connection type %s\n",
|
||||
e->monitor_name,
|
||||
eld_connection_type_names[e->conn_type]);
|
||||
|
||||
if (e->spk_alloc) {
|
||||
char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
|
||||
|
||||
snd_eld_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
|
||||
dev_dbg(dev, "HDMI: available speakers:%s\n", buf);
|
||||
}
|
||||
|
||||
for (i = 0; i < e->sad_count; i++)
|
||||
hdmi_show_short_audio_desc(dev, e->sad + i);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_show_eld);
|
||||
|
||||
#ifdef CONFIG_SND_PROC_FS
|
||||
static void hdmi_print_sad_info(int i, struct snd_cea_sad *a,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
|
||||
|
||||
snd_iprintf(buffer, "sad%d_coding_type\t[0x%x] %s\n",
|
||||
i, a->format, cea_audio_coding_type_names[a->format]);
|
||||
snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels);
|
||||
|
||||
hdmi_print_pcm_rates(a->rates, buf, sizeof(buf));
|
||||
snd_iprintf(buffer, "sad%d_rates\t\t[0x%x]%s\n", i, a->rates, buf);
|
||||
|
||||
if (a->format == AUDIO_CODING_TYPE_LPCM) {
|
||||
eld_print_pcm_bits(a->sample_bits, buf, sizeof(buf));
|
||||
snd_iprintf(buffer, "sad%d_bits\t\t[0x%x]%s\n",
|
||||
i, a->sample_bits, buf);
|
||||
}
|
||||
|
||||
if (a->max_bitrate)
|
||||
snd_iprintf(buffer, "sad%d_max_bitrate\t%d\n",
|
||||
i, a->max_bitrate);
|
||||
|
||||
if (a->profile)
|
||||
snd_iprintf(buffer, "sad%d_profile\t\t%d\n", i, a->profile);
|
||||
}
|
||||
|
||||
void snd_print_eld_info(struct snd_parsed_hdmi_eld *e,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
|
||||
int i;
|
||||
static const char * const eld_version_names[32] = {
|
||||
"reserved",
|
||||
"reserved",
|
||||
"CEA-861D or below",
|
||||
[3 ... 30] = "reserved",
|
||||
[31] = "partial"
|
||||
};
|
||||
static const char * const cea_edid_version_names[8] = {
|
||||
"no CEA EDID Timing Extension block present",
|
||||
"CEA-861",
|
||||
"CEA-861-A",
|
||||
"CEA-861-B, C or D",
|
||||
[4 ... 7] = "reserved"
|
||||
};
|
||||
|
||||
snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
|
||||
snd_iprintf(buffer, "connection_type\t\t%s\n",
|
||||
eld_connection_type_names[e->conn_type]);
|
||||
snd_iprintf(buffer, "eld_version\t\t[0x%x] %s\n", e->eld_ver,
|
||||
eld_version_names[e->eld_ver]);
|
||||
snd_iprintf(buffer, "edid_version\t\t[0x%x] %s\n", e->cea_edid_ver,
|
||||
cea_edid_version_names[e->cea_edid_ver]);
|
||||
snd_iprintf(buffer, "manufacture_id\t\t0x%x\n", e->manufacture_id);
|
||||
snd_iprintf(buffer, "product_id\t\t0x%x\n", e->product_id);
|
||||
snd_iprintf(buffer, "port_id\t\t\t0x%llx\n", (long long)e->port_id);
|
||||
snd_iprintf(buffer, "support_hdcp\t\t%d\n", e->support_hdcp);
|
||||
snd_iprintf(buffer, "support_ai\t\t%d\n", e->support_ai);
|
||||
snd_iprintf(buffer, "audio_sync_delay\t%d\n", e->aud_synch_delay);
|
||||
|
||||
snd_eld_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
|
||||
snd_iprintf(buffer, "speakers\t\t[0x%x]%s\n", e->spk_alloc, buf);
|
||||
|
||||
snd_iprintf(buffer, "sad_count\t\t%d\n", e->sad_count);
|
||||
|
||||
for (i = 0; i < e->sad_count; i++)
|
||||
hdmi_print_sad_info(i, e->sad + i, buffer);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_print_eld_info);
|
||||
#endif /* CONFIG_SND_PROC_FS */
|
||||
|
@ -432,9 +432,9 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
|
||||
if (samples == 0)
|
||||
return 0;
|
||||
width = pcm_formats[(INT)format].phys; /* physical width */
|
||||
pat = pcm_formats[(INT)format].silence;
|
||||
if (!width || !pat)
|
||||
if (!width)
|
||||
return -EINVAL;
|
||||
pat = pcm_formats[(INT)format].silence;
|
||||
/* signed or 1 byte data */
|
||||
if (pcm_formats[(INT)format].signd == 1 || width <= 8) {
|
||||
unsigned int bytes = samples * width / 8;
|
||||
|
@ -290,16 +290,14 @@ note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, st
|
||||
if (note == 255 && info->ch[ch].note >= 0) {
|
||||
/* volume control */
|
||||
int type;
|
||||
//if (! vel)
|
||||
/* set volume to zero -- note off */
|
||||
// type = SNDRV_SEQ_EVENT_NOTEOFF;
|
||||
//else
|
||||
if (info->ch[ch].vel)
|
||||
|
||||
if (info->ch[ch].vel)
|
||||
/* sample already started -- volume change */
|
||||
type = SNDRV_SEQ_EVENT_KEYPRESS;
|
||||
else
|
||||
/* sample not started -- start now */
|
||||
type = SNDRV_SEQ_EVENT_NOTEON;
|
||||
|
||||
info->ch[ch].vel = vel;
|
||||
return set_note_event(dp, dev, type, ch, info->ch[ch].note, vel, ev);
|
||||
} else if (note >= 128)
|
||||
|
@ -1150,8 +1150,7 @@ static __poll_t snd_seq_poll(struct file *file, poll_table * wait)
|
||||
if (snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT) {
|
||||
|
||||
/* check if data is available in the pool */
|
||||
if (!snd_seq_write_pool_allocated(client) ||
|
||||
snd_seq_pool_poll_wait(client->pool, file, wait))
|
||||
if (snd_seq_pool_poll_wait(client->pool, file, wait))
|
||||
mask |= EPOLLOUT | EPOLLWRNORM;
|
||||
}
|
||||
|
||||
@ -2586,8 +2585,6 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table
|
||||
if (client == NULL)
|
||||
return -ENXIO;
|
||||
|
||||
if (! snd_seq_write_pool_allocated(client))
|
||||
return 1;
|
||||
if (snd_seq_pool_poll_wait(client->pool, file, wait))
|
||||
return 1;
|
||||
return 0;
|
||||
@ -2729,6 +2726,7 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,
|
||||
continue;
|
||||
}
|
||||
|
||||
mutex_lock(&client->ioctl_mutex);
|
||||
snd_iprintf(buffer, "Client %3d : \"%s\" [%s %s]\n",
|
||||
c, client->name,
|
||||
client->type == USER_CLIENT ? "User" : "Kernel",
|
||||
@ -2746,6 +2744,7 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,
|
||||
snd_iprintf(buffer, " Input pool :\n");
|
||||
snd_seq_info_pool(buffer, client->data.user.fifo->pool, " ");
|
||||
}
|
||||
mutex_unlock(&client->ioctl_mutex);
|
||||
snd_seq_client_unlock(client);
|
||||
}
|
||||
}
|
||||
|
@ -427,6 +427,7 @@ int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file,
|
||||
poll_table *wait)
|
||||
{
|
||||
poll_wait(file, &pool->output_sleep, wait);
|
||||
guard(spinlock_irq)(&pool->lock);
|
||||
return snd_seq_output_ok(pool);
|
||||
}
|
||||
|
||||
|
@ -1515,91 +1515,97 @@ static void snd_timer_user_copy_id(struct snd_timer_id *id, struct snd_timer *ti
|
||||
id->subdevice = timer->tmr_subdevice;
|
||||
}
|
||||
|
||||
static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
|
||||
static void get_next_device(struct snd_timer_id *id)
|
||||
{
|
||||
struct snd_timer_id id;
|
||||
struct snd_timer *timer;
|
||||
struct list_head *p;
|
||||
|
||||
if (copy_from_user(&id, _tid, sizeof(id)))
|
||||
return -EFAULT;
|
||||
guard(mutex)(®ister_mutex);
|
||||
if (id.dev_class < 0) { /* first item */
|
||||
if (id->dev_class < 0) { /* first item */
|
||||
if (list_empty(&snd_timer_list))
|
||||
snd_timer_user_zero_id(&id);
|
||||
snd_timer_user_zero_id(id);
|
||||
else {
|
||||
timer = list_entry(snd_timer_list.next,
|
||||
struct snd_timer, device_list);
|
||||
snd_timer_user_copy_id(&id, timer);
|
||||
snd_timer_user_copy_id(id, timer);
|
||||
}
|
||||
} else {
|
||||
switch (id.dev_class) {
|
||||
switch (id->dev_class) {
|
||||
case SNDRV_TIMER_CLASS_GLOBAL:
|
||||
id.device = id.device < 0 ? 0 : id.device + 1;
|
||||
id->device = id->device < 0 ? 0 : id->device + 1;
|
||||
list_for_each(p, &snd_timer_list) {
|
||||
timer = list_entry(p, struct snd_timer, device_list);
|
||||
if (timer->tmr_class > SNDRV_TIMER_CLASS_GLOBAL) {
|
||||
snd_timer_user_copy_id(&id, timer);
|
||||
snd_timer_user_copy_id(id, timer);
|
||||
break;
|
||||
}
|
||||
if (timer->tmr_device >= id.device) {
|
||||
snd_timer_user_copy_id(&id, timer);
|
||||
if (timer->tmr_device >= id->device) {
|
||||
snd_timer_user_copy_id(id, timer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p == &snd_timer_list)
|
||||
snd_timer_user_zero_id(&id);
|
||||
snd_timer_user_zero_id(id);
|
||||
break;
|
||||
case SNDRV_TIMER_CLASS_CARD:
|
||||
case SNDRV_TIMER_CLASS_PCM:
|
||||
if (id.card < 0) {
|
||||
id.card = 0;
|
||||
if (id->card < 0) {
|
||||
id->card = 0;
|
||||
} else {
|
||||
if (id.device < 0) {
|
||||
id.device = 0;
|
||||
if (id->device < 0) {
|
||||
id->device = 0;
|
||||
} else {
|
||||
if (id.subdevice < 0)
|
||||
id.subdevice = 0;
|
||||
else if (id.subdevice < INT_MAX)
|
||||
id.subdevice++;
|
||||
if (id->subdevice < 0)
|
||||
id->subdevice = 0;
|
||||
else if (id->subdevice < INT_MAX)
|
||||
id->subdevice++;
|
||||
}
|
||||
}
|
||||
list_for_each(p, &snd_timer_list) {
|
||||
timer = list_entry(p, struct snd_timer, device_list);
|
||||
if (timer->tmr_class > id.dev_class) {
|
||||
snd_timer_user_copy_id(&id, timer);
|
||||
if (timer->tmr_class > id->dev_class) {
|
||||
snd_timer_user_copy_id(id, timer);
|
||||
break;
|
||||
}
|
||||
if (timer->tmr_class < id.dev_class)
|
||||
if (timer->tmr_class < id->dev_class)
|
||||
continue;
|
||||
if (timer->card->number > id.card) {
|
||||
snd_timer_user_copy_id(&id, timer);
|
||||
if (timer->card->number > id->card) {
|
||||
snd_timer_user_copy_id(id, timer);
|
||||
break;
|
||||
}
|
||||
if (timer->card->number < id.card)
|
||||
if (timer->card->number < id->card)
|
||||
continue;
|
||||
if (timer->tmr_device > id.device) {
|
||||
snd_timer_user_copy_id(&id, timer);
|
||||
if (timer->tmr_device > id->device) {
|
||||
snd_timer_user_copy_id(id, timer);
|
||||
break;
|
||||
}
|
||||
if (timer->tmr_device < id.device)
|
||||
if (timer->tmr_device < id->device)
|
||||
continue;
|
||||
if (timer->tmr_subdevice > id.subdevice) {
|
||||
snd_timer_user_copy_id(&id, timer);
|
||||
if (timer->tmr_subdevice > id->subdevice) {
|
||||
snd_timer_user_copy_id(id, timer);
|
||||
break;
|
||||
}
|
||||
if (timer->tmr_subdevice < id.subdevice)
|
||||
if (timer->tmr_subdevice < id->subdevice)
|
||||
continue;
|
||||
snd_timer_user_copy_id(&id, timer);
|
||||
snd_timer_user_copy_id(id, timer);
|
||||
break;
|
||||
}
|
||||
if (p == &snd_timer_list)
|
||||
snd_timer_user_zero_id(&id);
|
||||
snd_timer_user_zero_id(id);
|
||||
break;
|
||||
default:
|
||||
snd_timer_user_zero_id(&id);
|
||||
snd_timer_user_zero_id(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
|
||||
{
|
||||
struct snd_timer_id id;
|
||||
|
||||
if (copy_from_user(&id, _tid, sizeof(id)))
|
||||
return -EFAULT;
|
||||
scoped_guard(mutex, ®ister_mutex)
|
||||
get_next_device(&id);
|
||||
if (copy_to_user(_tid, &id, sizeof(*_tid)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
@ -1620,23 +1626,24 @@ static int snd_timer_user_ginfo(struct file *file,
|
||||
tid = ginfo->tid;
|
||||
memset(ginfo, 0, sizeof(*ginfo));
|
||||
ginfo->tid = tid;
|
||||
guard(mutex)(®ister_mutex);
|
||||
t = snd_timer_find(&tid);
|
||||
if (!t)
|
||||
return -ENODEV;
|
||||
ginfo->card = t->card ? t->card->number : -1;
|
||||
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
|
||||
ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
|
||||
strscpy(ginfo->id, t->id, sizeof(ginfo->id));
|
||||
strscpy(ginfo->name, t->name, sizeof(ginfo->name));
|
||||
scoped_guard(spinlock_irq, &t->lock)
|
||||
ginfo->resolution = snd_timer_hw_resolution(t);
|
||||
if (t->hw.resolution_min > 0) {
|
||||
ginfo->resolution_min = t->hw.resolution_min;
|
||||
ginfo->resolution_max = t->hw.resolution_max;
|
||||
}
|
||||
list_for_each(p, &t->open_list_head) {
|
||||
ginfo->clients++;
|
||||
scoped_guard(mutex, ®ister_mutex) {
|
||||
t = snd_timer_find(&tid);
|
||||
if (!t)
|
||||
return -ENODEV;
|
||||
ginfo->card = t->card ? t->card->number : -1;
|
||||
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
|
||||
ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
|
||||
strscpy(ginfo->id, t->id, sizeof(ginfo->id));
|
||||
strscpy(ginfo->name, t->name, sizeof(ginfo->name));
|
||||
scoped_guard(spinlock_irq, &t->lock)
|
||||
ginfo->resolution = snd_timer_hw_resolution(t);
|
||||
if (t->hw.resolution_min > 0) {
|
||||
ginfo->resolution_min = t->hw.resolution_min;
|
||||
ginfo->resolution_max = t->hw.resolution_max;
|
||||
}
|
||||
list_for_each(p, &t->open_list_head) {
|
||||
ginfo->clients++;
|
||||
}
|
||||
}
|
||||
if (copy_to_user(_ginfo, ginfo, sizeof(*ginfo)))
|
||||
return -EFAULT;
|
||||
@ -1674,31 +1681,31 @@ static int snd_timer_user_gstatus(struct file *file,
|
||||
struct snd_timer_gstatus gstatus;
|
||||
struct snd_timer_id tid;
|
||||
struct snd_timer *t;
|
||||
int err = 0;
|
||||
|
||||
if (copy_from_user(&gstatus, _gstatus, sizeof(gstatus)))
|
||||
return -EFAULT;
|
||||
tid = gstatus.tid;
|
||||
memset(&gstatus, 0, sizeof(gstatus));
|
||||
gstatus.tid = tid;
|
||||
guard(mutex)(®ister_mutex);
|
||||
t = snd_timer_find(&tid);
|
||||
if (t != NULL) {
|
||||
guard(spinlock_irq)(&t->lock);
|
||||
gstatus.resolution = snd_timer_hw_resolution(t);
|
||||
if (t->hw.precise_resolution) {
|
||||
t->hw.precise_resolution(t, &gstatus.resolution_num,
|
||||
&gstatus.resolution_den);
|
||||
scoped_guard(mutex, ®ister_mutex) {
|
||||
t = snd_timer_find(&tid);
|
||||
if (t != NULL) {
|
||||
guard(spinlock_irq)(&t->lock);
|
||||
gstatus.resolution = snd_timer_hw_resolution(t);
|
||||
if (t->hw.precise_resolution) {
|
||||
t->hw.precise_resolution(t, &gstatus.resolution_num,
|
||||
&gstatus.resolution_den);
|
||||
} else {
|
||||
gstatus.resolution_num = gstatus.resolution;
|
||||
gstatus.resolution_den = 1000000000uL;
|
||||
}
|
||||
} else {
|
||||
gstatus.resolution_num = gstatus.resolution;
|
||||
gstatus.resolution_den = 1000000000uL;
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
err = -ENODEV;
|
||||
}
|
||||
if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus)))
|
||||
err = -EFAULT;
|
||||
return err;
|
||||
if (copy_to_user(_gstatus, &gstatus, sizeof(gstatus)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_timer_user_tselect(struct file *file,
|
||||
|
@ -108,6 +108,10 @@ static const struct config_entry config_table[] = {
|
||||
{}
|
||||
}
|
||||
},
|
||||
{
|
||||
.flags = FLAG_SST,
|
||||
.device = PCI_DEVICE_ID_INTEL_HDA_RPL_M,
|
||||
},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
|
||||
{
|
||||
|
@ -1735,27 +1735,27 @@ static int snd_es18xx_new_device(struct snd_card *card,
|
||||
chip->active = 0;
|
||||
|
||||
if (!devm_request_region(card->dev, port, 16, "ES18xx")) {
|
||||
dev_err(card->dev, "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
|
||||
dev_err(card->dev, "unable to grab ports 0x%lx-0x%lx\n", port, port + 16 - 1);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (devm_request_irq(card->dev, irq, snd_es18xx_interrupt, 0, "ES18xx",
|
||||
(void *) card)) {
|
||||
dev_err(card->dev, "unable to grap IRQ %d\n", irq);
|
||||
dev_err(card->dev, "unable to grab IRQ %d\n", irq);
|
||||
return -EBUSY;
|
||||
}
|
||||
chip->irq = irq;
|
||||
card->sync_irq = chip->irq;
|
||||
|
||||
if (snd_devm_request_dma(card->dev, dma1, "ES18xx DMA 1")) {
|
||||
dev_err(card->dev, "unable to grap DMA1 %d\n", dma1);
|
||||
dev_err(card->dev, "unable to grab DMA1 %d\n", dma1);
|
||||
return -EBUSY;
|
||||
}
|
||||
chip->dma1 = dma1;
|
||||
|
||||
if (dma2 != dma1 &&
|
||||
snd_devm_request_dma(card->dev, dma2, "ES18xx DMA 2")) {
|
||||
dev_err(card->dev, "unable to grap DMA2 %d\n", dma2);
|
||||
dev_err(card->dev, "unable to grab DMA2 %d\n", dma2);
|
||||
return -EBUSY;
|
||||
}
|
||||
chip->dma2 = dma2;
|
||||
|
@ -486,7 +486,7 @@ __skip_base:
|
||||
#endif /* CS4231 || OPTi93X */
|
||||
|
||||
#ifndef OPTi93X
|
||||
outb(irq_bits << 3 | dma_bits, chip->wss_base);
|
||||
outb(irq_bits << 3 | dma_bits, chip->wss_base);
|
||||
#else /* OPTi93X */
|
||||
snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
|
||||
#endif /* OPTi93X */
|
||||
|
@ -159,7 +159,7 @@ static int dao_set_left_input(struct dao *dao, struct rsc *input)
|
||||
struct daio *daio = &dao->daio;
|
||||
int i;
|
||||
|
||||
entry = kzalloc((sizeof(*entry) * daio->rscl.msr), GFP_KERNEL);
|
||||
entry = kcalloc(daio->rscl.msr, sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -188,7 +188,7 @@ static int dao_set_right_input(struct dao *dao, struct rsc *input)
|
||||
struct daio *daio = &dao->daio;
|
||||
int i;
|
||||
|
||||
entry = kzalloc((sizeof(*entry) * daio->rscr.msr), GFP_KERNEL);
|
||||
entry = kcalloc(daio->rscr.msr, sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1966,7 +1966,6 @@ static int __snd_echo_probe(struct pci_dev *pci,
|
||||
struct snd_card *card;
|
||||
struct echoaudio *chip;
|
||||
char *dsp;
|
||||
__maybe_unused int i;
|
||||
int err;
|
||||
|
||||
if (dev >= SNDRV_CARDS)
|
||||
@ -1976,7 +1975,6 @@ static int __snd_echo_probe(struct pci_dev *pci,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
|
||||
sizeof(*chip), &card);
|
||||
if (err < 0)
|
||||
@ -2080,7 +2078,7 @@ static int __snd_echo_probe(struct pci_dev *pci,
|
||||
#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH
|
||||
/* Creates a list of available digital modes */
|
||||
chip->num_digital_modes = 0;
|
||||
for (i = 0; i < 6; i++)
|
||||
for (int i = 0; i < 6; i++)
|
||||
if (chip->digital_modes & (1 << i))
|
||||
chip->digital_mode_list[chip->num_digital_modes++] = i;
|
||||
|
||||
@ -2092,7 +2090,7 @@ static int __snd_echo_probe(struct pci_dev *pci,
|
||||
#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK
|
||||
/* Creates a list of available clock sources */
|
||||
chip->num_clock_sources = 0;
|
||||
for (i = 0; i < 10; i++)
|
||||
for (int i = 0; i < 10; i++)
|
||||
if (chip->input_clock_types & (1 << i))
|
||||
chip->clock_source_list[chip->num_clock_sources++] = i;
|
||||
|
||||
|
@ -441,7 +441,7 @@ snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk)
|
||||
unmap_memblk(emu, blk);
|
||||
spin_unlock_irqrestore(&emu->memblk_lock, flags);
|
||||
synth_free_pages(emu, blk);
|
||||
__snd_util_mem_free(hdr, memblk);
|
||||
__snd_util_mem_free(hdr, memblk);
|
||||
mutex_unlock(&hdr->block_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
@ -267,6 +267,7 @@ comment "Set to Y if you want auto-loading the codec driver"
|
||||
config SND_HDA_CODEC_HDMI
|
||||
tristate "Build HDMI/DisplayPort HD-audio codec support"
|
||||
select SND_DYNAMIC_MINORS
|
||||
select SND_PCM_ELD
|
||||
help
|
||||
Say Y or M here to include HDMI and DisplayPort HD-audio codec
|
||||
support in snd-hda-intel driver. This includes all AMD/ATI,
|
||||
|
@ -546,12 +546,10 @@ static void cs35l56_hda_release_firmware_files(const struct firmware *wmfw_firmw
|
||||
const struct firmware *coeff_firmware,
|
||||
char *coeff_filename)
|
||||
{
|
||||
if (wmfw_firmware)
|
||||
release_firmware(wmfw_firmware);
|
||||
release_firmware(wmfw_firmware);
|
||||
kfree(wmfw_filename);
|
||||
|
||||
if (coeff_firmware)
|
||||
release_firmware(coeff_firmware);
|
||||
release_firmware(coeff_firmware);
|
||||
kfree(coeff_filename);
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,9 @@ static void generate_tone(struct hda_beep *beep, int tone)
|
||||
beep->power_hook(beep, true);
|
||||
beep->playing = 1;
|
||||
}
|
||||
snd_hda_codec_write(codec, beep->nid, 0,
|
||||
AC_VERB_SET_BEEP_CONTROL, tone);
|
||||
if (!codec->beep_just_power_on)
|
||||
snd_hda_codec_write(codec, beep->nid, 0,
|
||||
AC_VERB_SET_BEEP_CONTROL, tone);
|
||||
if (!tone && beep->playing) {
|
||||
beep->playing = 0;
|
||||
if (beep->power_hook)
|
||||
@ -212,10 +213,12 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
|
||||
struct hda_beep *beep;
|
||||
int err;
|
||||
|
||||
if (!snd_hda_get_bool_hint(codec, "beep"))
|
||||
return 0; /* disabled explicitly by hints */
|
||||
if (codec->beep_mode == HDA_BEEP_MODE_OFF)
|
||||
return 0; /* disabled by module option */
|
||||
if (!codec->beep_just_power_on) {
|
||||
if (!snd_hda_get_bool_hint(codec, "beep"))
|
||||
return 0; /* disabled explicitly by hints */
|
||||
if (codec->beep_mode == HDA_BEEP_MODE_OFF)
|
||||
return 0; /* disabled by module option */
|
||||
}
|
||||
|
||||
beep = kzalloc(sizeof(*beep), GFP_KERNEL);
|
||||
if (beep == NULL)
|
||||
|
@ -185,7 +185,7 @@ int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name,
|
||||
drv->core.driver.probe = hda_codec_driver_probe;
|
||||
drv->core.driver.remove = hda_codec_driver_remove;
|
||||
drv->core.driver.shutdown = hda_codec_driver_shutdown;
|
||||
drv->core.driver.pm = &hda_codec_driver_pm;
|
||||
drv->core.driver.pm = pm_ptr(&hda_codec_driver_pm);
|
||||
drv->core.type = HDA_DEV_LEGACY;
|
||||
drv->core.match = hda_codec_match;
|
||||
drv->core.unsol_event = hda_codec_unsol_event;
|
||||
|
@ -3039,8 +3039,7 @@ const struct dev_pm_ops hda_codec_driver_pm = {
|
||||
.thaw = pm_sleep_ptr(hda_codec_pm_thaw),
|
||||
.poweroff = pm_sleep_ptr(hda_codec_pm_suspend),
|
||||
.restore = pm_sleep_ptr(hda_codec_pm_restore),
|
||||
.runtime_suspend = pm_ptr(hda_codec_runtime_suspend),
|
||||
.runtime_resume = pm_ptr(hda_codec_runtime_resume),
|
||||
RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
/* suspend the codec at shutdown; called from driver's shutdown callback */
|
||||
|
@ -17,11 +17,6 @@
|
||||
#include <sound/hda_codec.h>
|
||||
#include "hda_local.h"
|
||||
|
||||
enum eld_versions {
|
||||
ELD_VER_CEA_861D = 2,
|
||||
ELD_VER_PARTIAL = 31,
|
||||
};
|
||||
|
||||
enum cea_edid_versions {
|
||||
CEA_EDID_VER_NONE = 0,
|
||||
CEA_EDID_VER_CEA861 = 1,
|
||||
@ -30,95 +25,12 @@ enum cea_edid_versions {
|
||||
CEA_EDID_VER_RESERVED = 4,
|
||||
};
|
||||
|
||||
static const char * const eld_connection_type_names[4] = {
|
||||
"HDMI",
|
||||
"DisplayPort",
|
||||
"2-reserved",
|
||||
"3-reserved"
|
||||
};
|
||||
|
||||
enum cea_audio_coding_types {
|
||||
AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0,
|
||||
AUDIO_CODING_TYPE_LPCM = 1,
|
||||
AUDIO_CODING_TYPE_AC3 = 2,
|
||||
AUDIO_CODING_TYPE_MPEG1 = 3,
|
||||
AUDIO_CODING_TYPE_MP3 = 4,
|
||||
AUDIO_CODING_TYPE_MPEG2 = 5,
|
||||
AUDIO_CODING_TYPE_AACLC = 6,
|
||||
AUDIO_CODING_TYPE_DTS = 7,
|
||||
AUDIO_CODING_TYPE_ATRAC = 8,
|
||||
AUDIO_CODING_TYPE_SACD = 9,
|
||||
AUDIO_CODING_TYPE_EAC3 = 10,
|
||||
AUDIO_CODING_TYPE_DTS_HD = 11,
|
||||
AUDIO_CODING_TYPE_MLP = 12,
|
||||
AUDIO_CODING_TYPE_DST = 13,
|
||||
AUDIO_CODING_TYPE_WMAPRO = 14,
|
||||
AUDIO_CODING_TYPE_REF_CXT = 15,
|
||||
/* also include valid xtypes below */
|
||||
AUDIO_CODING_TYPE_HE_AAC = 15,
|
||||
AUDIO_CODING_TYPE_HE_AAC2 = 16,
|
||||
AUDIO_CODING_TYPE_MPEG_SURROUND = 17,
|
||||
};
|
||||
|
||||
enum cea_audio_coding_xtypes {
|
||||
AUDIO_CODING_XTYPE_HE_REF_CT = 0,
|
||||
AUDIO_CODING_XTYPE_HE_AAC = 1,
|
||||
AUDIO_CODING_XTYPE_HE_AAC2 = 2,
|
||||
AUDIO_CODING_XTYPE_MPEG_SURROUND = 3,
|
||||
AUDIO_CODING_XTYPE_FIRST_RESERVED = 4,
|
||||
};
|
||||
|
||||
static const char * const cea_audio_coding_type_names[] = {
|
||||
/* 0 */ "undefined",
|
||||
/* 1 */ "LPCM",
|
||||
/* 2 */ "AC-3",
|
||||
/* 3 */ "MPEG1",
|
||||
/* 4 */ "MP3",
|
||||
/* 5 */ "MPEG2",
|
||||
/* 6 */ "AAC-LC",
|
||||
/* 7 */ "DTS",
|
||||
/* 8 */ "ATRAC",
|
||||
/* 9 */ "DSD (One Bit Audio)",
|
||||
/* 10 */ "E-AC-3/DD+ (Dolby Digital Plus)",
|
||||
/* 11 */ "DTS-HD",
|
||||
/* 12 */ "MLP (Dolby TrueHD)",
|
||||
/* 13 */ "DST",
|
||||
/* 14 */ "WMAPro",
|
||||
/* 15 */ "HE-AAC",
|
||||
/* 16 */ "HE-AACv2",
|
||||
/* 17 */ "MPEG Surround",
|
||||
};
|
||||
|
||||
/*
|
||||
* The following two lists are shared between
|
||||
* - HDMI audio InfoFrame (source to sink)
|
||||
* - CEA E-EDID Extension (sink to source)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SS1:SS0 index => sample size
|
||||
*/
|
||||
static const int cea_sample_sizes[4] = {
|
||||
0, /* 0: Refer to Stream Header */
|
||||
AC_SUPPCM_BITS_16, /* 1: 16 bits */
|
||||
AC_SUPPCM_BITS_20, /* 2: 20 bits */
|
||||
AC_SUPPCM_BITS_24, /* 3: 24 bits */
|
||||
};
|
||||
|
||||
/*
|
||||
* SF2:SF1:SF0 index => sampling frequency
|
||||
*/
|
||||
static const int cea_sampling_frequencies[8] = {
|
||||
0, /* 0: Refer to Stream Header */
|
||||
SNDRV_PCM_RATE_32000, /* 1: 32000Hz */
|
||||
SNDRV_PCM_RATE_44100, /* 2: 44100Hz */
|
||||
SNDRV_PCM_RATE_48000, /* 3: 48000Hz */
|
||||
SNDRV_PCM_RATE_88200, /* 4: 88200Hz */
|
||||
SNDRV_PCM_RATE_96000, /* 5: 96000Hz */
|
||||
SNDRV_PCM_RATE_176400, /* 6: 176400Hz */
|
||||
SNDRV_PCM_RATE_192000, /* 7: 192000Hz */
|
||||
};
|
||||
|
||||
static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
|
||||
int byte_index)
|
||||
{
|
||||
@ -132,159 +44,6 @@ static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
|
||||
return val;
|
||||
}
|
||||
|
||||
#define GRAB_BITS(buf, byte, lowbit, bits) \
|
||||
({ \
|
||||
BUILD_BUG_ON(lowbit > 7); \
|
||||
BUILD_BUG_ON(bits > 8); \
|
||||
BUILD_BUG_ON(bits <= 0); \
|
||||
\
|
||||
(buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \
|
||||
})
|
||||
|
||||
static void hdmi_update_short_audio_desc(struct hda_codec *codec,
|
||||
struct cea_sad *a,
|
||||
const unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
int val;
|
||||
|
||||
val = GRAB_BITS(buf, 1, 0, 7);
|
||||
a->rates = 0;
|
||||
for (i = 0; i < 7; i++)
|
||||
if (val & (1 << i))
|
||||
a->rates |= cea_sampling_frequencies[i + 1];
|
||||
|
||||
a->channels = GRAB_BITS(buf, 0, 0, 3);
|
||||
a->channels++;
|
||||
|
||||
a->sample_bits = 0;
|
||||
a->max_bitrate = 0;
|
||||
|
||||
a->format = GRAB_BITS(buf, 0, 3, 4);
|
||||
switch (a->format) {
|
||||
case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
|
||||
codec_info(codec, "HDMI: audio coding type 0 not expected\n");
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_LPCM:
|
||||
val = GRAB_BITS(buf, 2, 0, 3);
|
||||
for (i = 0; i < 3; i++)
|
||||
if (val & (1 << i))
|
||||
a->sample_bits |= cea_sample_sizes[i + 1];
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_AC3:
|
||||
case AUDIO_CODING_TYPE_MPEG1:
|
||||
case AUDIO_CODING_TYPE_MP3:
|
||||
case AUDIO_CODING_TYPE_MPEG2:
|
||||
case AUDIO_CODING_TYPE_AACLC:
|
||||
case AUDIO_CODING_TYPE_DTS:
|
||||
case AUDIO_CODING_TYPE_ATRAC:
|
||||
a->max_bitrate = GRAB_BITS(buf, 2, 0, 8);
|
||||
a->max_bitrate *= 8000;
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_SACD:
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_EAC3:
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_DTS_HD:
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_MLP:
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_DST:
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_WMAPRO:
|
||||
a->profile = GRAB_BITS(buf, 2, 0, 3);
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_REF_CXT:
|
||||
a->format = GRAB_BITS(buf, 2, 3, 5);
|
||||
if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
|
||||
a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
|
||||
codec_info(codec,
|
||||
"HDMI: audio coding xtype %d not expected\n",
|
||||
a->format);
|
||||
a->format = 0;
|
||||
} else
|
||||
a->format += AUDIO_CODING_TYPE_HE_AAC -
|
||||
AUDIO_CODING_XTYPE_HE_AAC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Be careful, ELD buf could be totally rubbish!
|
||||
*/
|
||||
int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
|
||||
const unsigned char *buf, int size)
|
||||
{
|
||||
int mnl;
|
||||
int i;
|
||||
|
||||
memset(e, 0, sizeof(*e));
|
||||
e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
|
||||
if (e->eld_ver != ELD_VER_CEA_861D &&
|
||||
e->eld_ver != ELD_VER_PARTIAL) {
|
||||
codec_info(codec, "HDMI: Unknown ELD version %d\n", e->eld_ver);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
e->baseline_len = GRAB_BITS(buf, 2, 0, 8);
|
||||
mnl = GRAB_BITS(buf, 4, 0, 5);
|
||||
e->cea_edid_ver = GRAB_BITS(buf, 4, 5, 3);
|
||||
|
||||
e->support_hdcp = GRAB_BITS(buf, 5, 0, 1);
|
||||
e->support_ai = GRAB_BITS(buf, 5, 1, 1);
|
||||
e->conn_type = GRAB_BITS(buf, 5, 2, 2);
|
||||
e->sad_count = GRAB_BITS(buf, 5, 4, 4);
|
||||
|
||||
e->aud_synch_delay = GRAB_BITS(buf, 6, 0, 8) * 2;
|
||||
e->spk_alloc = GRAB_BITS(buf, 7, 0, 7);
|
||||
|
||||
e->port_id = get_unaligned_le64(buf + 8);
|
||||
|
||||
/* not specified, but the spec's tendency is little endian */
|
||||
e->manufacture_id = get_unaligned_le16(buf + 16);
|
||||
e->product_id = get_unaligned_le16(buf + 18);
|
||||
|
||||
if (mnl > ELD_MAX_MNL) {
|
||||
codec_info(codec, "HDMI: MNL is reserved value %d\n", mnl);
|
||||
goto out_fail;
|
||||
} else if (ELD_FIXED_BYTES + mnl > size) {
|
||||
codec_info(codec, "HDMI: out of range MNL %d\n", mnl);
|
||||
goto out_fail;
|
||||
} else
|
||||
strscpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
|
||||
|
||||
for (i = 0; i < e->sad_count; i++) {
|
||||
if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
|
||||
codec_info(codec, "HDMI: out of range SAD %d\n", i);
|
||||
goto out_fail;
|
||||
}
|
||||
hdmi_update_short_audio_desc(codec, e->sad + i,
|
||||
buf + ELD_FIXED_BYTES + mnl + 3 * i);
|
||||
}
|
||||
|
||||
/*
|
||||
* HDMI sink's ELD info cannot always be retrieved for now, e.g.
|
||||
* in console or for audio devices. Assume the highest speakers
|
||||
* configuration, to _not_ prohibit multi-channel audio playback.
|
||||
*/
|
||||
if (!e->spk_alloc)
|
||||
e->spk_alloc = 0xffff;
|
||||
|
||||
return 0;
|
||||
|
||||
out_fail:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
|
||||
@ -346,155 +105,27 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* SNDRV_PCM_RATE_* and AC_PAR_PCM values don't match, print correct rates with
|
||||
* hdmi-specific routine.
|
||||
*/
|
||||
static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
|
||||
{
|
||||
static const unsigned int alsa_rates[] = {
|
||||
5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
|
||||
88200, 96000, 176400, 192000, 384000
|
||||
};
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++)
|
||||
if (pcm & (1 << i))
|
||||
j += scnprintf(buf + j, buflen - j, " %d",
|
||||
alsa_rates[i]);
|
||||
|
||||
buf[j] = '\0'; /* necessary when j == 0 */
|
||||
}
|
||||
|
||||
#define SND_PRINT_RATES_ADVISED_BUFSIZE 80
|
||||
|
||||
static void hdmi_show_short_audio_desc(struct hda_codec *codec,
|
||||
struct cea_sad *a)
|
||||
{
|
||||
char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
|
||||
char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
|
||||
|
||||
if (!a->format)
|
||||
return;
|
||||
|
||||
hdmi_print_pcm_rates(a->rates, buf, sizeof(buf));
|
||||
|
||||
if (a->format == AUDIO_CODING_TYPE_LPCM)
|
||||
snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2) - 8);
|
||||
else if (a->max_bitrate)
|
||||
snprintf(buf2, sizeof(buf2),
|
||||
", max bitrate = %d", a->max_bitrate);
|
||||
else
|
||||
buf2[0] = '\0';
|
||||
|
||||
codec_dbg(codec,
|
||||
"HDMI: supports coding type %s: channels = %d, rates =%s%s\n",
|
||||
cea_audio_coding_type_names[a->format],
|
||||
a->channels, buf, buf2);
|
||||
}
|
||||
|
||||
void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e)
|
||||
{
|
||||
int i;
|
||||
|
||||
codec_dbg(codec, "HDMI: detected monitor %s at connection type %s\n",
|
||||
e->monitor_name,
|
||||
eld_connection_type_names[e->conn_type]);
|
||||
|
||||
if (e->spk_alloc) {
|
||||
char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
|
||||
snd_hdac_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
|
||||
codec_dbg(codec, "HDMI: available speakers:%s\n", buf);
|
||||
}
|
||||
|
||||
for (i = 0; i < e->sad_count; i++)
|
||||
hdmi_show_short_audio_desc(codec, e->sad + i);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_PROC_FS
|
||||
|
||||
static void hdmi_print_sad_info(int i, struct cea_sad *a,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
|
||||
|
||||
snd_iprintf(buffer, "sad%d_coding_type\t[0x%x] %s\n",
|
||||
i, a->format, cea_audio_coding_type_names[a->format]);
|
||||
snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels);
|
||||
|
||||
hdmi_print_pcm_rates(a->rates, buf, sizeof(buf));
|
||||
snd_iprintf(buffer, "sad%d_rates\t\t[0x%x]%s\n", i, a->rates, buf);
|
||||
|
||||
if (a->format == AUDIO_CODING_TYPE_LPCM) {
|
||||
snd_print_pcm_bits(a->sample_bits, buf, sizeof(buf));
|
||||
snd_iprintf(buffer, "sad%d_bits\t\t[0x%x]%s\n",
|
||||
i, a->sample_bits, buf);
|
||||
}
|
||||
|
||||
if (a->max_bitrate)
|
||||
snd_iprintf(buffer, "sad%d_max_bitrate\t%d\n",
|
||||
i, a->max_bitrate);
|
||||
|
||||
if (a->profile)
|
||||
snd_iprintf(buffer, "sad%d_profile\t\t%d\n", i, a->profile);
|
||||
}
|
||||
|
||||
void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
|
||||
struct snd_info_buffer *buffer,
|
||||
hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid)
|
||||
{
|
||||
struct parsed_hdmi_eld *e = &eld->info;
|
||||
char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
|
||||
int i;
|
||||
static const char * const eld_version_names[32] = {
|
||||
"reserved",
|
||||
"reserved",
|
||||
"CEA-861D or below",
|
||||
[3 ... 30] = "reserved",
|
||||
[31] = "partial"
|
||||
};
|
||||
static const char * const cea_edid_version_names[8] = {
|
||||
"no CEA EDID Timing Extension block present",
|
||||
"CEA-861",
|
||||
"CEA-861-A",
|
||||
"CEA-861-B, C or D",
|
||||
[4 ... 7] = "reserved"
|
||||
};
|
||||
|
||||
snd_iprintf(buffer, "monitor_present\t\t%d\n", eld->monitor_present);
|
||||
snd_iprintf(buffer, "eld_valid\t\t%d\n", eld->eld_valid);
|
||||
snd_iprintf(buffer, "codec_pin_nid\t\t0x%x\n", pin_nid);
|
||||
snd_iprintf(buffer, "codec_dev_id\t\t0x%x\n", dev_id);
|
||||
snd_iprintf(buffer, "codec_cvt_nid\t\t0x%x\n", cvt_nid);
|
||||
|
||||
if (!eld->eld_valid)
|
||||
return;
|
||||
snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
|
||||
snd_iprintf(buffer, "connection_type\t\t%s\n",
|
||||
eld_connection_type_names[e->conn_type]);
|
||||
snd_iprintf(buffer, "eld_version\t\t[0x%x] %s\n", e->eld_ver,
|
||||
eld_version_names[e->eld_ver]);
|
||||
snd_iprintf(buffer, "edid_version\t\t[0x%x] %s\n", e->cea_edid_ver,
|
||||
cea_edid_version_names[e->cea_edid_ver]);
|
||||
snd_iprintf(buffer, "manufacture_id\t\t0x%x\n", e->manufacture_id);
|
||||
snd_iprintf(buffer, "product_id\t\t0x%x\n", e->product_id);
|
||||
snd_iprintf(buffer, "port_id\t\t\t0x%llx\n", (long long)e->port_id);
|
||||
snd_iprintf(buffer, "support_hdcp\t\t%d\n", e->support_hdcp);
|
||||
snd_iprintf(buffer, "support_ai\t\t%d\n", e->support_ai);
|
||||
snd_iprintf(buffer, "audio_sync_delay\t%d\n", e->aud_synch_delay);
|
||||
|
||||
snd_hdac_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
|
||||
snd_iprintf(buffer, "speakers\t\t[0x%x]%s\n", e->spk_alloc, buf);
|
||||
|
||||
snd_iprintf(buffer, "sad_count\t\t%d\n", e->sad_count);
|
||||
|
||||
for (i = 0; i < e->sad_count; i++)
|
||||
hdmi_print_sad_info(i, e->sad + i, buffer);
|
||||
snd_print_eld_info(&eld->info, buffer);
|
||||
}
|
||||
|
||||
void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct parsed_hdmi_eld *e = &eld->info;
|
||||
struct snd_parsed_hdmi_eld *e = &eld->info;
|
||||
char line[64];
|
||||
char name[64];
|
||||
char *sname;
|
||||
@ -556,7 +187,7 @@ void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
|
||||
#endif /* CONFIG_SND_PROC_FS */
|
||||
|
||||
/* update PCM info based on ELD */
|
||||
void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
|
||||
void snd_hdmi_eld_update_pcm_info(struct snd_parsed_hdmi_eld *e,
|
||||
struct hda_pcm_stream *hinfo)
|
||||
{
|
||||
u32 rates;
|
||||
@ -574,17 +205,17 @@ void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
|
||||
maxbps = 16;
|
||||
channels_max = 2;
|
||||
for (i = 0; i < e->sad_count; i++) {
|
||||
struct cea_sad *a = &e->sad[i];
|
||||
struct snd_cea_sad *a = &e->sad[i];
|
||||
rates |= a->rates;
|
||||
if (a->channels > channels_max)
|
||||
channels_max = a->channels;
|
||||
if (a->format == AUDIO_CODING_TYPE_LPCM) {
|
||||
if (a->sample_bits & AC_SUPPCM_BITS_20) {
|
||||
if (a->sample_bits & ELD_PCM_BITS_20) {
|
||||
formats |= SNDRV_PCM_FMTBIT_S32_LE;
|
||||
if (maxbps < 20)
|
||||
maxbps = 20;
|
||||
}
|
||||
if (a->sample_bits & AC_SUPPCM_BITS_24) {
|
||||
if (a->sample_bits & ELD_PCM_BITS_24) {
|
||||
formats |= SNDRV_PCM_FMTBIT_S32_LE;
|
||||
if (maxbps < 24)
|
||||
maxbps = 24;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <linux/completion.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
/* for snoop control */
|
||||
@ -1050,7 +1051,7 @@ static int azx_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused azx_resume(struct device *dev)
|
||||
static int azx_resume(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip;
|
||||
@ -1097,7 +1098,7 @@ static int azx_thaw_noirq(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused azx_runtime_suspend(struct device *dev)
|
||||
static int azx_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip;
|
||||
@ -1114,7 +1115,7 @@ static int __maybe_unused azx_runtime_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused azx_runtime_resume(struct device *dev)
|
||||
static int azx_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip;
|
||||
@ -1131,7 +1132,7 @@ static int __maybe_unused azx_runtime_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused azx_runtime_idle(struct device *dev)
|
||||
static int azx_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip;
|
||||
@ -1162,7 +1163,7 @@ static const struct dev_pm_ops azx_pm = {
|
||||
.complete = pm_sleep_ptr(azx_complete),
|
||||
.freeze_noirq = pm_sleep_ptr(azx_freeze_noirq),
|
||||
.thaw_noirq = pm_sleep_ptr(azx_thaw_noirq),
|
||||
SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, azx_runtime_idle)
|
||||
RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, azx_runtime_idle)
|
||||
};
|
||||
|
||||
|
||||
@ -1352,8 +1353,21 @@ static void azx_free(struct azx *chip)
|
||||
if (use_vga_switcheroo(hda)) {
|
||||
if (chip->disabled && hda->probe_continued)
|
||||
snd_hda_unlock_devices(&chip->bus);
|
||||
if (hda->vga_switcheroo_registered)
|
||||
if (hda->vga_switcheroo_registered) {
|
||||
vga_switcheroo_unregister_client(chip->pci);
|
||||
|
||||
/* Some GPUs don't have sound, and azx_first_init fails,
|
||||
* leaving the device probed but non-functional. As long
|
||||
* as it's probed, the PCI subsystem keeps its runtime
|
||||
* PM status as active. Force it to suspended (as we
|
||||
* actually stop the chip) to allow GPU to suspend via
|
||||
* vga_switcheroo, and print a warning.
|
||||
*/
|
||||
dev_warn(&pci->dev, "GPU sound probed, but not operational: please add a quirk to driver_denylist\n");
|
||||
pm_runtime_disable(&pci->dev);
|
||||
pm_runtime_set_suspended(&pci->dev);
|
||||
pm_runtime_enable(&pci->dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (bus->chip_init) {
|
||||
@ -2061,6 +2075,27 @@ static const struct pci_device_id driver_denylist[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static struct pci_device_id driver_denylist_ideapad_z570[] = {
|
||||
{ PCI_DEVICE_SUB(0x10de, 0x0bea, 0x0000, 0x0000) }, /* NVIDIA GF108 HDA */
|
||||
{}
|
||||
};
|
||||
|
||||
/* DMI-based denylist, to be used when:
|
||||
* - PCI subsystem IDs are zero, impossible to distinguish from valid sound cards.
|
||||
* - Different modifications of the same laptop use different GPU models.
|
||||
*/
|
||||
static const struct dmi_system_id driver_denylist_dmi[] = {
|
||||
{
|
||||
/* No HDA in NVIDIA DGPU. BIOS disables it, but quirk_nvidia_hda() reenables. */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"),
|
||||
},
|
||||
.driver_data = &driver_denylist_ideapad_z570,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct hda_controller_ops pci_hda_ops = {
|
||||
.disable_msi_reset_irq = disable_msi_reset_irq,
|
||||
.position_check = azx_position_check,
|
||||
@ -2071,6 +2106,7 @@ static DECLARE_BITMAP(probed_devs, SNDRV_CARDS);
|
||||
static int azx_probe(struct pci_dev *pci,
|
||||
const struct pci_device_id *pci_id)
|
||||
{
|
||||
const struct dmi_system_id *dmi;
|
||||
struct snd_card *card;
|
||||
struct hda_intel *hda;
|
||||
struct azx *chip;
|
||||
@ -2083,6 +2119,12 @@ static int azx_probe(struct pci_dev *pci,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dmi = dmi_first_match(driver_denylist_dmi);
|
||||
if (dmi && pci_match_id(dmi->driver_data, pci)) {
|
||||
dev_info(&pci->dev, "Skipping the device on the DMI denylist\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev = find_first_zero_bit(probed_devs, SNDRV_CARDS);
|
||||
if (dev >= SNDRV_CARDS)
|
||||
return -ENODEV;
|
||||
@ -2757,7 +2799,7 @@ static struct pci_driver azx_driver = {
|
||||
.remove = azx_remove,
|
||||
.shutdown = azx_shutdown,
|
||||
.driver = {
|
||||
.pm = &azx_pm,
|
||||
.pm = pm_ptr(&azx_pm),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
#ifndef __SOUND_HDA_LOCAL_H
|
||||
#define __SOUND_HDA_LOCAL_H
|
||||
|
||||
#include <sound/pcm_drm_eld.h>
|
||||
|
||||
/* We abuse kcontrol_new.subdev field to pass the NID corresponding to
|
||||
* the given new control. If id.subdev has a bit flag HDA_SUBDEV_NID_FLAG,
|
||||
* snd_hda_ctl_add() takes the lower-bit subdev value as a valid NID.
|
||||
@ -675,61 +677,18 @@ int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
|
||||
#define snd_hda_enum_bool_helper_info(kcontrol, uinfo) \
|
||||
snd_hda_enum_helper_info(kcontrol, uinfo, 0, NULL)
|
||||
|
||||
/*
|
||||
* CEA Short Audio Descriptor data
|
||||
*/
|
||||
struct cea_sad {
|
||||
int channels;
|
||||
int format; /* (format == 0) indicates invalid SAD */
|
||||
int rates;
|
||||
int sample_bits; /* for LPCM */
|
||||
int max_bitrate; /* for AC3...ATRAC */
|
||||
int profile; /* for WMAPRO */
|
||||
};
|
||||
|
||||
#define ELD_FIXED_BYTES 20
|
||||
#define ELD_MAX_SIZE 256
|
||||
#define ELD_MAX_MNL 16
|
||||
#define ELD_MAX_SAD 16
|
||||
|
||||
/*
|
||||
* ELD: EDID Like Data
|
||||
*/
|
||||
struct parsed_hdmi_eld {
|
||||
/*
|
||||
* all fields will be cleared before updating ELD
|
||||
*/
|
||||
int baseline_len;
|
||||
int eld_ver;
|
||||
int cea_edid_ver;
|
||||
char monitor_name[ELD_MAX_MNL + 1];
|
||||
int manufacture_id;
|
||||
int product_id;
|
||||
u64 port_id;
|
||||
int support_hdcp;
|
||||
int support_ai;
|
||||
int conn_type;
|
||||
int aud_synch_delay;
|
||||
int spk_alloc;
|
||||
int sad_count;
|
||||
struct cea_sad sad[ELD_MAX_SAD];
|
||||
};
|
||||
|
||||
struct hdmi_eld {
|
||||
bool monitor_present;
|
||||
bool eld_valid;
|
||||
int eld_size;
|
||||
char eld_buffer[ELD_MAX_SIZE];
|
||||
struct parsed_hdmi_eld info;
|
||||
struct snd_parsed_hdmi_eld info;
|
||||
};
|
||||
|
||||
int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
|
||||
int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned char *buf, int *eld_size);
|
||||
int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
|
||||
const unsigned char *buf, int size);
|
||||
void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e);
|
||||
void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
|
||||
void snd_hdmi_eld_update_pcm_info(struct snd_parsed_hdmi_eld *e,
|
||||
struct hda_pcm_stream *hinfo);
|
||||
|
||||
int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid,
|
||||
|
@ -125,7 +125,7 @@ static void hda_tegra_init(struct hda_tegra *hda)
|
||||
/*
|
||||
* power management
|
||||
*/
|
||||
static int __maybe_unused hda_tegra_suspend(struct device *dev)
|
||||
static int hda_tegra_suspend(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
int rc;
|
||||
@ -138,7 +138,7 @@ static int __maybe_unused hda_tegra_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused hda_tegra_resume(struct device *dev)
|
||||
static int hda_tegra_resume(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
int rc;
|
||||
@ -151,7 +151,7 @@ static int __maybe_unused hda_tegra_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused hda_tegra_runtime_suspend(struct device *dev)
|
||||
static int hda_tegra_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip = card->private_data;
|
||||
@ -170,7 +170,7 @@ static int __maybe_unused hda_tegra_runtime_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused hda_tegra_runtime_resume(struct device *dev)
|
||||
static int hda_tegra_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip = card->private_data;
|
||||
@ -204,10 +204,8 @@ static int __maybe_unused hda_tegra_runtime_resume(struct device *dev)
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops hda_tegra_pm = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
|
||||
SET_RUNTIME_PM_OPS(hda_tegra_runtime_suspend,
|
||||
hda_tegra_runtime_resume,
|
||||
NULL)
|
||||
SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
|
||||
RUNTIME_PM_OPS(hda_tegra_runtime_suspend, hda_tegra_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static int hda_tegra_dev_disconnect(struct snd_device *device)
|
||||
@ -602,7 +600,7 @@ static void hda_tegra_shutdown(struct platform_device *pdev)
|
||||
static struct platform_driver tegra_platform_hda = {
|
||||
.driver = {
|
||||
.name = "tegra-hda",
|
||||
.pm = &hda_tegra_pm,
|
||||
.pm = pm_ptr(&hda_tegra_pm),
|
||||
.of_match_table = hda_tegra_match,
|
||||
},
|
||||
.probe = hda_tegra_probe,
|
||||
|
@ -1511,8 +1511,8 @@ static void update_eld(struct hda_codec *codec,
|
||||
|
||||
if (eld->eld_valid) {
|
||||
if (eld->eld_size <= 0 ||
|
||||
snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer,
|
||||
eld->eld_size) < 0) {
|
||||
snd_parse_eld(hda_codec_dev(codec), &eld->info,
|
||||
eld->eld_buffer, eld->eld_size) < 0) {
|
||||
eld->eld_valid = false;
|
||||
if (repoll) {
|
||||
schedule_delayed_work(&per_pin->work,
|
||||
@ -1555,7 +1555,7 @@ static void update_eld(struct hda_codec *codec,
|
||||
pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
|
||||
if (eld->eld_valid)
|
||||
snd_hdmi_show_eld(codec, &eld->info);
|
||||
snd_show_eld(hda_codec_dev(codec), &eld->info);
|
||||
|
||||
eld_changed = (pin_eld->eld_valid != eld->eld_valid);
|
||||
eld_changed |= (pin_eld->monitor_present != eld->monitor_present);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <sound/hda_codec.h>
|
||||
#include "hda_local.h"
|
||||
#include "hda_auto_parser.h"
|
||||
#include "hda_beep.h"
|
||||
#include "hda_jack.h"
|
||||
#include "hda_generic.h"
|
||||
#include "hda_component.h"
|
||||
@ -586,6 +587,9 @@ static void alc_shutup_pins(struct hda_codec *codec)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
if (spec->no_shutup_pins)
|
||||
return;
|
||||
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
@ -601,8 +605,7 @@ static void alc_shutup_pins(struct hda_codec *codec)
|
||||
alc_headset_mic_no_shutup(codec);
|
||||
break;
|
||||
default:
|
||||
if (!spec->no_shutup_pins)
|
||||
snd_hda_shutup_pins(codec);
|
||||
snd_hda_shutup_pins(codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -7016,6 +7019,30 @@ static void alc285_fixup_hp_envy_x360(struct hda_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
static void alc285_fixup_hp_beep(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||
codec->beep_just_power_on = true;
|
||||
} else if (action == HDA_FIXUP_ACT_INIT) {
|
||||
#ifdef CONFIG_SND_HDA_INPUT_BEEP
|
||||
/*
|
||||
* Just enable loopback to internal speaker and headphone jack.
|
||||
* Disable amplification to get about the same beep volume as
|
||||
* was on pure BIOS setup before loading the driver.
|
||||
*/
|
||||
alc_update_coef_idx(codec, 0x36, 0x7070, BIT(13));
|
||||
|
||||
snd_hda_enable_beep_device(codec, 1);
|
||||
|
||||
#if !IS_ENABLED(CONFIG_INPUT_PCSPKR)
|
||||
dev_warn_once(hda_codec_dev(codec),
|
||||
"enable CONFIG_INPUT_PCSPKR to get PC beeps\n");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* for hda_fixup_thinkpad_acpi() */
|
||||
#include "thinkpad_helper.c"
|
||||
|
||||
@ -7801,6 +7828,7 @@ enum {
|
||||
ALC285_FIXUP_HP_GPIO_LED,
|
||||
ALC285_FIXUP_HP_MUTE_LED,
|
||||
ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED,
|
||||
ALC285_FIXUP_HP_BEEP_MICMUTE_LED,
|
||||
ALC236_FIXUP_HP_MUTE_LED_COEFBIT2,
|
||||
ALC236_FIXUP_HP_GPIO_LED,
|
||||
ALC236_FIXUP_HP_MUTE_LED,
|
||||
@ -9395,6 +9423,12 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_hp_spectre_x360_mute_led,
|
||||
},
|
||||
[ALC285_FIXUP_HP_BEEP_MICMUTE_LED] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_hp_beep,
|
||||
.chained = true,
|
||||
.chain_id = ALC285_FIXUP_HP_MUTE_LED,
|
||||
},
|
||||
[ALC236_FIXUP_HP_MUTE_LED_COEFBIT2] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc236_fixup_hp_mute_led_coefbit2,
|
||||
@ -10489,7 +10523,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x8730, "HP ProBook 445 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x8735, "HP ProBook 435 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8760, "HP EliteBook 8{4,5}5 G7", ALC285_FIXUP_HP_BEEP_MICMUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x876e, "HP ENVY x360 Convertible 13-ay0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
|
||||
SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),
|
||||
@ -10519,6 +10553,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x8811, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
|
||||
SND_PCI_QUIRK(0x103c, 0x8812, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
|
||||
SND_PCI_QUIRK(0x103c, 0x881d, "HP 250 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x881e, "HP Laptop 15s-du3xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8847, "HP EliteBook x360 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x884b, "HP EliteBook 840 Aero G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
||||
@ -10688,17 +10723,54 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d01, "HP ZBook Power 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d84, "HP EliteBook X G1i", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d85, "HP EliteBook 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d86, "HP Elite X360 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d8c, "HP EliteBook 13 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d8d, "HP Elite X360 13 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d8e, "HP EliteBook 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d8f, "HP EliteBook 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d90, "HP EliteBook 16 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d91, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d92, "HP ZBook Firefly 16 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d9b, "HP 17 Turbine OmniBook 7 UMA", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d9c, "HP 17 Turbine OmniBook 7 DIS", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d9d, "HP 17 Turbine OmniBook X UMA", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d9e, "HP 17 Turbine OmniBook X DIS", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d9f, "HP 14 Cadet (x360)", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8da0, "HP 16 Clipper OmniBook 7(X360)", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8da1, "HP 16 Clipper OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8da7, "HP 14 Enstrom OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8da8, "HP 16 Piston OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8de8, "HP Gemtree", ALC245_FIXUP_TAS2781_SPI_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8de9, "HP Gemtree", ALC245_FIXUP_TAS2781_SPI_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8dec, "HP EliteBook 640 G12", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8dee, "HP EliteBook 660 G12", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8df0, "HP EliteBook 630 G12", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8dfc, "HP EliteBook 645 G12", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8dfe, "HP EliteBook 665 G12", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e11, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e12, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e13, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e14, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e15, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e16, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e17, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e18, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e19, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e1a, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e1b, "HP EliteBook G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e1c, "HP EliteBook G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e2c, "HP EliteBook 16 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e36, "HP 14 Enstrom OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e37, "HP 16 Piston OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e60, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e61, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e62, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
|
||||
SND_PCI_QUIRK(0x1043, 0x1054, "ASUS G614FH/FM/FP", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1043, 0x106f, "ASUS VivoBook X515UA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1074, "ASUS G614PH/PM/PP", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x10a1, "ASUS UX391UA", ALC294_FIXUP_ASUS_SPK),
|
||||
SND_PCI_QUIRK(0x1043, 0x10a4, "ASUS TP3407SA", ALC287_FIXUP_TAS2781_I2C),
|
||||
@ -10783,6 +10855,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x1df3, "ASUS UM5606WA", ALC294_FIXUP_BASS_SPEAKER_15),
|
||||
SND_PCI_QUIRK(0x1043, 0x1264, "ASUS UM5606KA", ALC294_FIXUP_BASS_SPEAKER_15),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
|
@ -88,7 +88,6 @@ struct tasdevice_priv {
|
||||
struct mutex codec_lock;
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
struct tm tm;
|
||||
|
||||
unsigned char crc8_lkp_tbl[CRC8_TABLE_SIZE];
|
||||
unsigned char coef_binaryname[64];
|
||||
|
@ -45,7 +45,7 @@
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_range, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xreg, .shift = xshift, \
|
||||
@ -594,7 +594,6 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
|
||||
efi_guid_t efi_guid = EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d,
|
||||
0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3);
|
||||
static efi_char16_t efi_name[] = L"CALI_DATA";
|
||||
struct tm *tm = &tas_priv->tm;
|
||||
unsigned int attr, crc;
|
||||
unsigned int *tmp_val;
|
||||
efi_status_t status;
|
||||
@ -629,10 +628,9 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
|
||||
crc, tmp_val[21]);
|
||||
|
||||
if (crc == tmp_val[21]) {
|
||||
time64_to_tm(tmp_val[20], 0, tm);
|
||||
dev_dbg(tas_priv->dev, "%4ld-%2d-%2d, %2d:%2d:%2d\n",
|
||||
tm->tm_year, tm->tm_mon, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
time64_t seconds = tmp_val[20];
|
||||
|
||||
dev_dbg(tas_priv->dev, "%ptTsr\n", &seconds);
|
||||
tasdevice_apply_calibration(tas_priv);
|
||||
} else
|
||||
tas_priv->cali_data.total_sz = 0;
|
||||
@ -755,8 +753,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
|
||||
|
||||
out:
|
||||
mutex_unlock(&tas_hda->priv->codec_lock);
|
||||
if (fmw)
|
||||
release_firmware(fmw);
|
||||
release_firmware(fmw);
|
||||
pm_runtime_mark_last_busy(tas_hda->dev);
|
||||
pm_runtime_put_autosuspend(tas_hda->dev);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_range, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) { \
|
||||
.reg = xreg, .rreg = xreg, \
|
||||
@ -802,7 +802,6 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
|
||||
static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME;
|
||||
unsigned char data[TASDEVICE_CALIBRATION_DATA_SIZE], *buf;
|
||||
unsigned int attr, crc, offset, *tmp_val;
|
||||
struct tm *tm = &tas_priv->tm;
|
||||
unsigned long total_sz = 0;
|
||||
efi_status_t status;
|
||||
|
||||
@ -849,7 +848,6 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
|
||||
if (crc != tmp_val[3 + tmp_val[1] * 6])
|
||||
return 0;
|
||||
|
||||
time64_to_tm(tmp_val[2], 0, tm);
|
||||
for (int j = 0; j < tmp_val[1]; j++) {
|
||||
offset = j * 6 + 3;
|
||||
if (tmp_val[offset] == tas_priv->index) {
|
||||
@ -882,7 +880,6 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
|
||||
*/
|
||||
crc = crc32(~0, data, 84) ^ ~0;
|
||||
if (crc == tmp_val[21]) {
|
||||
time64_to_tm(tmp_val[20], 0, tm);
|
||||
for (int i = 0; i < CALIB_MAX; i++)
|
||||
tas_priv->cali_data[i] =
|
||||
tmp_val[tas_priv->index * 5 + i];
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// TAS2781 HDA SPI driver
|
||||
//
|
||||
// Copyright 2024-2025 Texas Instruments, Inc.
|
||||
// Copyright 2024 - 2025 Texas Instruments, Inc.
|
||||
//
|
||||
// Author: Baojun Xu <baojun.xu@ti.com>
|
||||
|
||||
@ -370,10 +370,10 @@ static unsigned char map_dev_idx(struct tasdevice_fw *tas_fmw,
|
||||
int i, n = ARRAY_SIZE(non_ppc3_mapping_table);
|
||||
unsigned char dev_idx = 0;
|
||||
|
||||
if (fw_fixed_hdr->ppcver >= PPC3_VERSION_TAS2781) {
|
||||
if (fw_fixed_hdr->ppcver >= PPC3_VERSION_TAS2781_BASIC_MIN) {
|
||||
p = (struct blktyp_devidx_map *)ppc3_tas2781_mapping_table;
|
||||
n = ARRAY_SIZE(ppc3_tas2781_mapping_table);
|
||||
} else if (fw_fixed_hdr->ppcver >= PPC3_VERSION) {
|
||||
} else if (fw_fixed_hdr->ppcver >= PPC3_VERSION_BASE) {
|
||||
p = (struct blktyp_devidx_map *)ppc3_mapping_table;
|
||||
n = ARRAY_SIZE(ppc3_mapping_table);
|
||||
}
|
||||
@ -1605,7 +1605,7 @@ static int dspfw_default_callback(struct tasdevice_priv *tas_priv,
|
||||
int rc = 0;
|
||||
|
||||
if (drv_ver == 0x100) {
|
||||
if (ppcver >= PPC3_VERSION) {
|
||||
if (ppcver >= PPC3_VERSION_BASE) {
|
||||
tas_priv->fw_parse_variable_header =
|
||||
fw_parse_variable_header_kernel;
|
||||
tas_priv->fw_parse_program_data =
|
||||
|
@ -499,8 +499,6 @@ int lola_init_mixer_widget(struct lola *chip, int nid);
|
||||
void lola_free_mixer(struct lola *chip);
|
||||
int lola_create_mixer(struct lola *chip);
|
||||
int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute);
|
||||
void lola_save_mixer(struct lola *chip);
|
||||
void lola_restore_mixer(struct lola *chip);
|
||||
int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update);
|
||||
|
||||
/* proc */
|
||||
|
@ -336,49 +336,6 @@ int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute)
|
||||
return lola_codec_flush(chip);
|
||||
}
|
||||
|
||||
void lola_save_mixer(struct lola *chip)
|
||||
{
|
||||
/* mute analog output */
|
||||
if (chip->mixer.array_saved) {
|
||||
/* store contents of mixer array */
|
||||
memcpy_fromio(chip->mixer.array_saved, chip->mixer.array,
|
||||
sizeof(*chip->mixer.array));
|
||||
}
|
||||
lola_setup_all_analog_gains(chip, PLAY, true); /* output mute */
|
||||
}
|
||||
|
||||
void lola_restore_mixer(struct lola *chip)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*lola_reset_setups(chip);*/
|
||||
if (chip->mixer.array_saved) {
|
||||
/* restore contents of mixer array */
|
||||
memcpy_toio(chip->mixer.array, chip->mixer.array_saved,
|
||||
sizeof(*chip->mixer.array));
|
||||
/* inform micro-controller about all restored values
|
||||
* and ignore return values
|
||||
*/
|
||||
for (i = 0; i < chip->mixer.src_phys_ins; i++)
|
||||
lola_codec_write(chip, chip->mixer.nid,
|
||||
LOLA_VERB_SET_SOURCE_GAIN,
|
||||
i, 0);
|
||||
for (i = 0; i < chip->mixer.src_stream_outs; i++)
|
||||
lola_codec_write(chip, chip->mixer.nid,
|
||||
LOLA_VERB_SET_SOURCE_GAIN,
|
||||
chip->mixer.src_stream_out_ofs + i, 0);
|
||||
for (i = 0; i < chip->mixer.dest_stream_ins; i++)
|
||||
lola_codec_write(chip, chip->mixer.nid,
|
||||
LOLA_VERB_SET_DESTINATION_GAIN,
|
||||
i, 0);
|
||||
for (i = 0; i < chip->mixer.dest_phys_outs; i++)
|
||||
lola_codec_write(chip, chip->mixer.nid,
|
||||
LOLA_VERB_SET_DESTINATION_GAIN,
|
||||
chip->mixer.dest_phys_out_ofs + i, 0);
|
||||
lola_codec_flush(chip);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
|
@ -854,11 +854,9 @@ static struct pci_driver oxygen_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = oxygen_ids,
|
||||
.probe = generic_oxygen_probe,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.driver = {
|
||||
.pm = &oxygen_pci_pm,
|
||||
.pm = pm_sleep_ptr(&oxygen_pci_pm),
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
module_pci_driver(oxygen_driver);
|
||||
|
@ -161,9 +161,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
|
||||
const struct pci_device_id *id
|
||||
)
|
||||
);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
extern const struct dev_pm_ops oxygen_pci_pm;
|
||||
#endif
|
||||
void oxygen_pci_shutdown(struct pci_dev *pci);
|
||||
|
||||
/* oxygen_mixer.c */
|
||||
|
@ -713,7 +713,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
|
||||
}
|
||||
EXPORT_SYMBOL(oxygen_pci_probe);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int oxygen_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
@ -789,9 +788,7 @@ static int oxygen_pci_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SIMPLE_DEV_PM_OPS(oxygen_pci_pm, oxygen_pci_suspend, oxygen_pci_resume);
|
||||
EXPORT_SYMBOL(oxygen_pci_pm);
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
EXPORT_SIMPLE_DEV_PM_OPS(oxygen_pci_pm, oxygen_pci_suspend, oxygen_pci_resume);
|
||||
|
||||
void oxygen_pci_shutdown(struct pci_dev *pci)
|
||||
{
|
||||
|
@ -137,11 +137,9 @@ static struct pci_driver se6x_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = se6x_ids,
|
||||
.probe = se6x_probe,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.driver = {
|
||||
.pm = &oxygen_pci_pm,
|
||||
.pm = pm_sleep_ptr(&oxygen_pci_pm),
|
||||
},
|
||||
#endif
|
||||
.shutdown = oxygen_pci_shutdown,
|
||||
};
|
||||
|
||||
|
@ -82,11 +82,9 @@ static struct pci_driver xonar_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = xonar_ids,
|
||||
.probe = xonar_probe,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.driver = {
|
||||
.pm = &oxygen_pci_pm,
|
||||
.pm = pm_sleep_ptr(&oxygen_pci_pm),
|
||||
},
|
||||
#endif
|
||||
.shutdown = oxygen_pci_shutdown,
|
||||
};
|
||||
|
||||
|
@ -204,7 +204,6 @@ static int snd_vx222_probe(struct pci_dev *pci,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int snd_vx222_suspend(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
@ -221,18 +220,14 @@ static int snd_vx222_resume(struct device *dev)
|
||||
return snd_vx_resume(&vx->core);
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(snd_vx222_pm, snd_vx222_suspend, snd_vx222_resume);
|
||||
#define SND_VX222_PM_OPS &snd_vx222_pm
|
||||
#else
|
||||
#define SND_VX222_PM_OPS NULL
|
||||
#endif
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(snd_vx222_pm, snd_vx222_suspend, snd_vx222_resume);
|
||||
|
||||
static struct pci_driver vx222_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = snd_vx222_ids,
|
||||
.probe = snd_vx222_probe,
|
||||
.driver = {
|
||||
.pm = SND_VX222_PM_OPS,
|
||||
.pm = pm_ptr(&snd_vx222_pm),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -81,6 +81,13 @@ config SND_SOC_UTILS_KUNIT_TEST
|
||||
help
|
||||
If you want to perform tests on ALSA SoC utils library say Y here.
|
||||
|
||||
config SND_SOC_OPS_KUNIT_TEST
|
||||
tristate "KUnit tests for SoC ops"
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
If you want to perform tests on ALSA SoC ops library say Y here.
|
||||
|
||||
config SND_SOC_ACPI
|
||||
tristate
|
||||
|
||||
|
@ -21,6 +21,10 @@ ifneq ($(CONFIG_SND_SOC_UTILS_KUNIT_TEST),)
|
||||
obj-$(CONFIG_SND_SOC_UTILS_KUNIT_TEST) += soc-utils-test.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_SND_SOC_OPS_KUNIT_TEST),)
|
||||
obj-$(CONFIG_SND_SOC_OPS_KUNIT_TEST) += soc-ops-test.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
|
||||
snd-soc-core-y += soc-generic-dmaengine-pcm.o
|
||||
endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user