sound updates for 6.15-rc1

We've received lots of commits at this time, as a result of various
 cleanup and refactoring works as well as a few new drivers and the
 generic SoundWire support.  Most of changes are device-specific,
 little about the core changes.  Some highlights below:
 
 Core:
 * A couple of (rather minor) race fixes in ALSA sequencer code
 * A regression fix in ALSA timer code that may lead to a deadlock
 
 ASoC:
 * A large series of code conversion to use modern terminology for the
   clocking configuration
 * Conversions of PM ops with the modern macros in all ASoC drivers
 * Clarification of the control operations
 * Prepartory work for more generic SoundWire SCDA controls
 * Support for AMD ACP 7.x, AWINC WM88166, Everest ES8388, Intel AVS
   PEAKVOL and GAIN DSP modules Mediatek MT8188 DMIC, NXP i.MX95,
   nVidia Tegra interconnects, Rockchip RK3588 S/PDIF, Texas
   Instruments SN012776 and TAS5770L, and Wolfson WM8904 DMICs
 
 Others:
 * Conversions of PM ops with the modern macros in the rest drivers
 * USB-audio quirks and fixes for Presonus Studio, DJM-A9, CME
 * HD-audio quirks and fixes ASUS, HP, Lenovo, and others
 
 Note that the PR contains some changes from the tip tree for AMD code,
 and it might give some merge conflict due to the rebase afterwards.
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmfi3o0OHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE+mhQ//QPp4w4pegFco3//6lc6tTX1n61Ab8m9Vl1CF
 ALPN/zI7tkaI8S3cVNA3uXlzWSdmYzJOHvy8LrUAWG4e/cPQqTy9+oyZjnVrIthL
 lszAIh51fR7whtKabBQADdHzBPSPWwX5HmeiBlBP8TriCtM5wprZ4Wi8gaVrPw2G
 u4JqpRCpFQGf2S4WGnVGvV/7fyRM+R9LUhAX7BAFmSdtoz4oyg3Mt8R3MdAQkNOi
 eHX1n342b06UG9MRjv258RSW+ilf1ccPdMRVCayuVt789lgUUdo9DKhQiM6vPlT9
 FHtCbLGXkaYwxOsRuWGkPiRxc2xPLtvuSLhmiTomR1va/FnH+VW0Ghk5cwg0i31U
 mBNqdtgxYglb6Vp41OYRCImRa3dhFjR/SIHN1OokQpkzY4vsl1nu1kDXxHQttc9d
 qfXwWmviFN/Wg8hXFsEeGo26ISU+GQAmZksKfvF3YHJy/kz/amS8zSXDmUgL5WD9
 ttK25orLxptZ80sRVTywoPH25b8H4wgwRLdwvYCPqOLx8jv7V86n32gudWAibBz5
 Yua0TmWxd2r2LZVt3TdJgAhJSHXCDTdoybcwGoDn1p+jDRqcJDCpyL23TH+eAQUg
 whqQRTYVH/E/Cd1V2oATxeLwUsILkUOiHXqc7s12KMdU1rmL/S/rsASDuumxow7V
 viUoVAM=
 =NaAN
 -----END PGP SIGNATURE-----

Merge tag 'sound-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound updates from Takashi Iwai:
 "We've received lots of commits at this time, as a result of various
  cleanup and refactoring works as well as a few new drivers and the
  generic SoundWire support. Most of changes are device-specific, little
  about the core changes. Some highlights below:

  Core:
   - A couple of (rather minor) race fixes in ALSA sequencer code
   - A regression fix in ALSA timer code that may lead to a deadlock

  ASoC:
   - A large series of code conversion to use modern terminology for the
     clocking configuration
   - Conversions of PM ops with the modern macros in all ASoC drivers
   - Clarification of the control operations
   - Prepartory work for more generic SoundWire SCDA controls
   - Support for AMD ACP 7.x, AWINC WM88166, Everest ES8388, Intel AVS
     PEAKVOL and GAIN DSP modules Mediatek MT8188 DMIC, NXP i.MX95,
     nVidia Tegra interconnects, Rockchip RK3588 S/PDIF, Texas
     Instruments SN012776 and TAS5770L, and Wolfson WM8904 DMICs

  Others:
   - Conversions of PM ops with the modern macros in the rest drivers
   - USB-audio quirks and fixes for Presonus Studio, DJM-A9, CME
   - HD-audio quirks and fixes ASUS, HP, Lenovo, and others"

* tag 'sound-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (651 commits)
  ALSA: hda: tas2781-i2c: Remove unnecessary NULL check before release_firmware()
  ALSA: hda: cs35l56: Remove unnecessary NULL check before release_firmware()
  ALSA: hda/realtek: Bass speaker fixup for ASUS UM5606KA
  ALSA: hda/realtek: Fix built-in mic assignment on ASUS VivoBook X515UA
  ALSA: hda/realtek: Add support for various HP Laptops using CS35L41 HDA
  ALSA: timer: Don't take register_mutex with copy_from/to_user()
  ASoC: SDCA: Correct handling of selected mode DisCo property
  ASoC: amd: yc: update quirk data for new Lenovo model
  ALSA: hda/realtek: fix micmute LEDs on HP Laptops with ALC3247
  ALSA: hda/realtek: fix micmute LEDs on HP Laptops with ALC3315
  ASoC: SOF: mediatek: Commonize duplicated functions
  ASoC: dmic: Fix NULL pointer dereference
  ASoC: wm8904: add DMIC support
  ASoC: wm8904: get platform data from DT
  ASoC: dt-bindings: wm8904: Add DMIC, GPIO, MIC and EQ support
  ASoC: wm8904: Don't touch GPIO configs set to 0xFFFF
  of: Add of_property_read_u16_index
  ALSA: oxygen: Fix dependency on CONFIG_PM_SLEEP
  ASoC: ops: Apply platform_max after deciding control type
  ASoC: ops: Remove some unnecessary local variables
  ...
This commit is contained in:
Linus Torvalds 2025-03-26 09:41:55 -07:00
commit e50da555ca
610 changed files with 19605 additions and 8594 deletions

View File

@ -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 {

View File

@ -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>;
};

View File

@ -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:

View 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";
};

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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

View File

@ -19,6 +19,7 @@ properties:
enum:
- awinic,aw88081
- awinic,aw88083
- awinic,aw88166
- awinic,aw88261
- awinic,aw88395
- awinic,aw88399

View File

@ -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

View File

@ -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

View File

@ -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>;
};
};
};
};

View File

@ -80,7 +80,10 @@ required:
- fsl,asrc-rate
- fsl,asrc-format
additionalProperties: false
allOf:
- $ref: dai-common.yaml#
unevaluatedProperties: false
examples:
- |

View File

@ -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>;
};
};
};

View File

@ -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>;
};
};
};

View File

@ -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>;
};
};
};
};

View 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

View File

@ -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:

View File

@ -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.

View File

@ -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>;
};
};

View File

@ -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

View File

@ -23,6 +23,7 @@ properties:
compatible:
enum:
- ti,tas2770
- ti,tas5770l # Apple variant
reg:
maxItems: 1

View File

@ -24,6 +24,7 @@ properties:
enum:
- ti,tas2764
- ti,tas2780
- ti,sn012776 # Apple variant of TAS2764
reg:
maxItems: 1

View File

@ -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 = <&reg_1p8v>;
DCVDD-supply = <&reg_1p8v>;
MICVDD-supply = <&reg_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>;
};
};

View File

@ -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

View File

@ -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>;
};

View File

@ -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>;
};
...

View File

@ -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>;
};

View 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>;
};
...

View File

@ -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>;
};

View 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>;
};
...

View File

@ -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
------------------

View File

@ -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,

View File

@ -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,

View File

@ -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,
}

View File

@ -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>

View File

@ -21,6 +21,37 @@ static const struct regcache_ops *cache_types[] = {
&regcache_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;

View File

@ -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,

View File

@ -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,

View File

@ -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.
*

View File

@ -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 = {

View 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

View File

@ -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)
{

View File

@ -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");

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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

View 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__

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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 */
/*

View File

@ -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;
};

View File

@ -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);

View File

@ -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];
};

View File

@ -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,

View File

@ -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,
};

View File

@ -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,

View File

@ -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,
},
};

View File

@ -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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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)(&register_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, &register_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)(&register_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, &register_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)(&register_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, &register_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,

View 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)
{

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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,

View File

@ -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);
}

View File

@ -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)

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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),
},
};

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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),

View File

@ -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];

View File

@ -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);
}

View File

@ -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];

View File

@ -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 =

View File

@ -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 */

View File

@ -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);
}
}
/*
*/

View File

@ -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);

View File

@ -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 */

View File

@ -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)
{

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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),
},
};

View File

@ -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

View File

@ -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