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:
@@ -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
Reference in New Issue
Block a user