sound updates for 7.0-rc1

It's been relatively calm for a new era; majority of changes are for
 ASoC, mostly device-specific changes, while there are a bit of
 cleanups in core stuff.  A few SPI API and regmap updates are included
 to be used by sound drivers, too.
 
 Core:
 - A few trivial cleanups about __free() and runtime PM macros
 - Convert to new snd_seq_bus binding
 
 ASoC:
 - Generic SDCA support for reporting jack events
 - Continuing platform support, cleanup and feature improvements for
   AMD, Intel, Qualcomm and SOF code
 - Platform description improvements for the Cirrus drivers
 - Support for NXP i.MX952, Realtek RT1320 and RT5575, and Sophogo
   CV1800B
 
 HD- and USB-audio:
 - Many quirks as usual
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmmLT6wOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE8pNA/+OW1DA4II37keAClezQ6Z5O88MPO0ETx6DFgO
 yT1fWWiqaSzETdxMHVkviiagoeeE96wN8mM/B2Vvljd+KL0L+z+dEATZgct1w2xQ
 toWB78eOvFlVv51oYxrHhVCWHpFtC5SEi7Ize8FmR/NaaRd2aBNlAz9n88fvR3Bg
 ApfGFsufEYqDPCfQG002r4skcKaqrOMabhd/RSwp4MrTZkG/O2h95BUHuF2EEUHr
 j0MayB0n77Dav6PxfgayNcxjAEPi9tu8T9mP3HO3Z8AtGyaTLZPPf4Y3MBybTmIU
 7CBiDQJy9a6vd7qhfMtr0tNwVNXZOOjRkzDl0HRDqKkw08ftybKTZBmP/dFmCNAp
 f/0os6ue4Sl/lh1KXAW8wqyN8i/0Y5SCNvb1FOuGQwg8CWAqC+7jfIyFrQVgGsTj
 fOsvpH3DmU0dGxVwJYiIBXCVNS8/TGF5vw9URyh0vm3LXH7AHn9e+IB7QlYvAOFR
 Vis81OTO3QbjQn5Ig4+7vDkj6ywjLApX5kx6GiVMUisKJ54YX8RHC0HBZcOeyavy
 Qfe/VMHcFmWKNLhRRUaKdsZwZMuig/RTrJfCp2eLGnEVHyPM+/5ECjRSzCcL5I4t
 +jFJkhjEryqWtWk1Vmxz4gCyqoGsdSGSsuVVdYlS7MmMkAb6kpl2EztvpXR3FH60
 TNqVYLY=
 =kfLN
 -----END PGP SIGNATURE-----

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

Pull sound updates from Takashi Iwai:
 "It's been relatively calm for a new era; majority of changes are for
  ASoC, mostly device-specific changes, while there are a bit of
  cleanups in core stuff. A few SPI API and regmap updates are included
  to be used by sound drivers, too.

  Core:
   - A few trivial cleanups about __free() and runtime PM macros
   - Convert to new snd_seq_bus binding

  ASoC:
   - Generic SDCA support for reporting jack events
   - Continuing platform support, cleanup and feature improvements for
     AMD, Intel, Qualcomm and SOF code
   - Platform description improvements for the Cirrus drivers
   - Support for NXP i.MX952, Realtek RT1320 and RT5575, and Sophogo
     CV1800B

  HD- and USB-audio:
   - Many quirks as usual"

* tag 'sound-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (341 commits)
  ALSA: usb-audio: Add DSD support for iBasso DC04U
  ALSA: mixer: oss: Add card disconnect checkpoints
  ASoC: SOF: ipc4-control: Set correct error code in refresh_bytes_control
  ASoC: SOF: Intel: select CONFIG_SND_HDA_EXT_CORE from SND_SOC_SOF_HDA_COMMON
  ALSA: usb-audio: Add iface reset and delay quirk for AB13X USB Audio
  ASoC: amd: maintainer information
  ALSA: ctxfi: Add quirk for SE-300PCIE variant (160b:0102)
  ALSA: hda/generic: fix typos in comments
  ALSA: hda/realtek - Enable mute LEDs on HP ENVY x360 15-es0xxx
  ALSA: hda/conexant: Add quirk for HP ZBook Studio G4
  ASoC: fsl_asrc_dma: allocate memory from dma device
  ASoC: fsl_asrc: Add support for i.MX952 platform
  ASoC: fsl_asrc_m2m: Add option to start ASRC before DMA device for M2M
  ASoC: dt-bindings: fsl,imx-asrc: Add support for i.MX952 platform
  ALSA: oss: delete self assignment
  ASoC: rockchip: spdif: Convert to FIELD_PREP
  ASoC: rockchip: spdif: Fill IEC958 CS info per params
  ASoC: rockchip: spdif: Add support for format S32_LE
  ASoC: rockchip: spdif: Add support for set mclk rate
  ASoC: rockchip: spdif: Swap PCM and DAI component registration order
  ...
This commit is contained in:
Linus Torvalds 2026-02-11 11:43:00 -08:00
commit d061251387
330 changed files with 14425 additions and 4703 deletions

View file

@ -1,17 +0,0 @@
Android Goldfish Audio
Android goldfish audio device generated by android emulator.
Required properties:
- compatible : should contain "google,goldfish-audio" to match emulator
- reg : <registers mapping>
- interrupts : <interrupt mapping>
Example:
goldfish_audio@9030000 {
compatible = "google,goldfish-audio";
reg = <0x9030000 0x100>;
interrupts = <0x4>;
};

View file

@ -15,12 +15,15 @@ description:
sound quallity, which is a new high efficiency, low
noise, constant large volume, 6th Smart K audio amplifier.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: awinic,aw87390
oneOf:
- enum:
- awinic,aw87390
- items:
- enum:
- anbernic,rgds-amp
- const: awinic,aw87391
reg:
maxItems: 1
@ -40,10 +43,31 @@ required:
- compatible
- reg
- "#sound-dai-cells"
- awinic,audio-channel
unevaluatedProperties: false
allOf:
- $ref: dai-common.yaml#
- if:
properties:
compatible:
contains:
enum:
- awinic,aw87390
then:
required:
- awinic,audio-channel
- if:
properties:
compatible:
contains:
enum:
- anbernic,rgds-amp
then:
properties:
vdd-supply: true
examples:
- |
i2c {

View file

@ -33,6 +33,8 @@ properties:
reset-gpios:
maxItems: 1
dvdd-supply: true
awinic,audio-channel:
description:
It is used to distinguish multiple PA devices, so that different
@ -65,6 +67,17 @@ allOf:
then:
properties:
reset-gpios: false
- if:
properties:
compatible:
contains:
const: awinic,aw88261
then:
required:
- dvdd-supply
else:
properties:
dvdd-supply: false
unevaluatedProperties: false

View file

@ -40,11 +40,33 @@ properties:
tdm-slots:
$ref: /schemas/types.yaml#/definitions/uint32
description:
number of channels over one serializer
the property is ignored in DIT mode
Number of channels over one serializer. This property
specifies the TX playback TDM slot count, along with default RX slot count
if tdm-slots-rx is not specified.
The property is ignored in DIT mode.
minimum: 2
maximum: 32
tdm-slots-rx:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Number of RX capture channels over one serializer. If specified,
allows independent RX TDM slot count separate from TX. Requires
ti,async-mode to be enabled for independent TX/RX clock rates.
The property is ignored in DIT mode.
minimum: 2
maximum: 32
ti,async-mode:
description:
Specify to allow independent TX & RX clocking,
to enable audio playback & record with different sampling rate,
and different number of bits per frame.
if property is omitted, TX and RX will share same bit clock and frame clock signals,
thus RX need to use same bits per frame and sampling rate as TX in synchronous mode.
the property is ignored in DIT mode (as DIT is TX-only)
type: boolean
serial-dir:
description:
A list of serializer configuration
@ -125,7 +147,21 @@ properties:
auxclk-fs-ratio:
$ref: /schemas/types.yaml#/definitions/uint32
description: ratio of AUCLK and FS rate if applicable
description:
Ratio of AUCLK and FS rate if applicable. This property specifies
the TX ratio, along with default RX ratio if auxclk-fs-ratio-rx
is not specified.
When not specified, the inputted system clock frequency via set_sysclk
callback by the machine driver is used for divider calculation.
auxclk-fs-ratio-rx:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Ratio of AUCLK and FS rate for RX. If specified, allows
for a different RX ratio. Requires ti,async-mode to be
enabled when the ratio differs from auxclk-fs-ratio.
When not specified, it defaults to the value of auxclk-fs-ratio.
The property is ignored in DIT mode.
gpio-controller: true
@ -170,14 +206,38 @@ allOf:
- $ref: dai-common.yaml#
- if:
properties:
opmode:
op-mode:
enum:
- 0
then:
required:
- tdm-slots
- if:
properties:
op-mode:
const: 1
then:
properties:
tdm-slots: false
tdm-slots-rx: false
ti,async-mode: false
auxclk-fs-ratio-rx: false
- if:
required:
- tdm-slots-rx
then:
required:
- ti,async-mode
- if:
required:
- auxclk-fs-ratio-rx
then:
required:
- ti,async-mode
unevaluatedProperties: false
examples:
@ -190,6 +250,7 @@ examples:
interrupt-names = "tx", "rx";
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
ti,async-mode;
dmas = <&main_udmap 0xc400>, <&main_udmap 0x4400>;
dma-names = "tx", "rx";
serial-dir = <

View file

@ -30,10 +30,20 @@ properties:
"#sound-dai-cells":
const: 0
vdda-supply:
description:
Analogue power supply.
vddd-supply:
description:
Interface power supply.
required:
- compatible
- reg
- "#sound-dai-cells"
- vddd-supply
- vdda-supply
additionalProperties: false
@ -46,5 +56,7 @@ examples:
compatible = "everest,es8389";
reg = <0x10>;
#sound-dai-cells = <0>;
vddd-supply = <&vdd3v3>;
vdda-supply = <&vdd3v3>;
};
};

View file

@ -34,7 +34,9 @@ description: |
properties:
compatible:
const: fsl,imx8qm-audmix
enum:
- fsl,imx8qm-audmix
- fsl,imx952-audmix
reg:
maxItems: 1
@ -80,7 +82,17 @@ required:
- reg
- clocks
- clock-names
- power-domains
allOf:
- if:
properties:
compatible:
contains:
enum:
- fsl,imx8qm-audmix
then:
required:
- power-domains
unevaluatedProperties: false

View file

@ -25,6 +25,7 @@ properties:
- fsl,imx53-asrc
- fsl,imx8qm-asrc
- fsl,imx8qxp-asrc
- fsl,imx952-asrc
- items:
- enum:
- fsl,imx6sx-asrc

View file

@ -63,6 +63,16 @@ required:
allOf:
- $ref: dai-common.yaml#
- if:
properties:
compatible:
contains:
enum:
- fsl,imx6sx-mqs
- fsl,imx93-mqs
then:
required:
- gpr
- if:
properties:
compatible:
@ -91,8 +101,6 @@ allOf:
clock-names:
items:
- const: mclk
required:
- gpr
unevaluatedProperties: false

View file

@ -22,14 +22,20 @@ allOf:
properties:
compatible:
enum:
- fsl,imx7ulp-rpmsg-audio
- fsl,imx8mn-rpmsg-audio
- fsl,imx8mm-rpmsg-audio
- fsl,imx8mp-rpmsg-audio
- fsl,imx8ulp-rpmsg-audio
- fsl,imx93-rpmsg-audio
- fsl,imx95-rpmsg-audio
oneOf:
- enum:
- fsl,imx7ulp-rpmsg-audio
- fsl,imx8mn-rpmsg-audio
- fsl,imx8mm-rpmsg-audio
- fsl,imx8mp-rpmsg-audio
- fsl,imx8ulp-rpmsg-audio
- fsl,imx93-rpmsg-audio
- fsl,imx95-rpmsg-audio
- items:
- enum:
- fsl,imx94-rpmsg-audio
- fsl,imx952-rpmsg-audio
- const: fsl,imx95-rpmsg-audio
clocks:
items:

View file

@ -133,6 +133,13 @@ properties:
- description: dataline mask for 'rx'
- description: dataline mask for 'tx'
fsl,sai-amix-mode:
$ref: /schemas/types.yaml#/definitions/string
description:
The audmix module is bypassed from hardware or not.
enum: [none, bypass, audmix]
default: none
fsl,sai-mclk-direction-output:
description: SAI will output the SAI MCLK clock.
type: boolean
@ -180,6 +187,15 @@ allOf:
properties:
fsl,sai-synchronous-rx: false
- if:
required:
- fsl,sai-amix-mode
then:
properties:
compatible:
contains:
const: fsl,imx952-sai
required:
- compatible
- reg

View file

@ -0,0 +1,38 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/google,goldfish-audio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Android Goldfish Audio
maintainers:
- Kuan-Wei Chiu <visitorckw@gmail.com>
description:
Android goldfish audio device generated by Android emulator.
properties:
compatible:
const: google,goldfish-audio
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- interrupts
additionalProperties: false
examples:
- |
sound@9030000 {
compatible = "google,goldfish-audio";
reg = <0x9030000 0x100>;
interrupts = <4>;
};

View file

@ -47,16 +47,118 @@ properties:
- description: AFE clock
- description: ADDA DAC clock
- description: ADDA DAC pre-distortion clock
- description: audio infra sys clock
- description: audio infra 26M clock
- description: ADDA ADC clock
- description: ADDA6 ADC clock
- description: Audio low-jitter 22.5792m clock
- description: Audio low-jitter 24.576m clock
- description: Audio PLL1 tuner clock
- description: Audio PLL2 tuner clock
- description: Audio Time-Division Multiplexing interface clock
- description: ADDA ADC Sine Generator clock
- description: audio Non-LE clock
- description: Audio DAC High-Resolution clock
- description: Audio High-Resolution ADC clock
- description: Audio High-Resolution ADC SineGen clock
- description: Audio ADDA6 High-Resolution ADC clock
- description: Tertiary ADDA DAC clock
- description: Tertiary ADDA DAC pre-distortion clock
- description: Tertiary ADDA DAC Sine Generator clock
- description: Tertiary ADDA DAC High-Resolution clock
- description: Audio infra sys clock
- description: Audio infra 26M clock
- description: Mux for audio clock
- description: Mux for audio internal bus clock
- description: Mux main divider by 4
- description: Primary audio mux
- description: Primary audio PLL
- description: Secondary audio mux
- description: Secondary audio PLL
- description: Primary audio en-generator clock
- description: Primary PLL divider by 4 for IEC
- description: Secondary audio en-generator clock
- description: Secondary PLL divider by 4 for IEC
- description: Mux selector for I2S port 0
- description: Mux selector for I2S port 1
- description: Mux selector for I2S port 2
- description: Mux selector for I2S port 3
- description: Mux selector for I2S port 4
- description: Mux selector for I2S port 5
- description: Mux selector for I2S port 6
- description: Mux selector for I2S port 7
- description: Mux selector for I2S port 8
- description: Mux selector for I2S port 9
- description: APLL1 and APLL2 divider for I2S port 0
- description: APLL1 and APLL2 divider for I2S port 1
- description: APLL1 and APLL2 divider for I2S port 2
- description: APLL1 and APLL2 divider for I2S port 3
- description: APLL1 and APLL2 divider for I2S port 4
- description: APLL1 and APLL2 divider for IEC
- description: APLL1 and APLL2 divider for I2S port 5
- description: APLL1 and APLL2 divider for I2S port 6
- description: APLL1 and APLL2 divider for I2S port 7
- description: APLL1 and APLL2 divider for I2S port 8
- description: APLL1 and APLL2 divider for I2S port 9
- description: Top mux for audio subsystem
- description: 26MHz clock for audio subsystem
clock-names:
items:
- const: aud_afe_clk
- const: aud_dac_clk
- const: aud_dac_predis_clk
- const: aud_adc_clk
- const: aud_adda6_adc_clk
- const: aud_apll22m_clk
- const: aud_apll24m_clk
- const: aud_apll1_tuner_clk
- const: aud_apll2_tuner_clk
- const: aud_tdm_clk
- const: aud_tml_clk
- const: aud_nle
- const: aud_dac_hires_clk
- const: aud_adc_hires_clk
- const: aud_adc_hires_tml
- const: aud_adda6_adc_hires_clk
- const: aud_3rd_dac_clk
- const: aud_3rd_dac_predis_clk
- const: aud_3rd_dac_tml
- const: aud_3rd_dac_hires_clk
- const: aud_infra_clk
- const: aud_infra_26m_clk
- const: top_mux_audio
- const: top_mux_audio_int
- const: top_mainpll_d4_d4
- const: top_mux_aud_1
- const: top_apll1_ck
- const: top_mux_aud_2
- const: top_apll2_ck
- const: top_mux_aud_eng1
- const: top_apll1_d4
- const: top_mux_aud_eng2
- const: top_apll2_d4
- const: top_i2s0_m_sel
- const: top_i2s1_m_sel
- const: top_i2s2_m_sel
- const: top_i2s3_m_sel
- const: top_i2s4_m_sel
- const: top_i2s5_m_sel
- const: top_i2s6_m_sel
- const: top_i2s7_m_sel
- const: top_i2s8_m_sel
- const: top_i2s9_m_sel
- const: top_apll12_div0
- const: top_apll12_div1
- const: top_apll12_div2
- const: top_apll12_div3
- const: top_apll12_div4
- const: top_apll12_divb
- const: top_apll12_div5
- const: top_apll12_div6
- const: top_apll12_div7
- const: top_apll12_div8
- const: top_apll12_div9
- const: top_mux_audio_h
- const: top_clk26m_clk
required:
- compatible
@ -83,23 +185,69 @@ examples:
afe: mt8192-afe-pcm {
compatible = "mediatek,mt8192-audio";
interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&audsys CLK_AUD_AFE>, <&audsys CLK_AUD_DAC>,
<&audsys CLK_AUD_DAC_PREDIS>, <&audsys CLK_AUD_ADC>,
<&audsys CLK_AUD_ADDA6_ADC>, <&audsys CLK_AUD_22M>,
<&audsys CLK_AUD_24M>, <&audsys CLK_AUD_APLL_TUNER>,
<&audsys CLK_AUD_APLL2_TUNER>, <&audsys CLK_AUD_TDM>,
<&audsys CLK_AUD_TML>, <&audsys CLK_AUD_NLE>,
<&audsys CLK_AUD_DAC_HIRES>, <&audsys CLK_AUD_ADC_HIRES>,
<&audsys CLK_AUD_ADC_HIRES_TML>, <&audsys CLK_AUD_ADDA6_ADC_HIRES>,
<&audsys CLK_AUD_3RD_DAC>, <&audsys CLK_AUD_3RD_DAC_PREDIS>,
<&audsys CLK_AUD_3RD_DAC_TML>, <&audsys CLK_AUD_3RD_DAC_HIRES>,
<&infracfg CLK_INFRA_AUDIO>, <&infracfg CLK_INFRA_AUDIO_26M_B>,
<&topckgen CLK_TOP_AUDIO_SEL>, <&topckgen CLK_TOP_AUD_INTBUS_SEL>,
<&topckgen CLK_TOP_MAINPLL_D4_D4>, <&topckgen CLK_TOP_AUD_1_SEL>,
<&topckgen CLK_TOP_APLL1>, <&topckgen CLK_TOP_AUD_2_SEL>,
<&topckgen CLK_TOP_APLL2>, <&topckgen CLK_TOP_AUD_ENGEN1_SEL>,
<&topckgen CLK_TOP_APLL1_D4>, <&topckgen CLK_TOP_AUD_ENGEN2_SEL>,
<&topckgen CLK_TOP_APLL2_D4>, <&topckgen CLK_TOP_APLL_I2S0_M_SEL>,
<&topckgen CLK_TOP_APLL_I2S1_M_SEL>, <&topckgen CLK_TOP_APLL_I2S2_M_SEL>,
<&topckgen CLK_TOP_APLL_I2S3_M_SEL>, <&topckgen CLK_TOP_APLL_I2S4_M_SEL>,
<&topckgen CLK_TOP_APLL_I2S5_M_SEL>, <&topckgen CLK_TOP_APLL_I2S6_M_SEL>,
<&topckgen CLK_TOP_APLL_I2S7_M_SEL>, <&topckgen CLK_TOP_APLL_I2S8_M_SEL>,
<&topckgen CLK_TOP_APLL_I2S9_M_SEL>, <&topckgen CLK_TOP_APLL12_DIV0>,
<&topckgen CLK_TOP_APLL12_DIV1>, <&topckgen CLK_TOP_APLL12_DIV2>,
<&topckgen CLK_TOP_APLL12_DIV3>, <&topckgen CLK_TOP_APLL12_DIV4>,
<&topckgen CLK_TOP_APLL12_DIVB>, <&topckgen CLK_TOP_APLL12_DIV5>,
<&topckgen CLK_TOP_APLL12_DIV6>, <&topckgen CLK_TOP_APLL12_DIV7>,
<&topckgen CLK_TOP_APLL12_DIV8>, <&topckgen CLK_TOP_APLL12_DIV9>,
<&topckgen CLK_TOP_AUDIO_H_SEL>, <&clk26m>;
clock-names = "aud_afe_clk", "aud_dac_clk",
"aud_dac_predis_clk", "aud_adc_clk",
"aud_adda6_adc_clk", "aud_apll22m_clk",
"aud_apll24m_clk", "aud_apll1_tuner_clk",
"aud_apll2_tuner_clk", "aud_tdm_clk",
"aud_tml_clk", "aud_nle",
"aud_dac_hires_clk", "aud_adc_hires_clk",
"aud_adc_hires_tml", "aud_adda6_adc_hires_clk",
"aud_3rd_dac_clk", "aud_3rd_dac_predis_clk",
"aud_3rd_dac_tml", "aud_3rd_dac_hires_clk",
"aud_infra_clk", "aud_infra_26m_clk",
"top_mux_audio", "top_mux_audio_int",
"top_mainpll_d4_d4", "top_mux_aud_1",
"top_apll1_ck", "top_mux_aud_2",
"top_apll2_ck", "top_mux_aud_eng1",
"top_apll1_d4", "top_mux_aud_eng2",
"top_apll2_d4", "top_i2s0_m_sel",
"top_i2s1_m_sel", "top_i2s2_m_sel",
"top_i2s3_m_sel", "top_i2s4_m_sel",
"top_i2s5_m_sel", "top_i2s6_m_sel",
"top_i2s7_m_sel", "top_i2s8_m_sel",
"top_i2s9_m_sel", "top_apll12_div0",
"top_apll12_div1", "top_apll12_div2",
"top_apll12_div3", "top_apll12_div4",
"top_apll12_divb", "top_apll12_div5",
"top_apll12_div6", "top_apll12_div7",
"top_apll12_div8", "top_apll12_div9",
"top_mux_audio_h", "top_clk26m_clk";
memory-region = <&afe_dma_mem>;
power-domains = <&scpsys MT8192_POWER_DOMAIN_AUDIO>;
resets = <&watchdog MT8192_TOPRGU_AUDIO_SW_RST>;
reset-names = "audiosys";
mediatek,apmixedsys = <&apmixedsys>;
mediatek,infracfg = <&infracfg>;
mediatek,topckgen = <&topckgen>;
power-domains = <&scpsys MT8192_POWER_DOMAIN_AUDIO>;
clocks = <&audsys CLK_AUD_AFE>,
<&audsys CLK_AUD_DAC>,
<&audsys CLK_AUD_DAC_PREDIS>,
<&infracfg CLK_INFRA_AUDIO>,
<&infracfg CLK_INFRA_AUDIO_26M_B>;
clock-names = "aud_afe_clk",
"aud_dac_clk",
"aud_dac_predis_clk",
"aud_infra_clk",
"aud_infra_26m_clk";
memory-region = <&afe_dma_mem>;
};
...

View file

@ -0,0 +1,61 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/realtek,rt5575.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ALC5575 audio CODEC
maintainers:
- Oder Chiou <oder_chiou@realtek.com>
description:
The device supports both I2C and SPI. I2C is mandatory, while SPI is
optional depending on the hardware configuration. SPI is used for
firmware loading if present.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: realtek,rt5575
reg:
maxItems: 1
spi-parent:
description:
Optional phandle reference to the SPI controller used for firmware
loading. The argument specifies the chip select.
$ref: /schemas/types.yaml#/definitions/phandle-array
required:
- compatible
- reg
unevaluatedProperties: false
examples:
# I2C-only node
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
codec@57 {
compatible = "realtek,rt5575";
reg = <0x57>;
};
};
# I2C + optional SPI node
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
codec@57 {
compatible = "realtek,rt5575";
reg = <0x57>;
spi-parent = <&spi0 0>; /* chip-select 0 */
};
};

View file

@ -0,0 +1,100 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/realtek,rt5651.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Realtek RT5651 audio CODEC
maintainers:
- Bard Liao <bardliao@realtek.com>
description: >
This device supports I2C only.
Pins on the device (for linking into audio routes) for RT5651:
* DMIC L1
* DMIC R1
* IN1P
* IN2P
* IN2N
* IN3P
* HPOL
* HPOR
* LOUTL
* LOUTR
* PDML
* PDMR
allOf:
- $ref: /schemas/sound/dai-common.yaml#
properties:
compatible:
const: realtek,rt5651
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: mclk
'#sound-dai-cells':
const: 0
realtek,in2-differential:
type: boolean
description: Indicate MIC2 input are differential, rather than single-ended.
realtek,dmic-en:
type: boolean
description: Indicates DMIC is used.
realtek,jack-detect-source:
$ref: /schemas/types.yaml#/definitions/uint32
description: Select jack-detect input pin.
enum: [1, 2, 3]
realtek,jack-detect-not-inverted:
type: boolean
description:
Normal jack-detect switches give an inverted (active-low) signal. Set this
bool in the rare case you've a jack-detect switch which is not inverted.
realtek,over-current-threshold-microamp:
description: Micbias over-current detection threshold in µA.
enum: [600, 1500, 2000]
realtek,over-current-scale-factor:
$ref: /schemas/types.yaml#/definitions/uint32
description: >
Micbias over-current detection scale factor:
0: scale current by 0.5
1: scale current by 0.75
2: scale current by 1.0
3: scale current by 1.5
enum: [0, 1, 2, 3]
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
codec@1a {
compatible = "realtek,rt5651";
reg = <0x1a>;
realtek,dmic-en;
realtek,in2-differential;
};
};

View file

@ -14,13 +14,21 @@ description:
class-D audio power amplifier and delivering 4x75W into 4OHm at 10%
THD+N from a 25V supply in automotive applications.
The RTQ9154 is the family series of RTQ9128. The major change is to modify
the package size. Beside this, whole functions are almost all the same.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
enum:
- richtek,rtq9128
oneOf:
- enum:
- richtek,rtq9128
- items:
- enum:
- richtek,rtq9154
- const: richtek,rtq9128
reg:
maxItems: 1

View file

@ -1,63 +0,0 @@
RT5651 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "realtek,rt5651".
- reg : The I2C address of the device.
Optional properties:
- realtek,in2-differential
Boolean. Indicate MIC2 input are differential, rather than single-ended.
- realtek,dmic-en
Boolean. true if dmic is used.
- realtek,jack-detect-source
u32. Valid values:
1: Use JD1_1 pin for jack-detect
2: Use JD1_2 pin for jack-detect
3: Use JD2 pin for jack-detect
- realtek,jack-detect-not-inverted
bool. Normal jack-detect switches give an inverted (active-low) signal,
set this bool in the rare case you've a jack-detect switch which is not
inverted.
- realtek,over-current-threshold-microamp
u32, micbias over-current detection threshold in µA, valid values are
600, 1500 and 2000µA.
- realtek,over-current-scale-factor
u32, micbias over-current detection scale-factor, valid values are:
0: Scale current by 0.5
1: Scale current by 0.75
2: Scale current by 1.0
3: Scale current by 1.5
Pins on the device (for linking into audio routes) for RT5651:
* DMIC L1
* DMIC R1
* IN1P
* IN2P
* IN2N
* IN3P
* HPOL
* HPOR
* LOUTL
* LOUTR
* PDML
* PDMR
Example:
rt5651: codec@1a {
compatible = "realtek,rt5651";
reg = <0x1a>;
realtek,dmic-en = "true";
realtek,in2-diff = "false";
};

View file

@ -0,0 +1,46 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/sophgo,cv1800b-codecs.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sophgo CV1800B Internal ADC/DAC Codec
maintainers:
- Anton D. Stavinskii <stavinsky@gmail.com>
description:
Internal ADC and DAC audio codecs integrated in the Sophgo CV1800B SoC.
Codecs expose a single DAI and are intended to be connected
to an I2S/TDM controller via an ASoC machine driver.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
enum:
- sophgo,cv1800b-sound-adc
- sophgo,cv1800b-sound-dac
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
required:
- compatible
- reg
- "#sound-dai-cells"
unevaluatedProperties: false
examples:
- |
audio-codec@300a100 {
compatible = "sophgo,cv1800b-sound-adc";
reg = <0x0300a100 0x100>;
#sound-dai-cells = <0>;
};
...

View file

@ -0,0 +1,67 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/sophgo,cv1800b-i2s.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sophgo CV1800B I2S/TDM controller
maintainers:
- Anton D. Stavinskii <stavinsky@gmail.com>
description: I2S/TDM controller found in CV1800B / Sophgo SG2002/SG2000 SoCs.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: sophgo,cv1800b-i2s
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
clocks:
maxItems: 2
clock-names:
items:
- const: i2s
- const: mclk
dmas:
minItems: 1
maxItems: 2
dma-names:
minItems: 1
items:
- enum: [rx, tx]
- const: tx
required:
- compatible
- reg
- clocks
- clock-names
- "#sound-dai-cells"
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/sophgo,cv1800.h>
i2s@4110000 {
compatible = "sophgo,cv1800b-i2s";
reg = <0x04110000 0x10000>;
clocks = <&clk CLK_APB_I2S1>, <&clk CLK_SDMA_AUD1>;
clock-names = "i2s", "mclk";
dmas = <&dmamux 2 1>, <&dmamux 3 1>;
dma-names = "rx", "tx";
#sound-dai-cells = <0>;
};
...

View file

@ -1,36 +0,0 @@
Texas Instruments - tas2552 Codec module
The tas2552 serial control bus communicates through I2C protocols
Required properties:
- compatible - One of:
"ti,tas2552" - TAS2552
- reg - I2C slave address: it can be 0x40 if ADDR pin is 0
or 0x41 if ADDR pin is 1.
- supply-*: Required supply regulators are:
"vbat" battery voltage
"iovdd" I/O Voltage
"avdd" Analog DAC Voltage
Optional properties:
- enable-gpio - gpio pin to enable/disable the device
tas2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or use the
internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL, the PDM
reference clock is also selectable: PLL, IVCLKIN, BCLK or MCLK.
For system integration the dt-bindings/sound/tas2552.h header file provides
defined values to select and configure the PLL and PDM reference clocks.
Example:
tas2552: tas2552@41 {
compatible = "ti,tas2552";
reg = <0x41>;
vbat-supply = <&reg_vbat>;
iovdd-supply = <&reg_iovdd>;
avdd-supply = <&reg_avdd>;
enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
};
For more product information please see the link below:
https://www.ti.com/product/TAS2552

View file

@ -0,0 +1,62 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,tas2552.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TAS2552 Codec
maintainers:
- Shenghao Ding <shenghao-ding@ti.com>
- Kevin Lu <kevin-lu@ti.com>
- Baojun Xu <baojun.xu@ti.com>
description: >
The TAS2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or
use the internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL,
the PDM reference clock is also selectable: PLL, IVCLKIN, BCLK or MCLK.
For system integration the dt-bindings/sound/tas2552.h header file provides
defined values to select and configure the PLL and PDM reference clocks.
properties:
compatible:
const: ti,tas2552
reg:
maxItems: 1
vbat-supply: true
iovdd-supply: true
avdd-supply: true
enable-gpio:
maxItems: 1
description: gpio pin to enable/disable the device
required:
- compatible
- reg
- vbat-supply
- iovdd-supply
- avdd-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@41 {
compatible = "ti,tas2552";
reg = <0x41>;
vbat-supply = <&reg_vbat>;
iovdd-supply = <&reg_iovdd>;
avdd-supply = <&reg_avdd>;
enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
};
};

View file

@ -41,8 +41,11 @@ properties:
areg-supply:
description: |
Regulator with AVDD at 3.3V. If not defined then the internal regulator
is enabled.
External supply of 1.8V. If not defined then the internal regulator is
enabled instead.
avdd-supply: true
iovdd-supply: true
ti,mic-bias-source:
description: |

View file

@ -1032,6 +1032,13 @@ L: dmaengine@vger.kernel.org
S: Supported
F: drivers/dma/amd/ae4dma/
AMD ASoC DRIVERS
M: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
R: Venkata Prasad Potturu <venkataprasad.potturu@amd.com>
L: linux-sound@vger.kernel.org
S: Supported
F: sound/soc/amd/
AMD AXI W1 DRIVER
M: Kris Chaplin <kris.chaplin@amd.com>
R: Thomas Delev <thomas.delev@amd.com>
@ -25898,7 +25905,7 @@ M: Kevin Lu <kevin-lu@ti.com>
M: Baojun Xu <baojun.xu@ti.com>
L: linux-sound@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/sound/tas2552.txt
F: Documentation/devicetree/bindings/sound/ti,tas2552.yaml
F: Documentation/devicetree/bindings/sound/ti,tas2562.yaml
F: Documentation/devicetree/bindings/sound/ti,tas2770.yaml
F: Documentation/devicetree/bindings/sound/ti,tas27xx.yaml

View file

@ -412,18 +412,23 @@ static ssize_t cs_dsp_debugfs_string_read(struct cs_dsp *dsp,
size_t count, loff_t *ppos,
const char **pstr)
{
const char *str __free(kfree) = NULL;
const char *str;
ssize_t ret = 0;
scoped_guard(mutex, &dsp->pwr_lock) {
if (!*pstr)
return 0;
str = kasprintf(GFP_KERNEL, "%s\n", *pstr);
if (!str)
return -ENOMEM;
return simple_read_from_buffer(user_buf, count, ppos, str, strlen(str));
if (*pstr) {
str = kasprintf(GFP_KERNEL, "%s\n", *pstr);
if (str) {
ret = simple_read_from_buffer(user_buf, count,
ppos, str, strlen(str));
kfree(str);
} else {
ret = -ENOMEM;
}
}
}
return ret;
}
static ssize_t cs_dsp_debugfs_wmfw_read(struct file *file,
@ -1483,7 +1488,7 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
const struct wmfw_region *region;
const struct cs_dsp_region *mem;
const char *region_name;
u8 *buf __free(kfree) = NULL;
u8 *buf = NULL;
size_t buf_len = 0;
size_t region_len;
unsigned int reg;
@ -1638,6 +1643,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
ret = 0;
out_fw:
kfree(buf);
if (ret == -EOVERFLOW)
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
@ -2168,8 +2175,9 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
const struct cs_dsp_region *mem;
struct cs_dsp_alg_region *alg_region;
const char *region_name;
int ret, pos, blocks, type, offset, reg, version;
u8 *buf __free(kfree) = NULL;
int ret, pos, blocks, type, version;
unsigned int offset, reg;
u8 *buf = NULL;
size_t buf_len = 0;
size_t region_len;
@ -2193,6 +2201,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
switch (be32_to_cpu(hdr->rev) & 0xff) {
case 1:
case 2:
case 3:
break;
default:
cs_dsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
@ -2201,7 +2210,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
goto out_fw;
}
cs_dsp_info(dsp, "%s: v%d.%d.%d\n", file,
cs_dsp_info(dsp, "%s (v%d): v%d.%d.%d\n", file,
be32_to_cpu(hdr->rev) & 0xff,
(le32_to_cpu(hdr->ver) >> 16) & 0xff,
(le32_to_cpu(hdr->ver) >> 8) & 0xff,
le32_to_cpu(hdr->ver) & 0xff);
@ -2232,8 +2242,9 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
(le32_to_cpu(blk->ver) >> 16) & 0xff,
(le32_to_cpu(blk->ver) >> 8) & 0xff,
le32_to_cpu(blk->ver) & 0xff);
cs_dsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
file, blocks, le32_to_cpu(blk->len), offset, type);
cs_dsp_dbg(dsp, "%s.%d: %d bytes off:%#x off32:%#x in %#x\n",
file, blocks, le32_to_cpu(blk->len), offset,
le32_to_cpu(blk->offset32), type);
reg = 0;
region_name = "Unknown";
@ -2266,6 +2277,13 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
}
break;
case WMFW_ADSP2_XM_LONG:
case WMFW_ADSP2_YM_LONG:
case WMFW_HALO_XM_PACKED_LONG:
case WMFW_HALO_YM_PACKED_LONG:
offset = le32_to_cpu(blk->offset32);
type &= 0xff; /* strip extended block type flags */
fallthrough;
case WMFW_ADSP1_DM:
case WMFW_ADSP1_ZM:
case WMFW_ADSP2_XM:
@ -2348,6 +2366,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
ret = 0;
out_fw:
kfree(buf);
if (ret == -EOVERFLOW)
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);

View file

@ -56,13 +56,14 @@ EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_get_firmware, "FW_CS_DSP_KUNIT_TEST_UTILS")
* @alg_id: Algorithm ID.
* @alg_ver: Algorithm version.
* @type: Type of the block.
* @offset: Offset.
* @offset: 16-bit offset.
* @offset32: 32-bit offset (sample rate on V1 and V2 file formats).
* @payload_data: Pointer to buffer containing the payload data.
* @payload_len_bytes: Length of payload data in bytes.
*/
void cs_dsp_mock_bin_add_raw_block(struct cs_dsp_mock_bin_builder *builder,
unsigned int alg_id, unsigned int alg_ver,
int type, unsigned int offset,
int type, u16 offset, u32 offset32,
const void *payload_data, size_t payload_len_bytes)
{
struct wmfw_coeff_item *item;
@ -75,6 +76,7 @@ void cs_dsp_mock_bin_add_raw_block(struct cs_dsp_mock_bin_builder *builder,
item = builder->write_p;
item->offset = cpu_to_le16(offset);
item->offset32 = cpu_to_le32(offset32);
item->type = cpu_to_le16(type);
item->id = cpu_to_le32(alg_id);
item->ver = cpu_to_le32(alg_ver << 8);
@ -104,7 +106,7 @@ static void cs_dsp_mock_bin_add_name_or_info(struct cs_dsp_mock_bin_builder *bui
info = tmp;
}
cs_dsp_mock_bin_add_raw_block(builder, 0, 0, WMFW_INFO_TEXT, 0, info, info_len);
cs_dsp_mock_bin_add_raw_block(builder, 0, 0, WMFW_INFO_TEXT, 0, 0, info, info_len);
kunit_kfree(builder->test_priv->test, tmp);
}
@ -156,11 +158,39 @@ void cs_dsp_mock_bin_add_patch(struct cs_dsp_mock_bin_builder *builder,
KUNIT_ASSERT_EQ(builder->test_priv->test, payload_len_bytes % 4, 0);
cs_dsp_mock_bin_add_raw_block(builder, alg_id, alg_ver,
mem_region, reg_addr_offset,
mem_region, (u16)reg_addr_offset, 0,
payload_data, payload_len_bytes);
}
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_patch, "FW_CS_DSP_KUNIT_TEST_UTILS");
/**
* cs_dsp_mock_bin_add_patch_off32() - Add a patch data block with 32-bit offset.
*
* @builder: Pointer to struct cs_dsp_mock_bin_builder.
* @alg_id: Algorithm ID for the patch.
* @alg_ver: Algorithm version for the patch.
* @mem_region: Memory region for the patch.
* @reg_addr_offset: Offset to start of data in register addresses.
* @payload_data: Pointer to buffer containing the payload data.
* @payload_len_bytes: Length of payload data in bytes.
*/
void cs_dsp_mock_bin_add_patch_off32(struct cs_dsp_mock_bin_builder *builder,
unsigned int alg_id, unsigned int alg_ver,
int mem_region, unsigned int reg_addr_offset,
const void *payload_data, size_t payload_len_bytes)
{
/* Payload length must be a multiple of 4 */
KUNIT_ASSERT_EQ(builder->test_priv->test, payload_len_bytes % 4, 0);
/* Mark the block as using the 32-bit offset */
mem_region |= 0xf400;
cs_dsp_mock_bin_add_raw_block(builder, alg_id, alg_ver,
mem_region, 0, reg_addr_offset,
payload_data, payload_len_bytes);
}
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_patch_off32, "FW_CS_DSP_KUNIT_TEST_UTILS");
/**
* cs_dsp_mock_bin_init() - Initialize a struct cs_dsp_mock_bin_builder.
*

View file

@ -23,10 +23,10 @@ EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_halo_dsp1_regions, "FW_CS_DSP_KUNIT_TEST_UTILS"
/* List of sizes in bytes, for each entry above */
const unsigned int cs_dsp_mock_halo_dsp1_region_sizes[] = {
0x5000, /* PM_PACKED */
0x6000, /* XM_PACKED */
0x47F4, /* YM_PACKED */
0x8000, /* XM_UNPACKED_24 */
0x5FF8, /* YM_UNPACKED_24 */
0x8fff4, /* XM_PACKED */
0x8fff4, /* YM_PACKED */
0xbfff8, /* XM_UNPACKED_24 */
0xbfff8, /* YM_UNPACKED_24 */
0 /* terminator */
};

View file

@ -157,22 +157,22 @@ static const struct reg_default halo_register_defaults[] = {
};
static const struct regmap_range halo_readable_registers[] = {
regmap_reg_range(0x2000000, 0x2005fff), /* XM_PACKED */
regmap_reg_range(0x2000000, 0x208fff0), /* XM_PACKED */
regmap_reg_range(0x25e0000, 0x25e004f), /* SYSINFO */
regmap_reg_range(0x25e2000, 0x25e2047), /* SYSINFO */
regmap_reg_range(0x2800000, 0x2807fff), /* XM */
regmap_reg_range(0x2800000, 0x28bfff4), /* XM */
regmap_reg_range(0x2b80000, 0x2bc700b), /* CORE CTRL */
regmap_reg_range(0x2c00000, 0x2c047f3), /* YM_PACKED */
regmap_reg_range(0x3400000, 0x3405ff7), /* YM */
regmap_reg_range(0x2c00000, 0x2c8fff0), /* YM_PACKED */
regmap_reg_range(0x3400000, 0x34bfff4), /* YM */
regmap_reg_range(0x3800000, 0x3804fff), /* PM_PACKED */
};
static const struct regmap_range halo_writeable_registers[] = {
regmap_reg_range(0x2000000, 0x2005fff), /* XM_PACKED */
regmap_reg_range(0x2800000, 0x2807fff), /* XM */
regmap_reg_range(0x2000000, 0x208fff0), /* XM_PACKED */
regmap_reg_range(0x2800000, 0x28bfff4), /* XM */
regmap_reg_range(0x2b80000, 0x2bc700b), /* CORE CTRL */
regmap_reg_range(0x2c00000, 0x2c047f3), /* YM_PACKED */
regmap_reg_range(0x3400000, 0x3405ff7), /* YM */
regmap_reg_range(0x2c00000, 0x2c8fff0), /* YM_PACKED */
regmap_reg_range(0x3400000, 0x34bfff4), /* YM */
regmap_reg_range(0x3800000, 0x3804fff), /* PM_PACKED */
};

File diff suppressed because it is too large Load diff

View file

@ -68,24 +68,24 @@ static void bin_load_with_unknown_blocks(struct kunit *test)
cs_dsp_mock_bin_add_raw_block(local->bin_builder,
cs_dsp_bin_err_test_mock_algs[0].id,
cs_dsp_bin_err_test_mock_algs[0].ver,
0xf5, 0,
0xf5, 0, 0,
random_data, sizeof(random_data));
cs_dsp_mock_bin_add_raw_block(local->bin_builder,
cs_dsp_bin_err_test_mock_algs[0].id,
cs_dsp_bin_err_test_mock_algs[0].ver,
0xf500, 0,
0xf500, 0, 0,
random_data, sizeof(random_data));
cs_dsp_mock_bin_add_raw_block(local->bin_builder,
cs_dsp_bin_err_test_mock_algs[0].id,
cs_dsp_bin_err_test_mock_algs[0].ver,
0xc300, 0,
0xc300, 0, 0,
random_data, sizeof(random_data));
/* Add a single payload to be written to DSP memory */
cs_dsp_mock_bin_add_raw_block(local->bin_builder,
cs_dsp_bin_err_test_mock_algs[0].id,
cs_dsp_bin_err_test_mock_algs[0].ver,
WMFW_ADSP2_YM, 0,
WMFW_ADSP2_YM, 0, 0,
payload_data, payload_size_bytes);
bin = cs_dsp_mock_bin_get_firmware(local->bin_builder);
@ -279,7 +279,7 @@ static void bin_too_short_for_block_header(struct kunit *test)
cs_dsp_mock_bin_add_raw_block(local->bin_builder,
cs_dsp_bin_err_test_mock_algs[0].id,
cs_dsp_bin_err_test_mock_algs[0].ver,
param->block_type, 0,
param->block_type, 0, 0,
NULL, 0);
bin = cs_dsp_mock_bin_get_firmware(local->bin_builder);
@ -311,7 +311,7 @@ static void bin_too_short_for_block_payload(struct kunit *test)
cs_dsp_mock_bin_add_raw_block(local->bin_builder,
cs_dsp_bin_err_test_mock_algs[0].id,
cs_dsp_bin_err_test_mock_algs[0].ver,
param->block_type, 0,
param->block_type, 0, 0,
payload, sizeof(payload));
bin = cs_dsp_mock_bin_get_firmware(local->bin_builder);
@ -343,7 +343,7 @@ static void bin_block_payload_len_garbage(struct kunit *test)
cs_dsp_mock_bin_add_raw_block(local->bin_builder,
cs_dsp_bin_err_test_mock_algs[0].id,
cs_dsp_bin_err_test_mock_algs[0].ver,
param->block_type, 0,
param->block_type, 0, 0,
&payload, sizeof(payload));
bin = cs_dsp_mock_bin_get_firmware(local->bin_builder);

View file

@ -4889,17 +4889,9 @@ EXPORT_SYMBOL_GPL(spi_write_then_read);
/*-------------------------------------------------------------------------*/
#if IS_ENABLED(CONFIG_OF_DYNAMIC)
/* Must call put_device() when done with returned spi_device device */
static struct spi_device *of_find_spi_device_by_node(struct device_node *node)
{
struct device *dev = bus_find_device_by_of_node(&spi_bus_type, node);
return dev ? to_spi_device(dev) : NULL;
}
#if IS_ENABLED(CONFIG_OF)
/* The spi controllers are not using spi_bus, so we find it with another way */
static struct spi_controller *of_find_spi_controller_by_node(struct device_node *node)
struct spi_controller *of_find_spi_controller_by_node(struct device_node *node)
{
struct device *dev;
@ -4912,6 +4904,17 @@ static struct spi_controller *of_find_spi_controller_by_node(struct device_node
/* Reference got in class_find_device */
return container_of(dev, struct spi_controller, dev);
}
EXPORT_SYMBOL_GPL(of_find_spi_controller_by_node);
#endif
#if IS_ENABLED(CONFIG_OF_DYNAMIC)
/* Must call put_device() when done with returned spi_device device */
static struct spi_device *of_find_spi_device_by_node(struct device_node *node)
{
struct device *dev = bus_find_device_by_of_node(&spi_bus_type, node);
return dev ? to_spi_device(dev) : NULL;
}
static int of_spi_notify(struct notifier_block *nb, unsigned long action,
void *arg)

View file

@ -126,7 +126,7 @@ struct cs_dsp_mock_bin_builder *cs_dsp_mock_bin_init(struct cs_dsp_test *priv,
unsigned int fw_version);
void cs_dsp_mock_bin_add_raw_block(struct cs_dsp_mock_bin_builder *builder,
unsigned int alg_id, unsigned int alg_ver,
int type, unsigned int offset,
int type, u16 offset, u32 offset32,
const void *payload_data, size_t payload_len_bytes);
void cs_dsp_mock_bin_add_info(struct cs_dsp_mock_bin_builder *builder,
const char *info);
@ -136,6 +136,10 @@ void cs_dsp_mock_bin_add_patch(struct cs_dsp_mock_bin_builder *builder,
unsigned int alg_id, unsigned int alg_ver,
int mem_region, unsigned int reg_addr_offset,
const void *payload_data, size_t payload_len_bytes);
void cs_dsp_mock_bin_add_patch_off32(struct cs_dsp_mock_bin_builder *builder,
unsigned int alg_id, unsigned int alg_ver,
int mem_region, unsigned int reg_addr_offset,
const void *payload_data, size_t payload_len_bytes);
struct firmware *cs_dsp_mock_bin_get_firmware(struct cs_dsp_mock_bin_builder *builder);
struct cs_dsp_mock_wmfw_builder *cs_dsp_mock_wmfw_init(struct cs_dsp_test *priv,

View file

@ -172,7 +172,7 @@ struct wmfw_coeff_item {
__le16 type;
__le32 id;
__le32 ver;
__le32 sr;
__le32 offset32;
__le32 len;
u8 data[];
} __packed;
@ -200,4 +200,9 @@ struct wmfw_coeff_item {
#define WMFW_HALO_XM_PACKED 0x11
#define WMFW_HALO_YM_PACKED 0x12
#define WMFW_ADSP2_XM_LONG 0xf405
#define WMFW_ADSP2_YM_LONG 0xf406
#define WMFW_HALO_XM_PACKED_LONG 0xf411
#define WMFW_HALO_YM_PACKED_LONG 0xf412
#endif

View file

@ -26,6 +26,8 @@
#define SCMI_IMX94_CTRL_SAI3_MCLK 5U /*!< WAKE SAI3 MCLK */
#define SCMI_IMX94_CTRL_SAI4_MCLK 6U /*!< WAKE SAI4 MCLK */
#define SCMI_IMX952_CTRL_BYPASS_AUDMIX 8U /* WAKE AUDMIX */
#if IS_ENABLED(CONFIG_IMX_SCMI_MISC_DRV)
int scmi_imx_misc_ctrl_get(u32 id, u32 *num, u32 *val);
int scmi_imx_misc_ctrl_set(u32 id, u32 val);

View file

@ -2950,7 +2950,8 @@
#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2 0x2db1
#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2 0x2db2
#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2 0x2db3
#define PCI_DEVICE_ID_INTEL_HDA_GML 0x3198
/* In a few of the Intel documents the GML acronym is used for Gemini Lake */
#define PCI_DEVICE_ID_INTEL_HDA_GLK 0x3198
#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
#define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429
#define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a
@ -3143,6 +3144,7 @@
#define PCI_DEVICE_ID_INTEL_HDA_CML_S 0xa3f0
#define PCI_DEVICE_ID_INTEL_HDA_LNL_P 0xa828
#define PCI_DEVICE_ID_INTEL_S21152BB 0xb152
#define PCI_DEVICE_ID_INTEL_HDA_NVL 0xd328
#define PCI_DEVICE_ID_INTEL_HDA_BMG 0xe2f7
#define PCI_DEVICE_ID_INTEL_HDA_PTL_H 0xe328
#define PCI_DEVICE_ID_INTEL_HDA_PTL 0xe428

View file

@ -59,7 +59,8 @@ struct davinci_mcasp_pdata {
bool i2s_accurate_sck;
/* McASP specific fields */
int tdm_slots;
int tdm_slots_tx;
int tdm_slots_rx;
u8 op_mode;
u8 dismod;
u8 num_serializer;

View file

@ -122,7 +122,7 @@ struct gpr_ibasic_rsp_accepted_t {
#define APR_SVC_MAJOR_VERSION(v) ((v >> 16) & 0xFF)
#define APR_SVC_MINOR_VERSION(v) (v & 0xFF)
typedef int (*gpr_port_cb) (struct gpr_resp_pkt *d, void *priv, int op);
typedef int (*gpr_port_cb) (const struct gpr_resp_pkt *d, void *priv, int op);
struct packet_router;
struct pkt_router_svc {
struct device *dev;
@ -155,8 +155,8 @@ struct apr_driver {
int (*probe)(struct apr_device *sl);
void (*remove)(struct apr_device *sl);
int (*callback)(struct apr_device *a,
struct apr_resp_pkt *d);
int (*gpr_callback)(struct gpr_resp_pkt *d, void *data, int op);
const struct apr_resp_pkt *d);
gpr_port_cb gpr_callback;
struct device_driver driver;
const struct apr_device_id *id_table;
};

View file

@ -904,6 +904,15 @@ extern int devm_spi_register_controller(struct device *dev,
struct spi_controller *ctlr);
extern void spi_unregister_controller(struct spi_controller *ctlr);
#if IS_ENABLED(CONFIG_OF)
extern struct spi_controller *of_find_spi_controller_by_node(struct device_node *node);
#else
static inline struct spi_controller *of_find_spi_controller_by_node(struct device_node *node)
{
return NULL;
}
#endif
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SPI_MASTER)
extern struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev);
extern struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,

View file

@ -1,23 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* AK4641 ALSA SoC Codec driver
*
* Copyright 2009 Philipp Zabel
*/
#ifndef __AK4641_H
#define __AK4641_H
/**
* struct ak4641_platform_data - platform specific AK4641 configuration
* @gpio_power: GPIO to control external power to AK4641
* @gpio_npdn: GPIO connected to AK4641 nPDN pin
*
* Both GPIO parameters are optional.
*/
struct ak4641_platform_data {
int gpio_power;
int gpio_npdn;
};
#endif /* __AK4641_H */

View file

@ -58,6 +58,9 @@ int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_
int cs_amp_set_efi_calibration_data(struct device *dev, int amp_index, int num_amps,
const struct cirrus_amp_cal_data *in_data);
int cs_amp_get_vendor_spkid(struct device *dev);
const char *cs_amp_devm_get_vendor_specific_variant_id(struct device *dev,
int ssid_vendor,
int ssid_device);
struct dentry *cs_amp_create_debugfs(struct device *dev);
static inline u64 cs_amp_cal_target_u64(const struct cirrus_amp_cal_data *data)

View file

@ -9,6 +9,7 @@
#ifndef __CS35L56_H
#define __CS35L56_H
#include <linux/bits.h>
#include <linux/debugfs.h>
#include <linux/firmware/cirrus/cs_dsp.h>
#include <linux/regulator/consumer.h>
@ -26,6 +27,9 @@ struct snd_ctl_elem_value;
#define CS35L56_GLOBAL_ENABLES 0x0002014
#define CS35L56_BLOCK_ENABLES 0x0002018
#define CS35L56_BLOCK_ENABLES2 0x000201C
#define CS35L56_SYNC_GPIO1_CFG 0x0002410
#define CS35L56_ASP2_DIO_GPIO13_CFG 0x0002440
#define CS35L56_UPDATE_REGS 0x0002A0C
#define CS35L56_REFCLK_INPUT 0x0002C04
#define CS35L56_GLOBAL_SAMPLE_RATE 0x0002C0C
#define CS35L56_OTP_MEM_53 0x00300D4
@ -65,6 +69,9 @@ struct snd_ctl_elem_value;
#define CS35L56_IRQ1_MASK_8 0x000E0AC
#define CS35L56_IRQ1_MASK_18 0x000E0D4
#define CS35L56_IRQ1_MASK_20 0x000E0DC
#define CS35L56_GPIO_STATUS1 0x000F000
#define CS35L56_GPIO1_CTRL1 0x000F008
#define CS35L56_GPIO13_CTRL1 0x000F038
#define CS35L56_MIXER_NGATE_CH1_CFG 0x0010004
#define CS35L56_MIXER_NGATE_CH2_CFG 0x0010008
#define CS35L56_DSP_MBOX_1_RAW 0x0011000
@ -130,6 +137,17 @@ struct snd_ctl_elem_value;
#define CS35L56_MTLREVID_MASK 0x0000000F
#define CS35L56_REVID_B0 0x000000B0
/* PAD_INTF */
#define CS35L56_PAD_GPIO_PULL_MASK GENMASK(3, 2)
#define CS35L56_PAD_GPIO_IE BIT(0)
#define CS35L56_PAD_PULL_NONE 0
#define CS35L56_PAD_PULL_UP 1
#define CS35L56_PAD_PULL_DOWN 2
/* UPDATE_REGS */
#define CS35L56_UPDT_GPIO_PRES BIT(6)
/* ASP_ENABLES1 */
#define CS35L56_ASP_RX2_EN_SHIFT 17
#define CS35L56_ASP_RX1_EN_SHIFT 16
@ -185,6 +203,12 @@ struct snd_ctl_elem_value;
/* MIXER_NGATE_CHn_CFG */
#define CS35L56_AUX_NGATE_CHn_EN 0x00000001
/* GPIOn_CTRL1 */
#define CS35L56_GPIO_DIR_MASK BIT(31)
#define CS35L56_GPIO_FN_MASK GENMASK(2, 0)
#define CS35L56_GPIO_FN_GPIO 0x00000001
/* Mixer input sources */
#define CS35L56_INPUT_SRC_NONE 0x00
#define CS35L56_INPUT_SRC_ASP1RX1 0x08
@ -279,6 +303,7 @@ struct snd_ctl_elem_value;
#define CS35L56_HALO_STATE_TIMEOUT_US 250000
#define CS35L56_RESET_PULSE_MIN_US 1100
#define CS35L56_WAKE_HOLD_TIME_US 1000
#define CS35L56_PAD_PULL_SETTLE_US 10
#define CS35L56_CALIBRATION_POLL_US (100 * USEC_PER_MSEC)
#define CS35L56_CALIBRATION_TIMEOUT_US (5 * USEC_PER_SEC)
@ -289,6 +314,9 @@ struct snd_ctl_elem_value;
#define CS35L56_NUM_BULK_SUPPLIES 3
#define CS35L56_NUM_DSP_REGIONS 5
#define CS35L56_MAX_GPIO 13
#define CS35L63_MAX_GPIO 9
/* Additional margin for SYSTEM_RESET to control port ready on SPI */
#define CS35L56_SPI_RESET_TO_PORT_READY_US (CS35L56_CONTROL_PORT_READY_US + 2500)
@ -338,6 +366,10 @@ struct cs35l56_base {
const struct cirrus_amp_cal_controls *calibration_controls;
struct dentry *debugfs;
u64 silicon_uid;
u8 onchip_spkid_gpios[5];
u8 num_onchip_spkid_gpios;
u8 onchip_spkid_pulls[5];
u8 num_onchip_spkid_pulls;
};
static inline bool cs35l56_is_otp_register(unsigned int reg)
@ -413,6 +445,11 @@ void cs35l56_warn_if_firmware_missing(struct cs35l56_base *cs35l56_base);
void cs35l56_log_tuning(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp);
int cs35l56_hw_init(struct cs35l56_base *cs35l56_base);
int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base);
int cs35l56_check_and_save_onchip_spkid_gpios(struct cs35l56_base *cs35l56_base,
const u32 *gpios, int num_gpios,
const u32 *pulls, int num_pulls);
int cs35l56_configure_onchip_spkid_pads(struct cs35l56_base *cs35l56_base);
int cs35l56_read_onchip_spkid(struct cs35l56_base *cs35l56_base);
int cs35l56_get_bclk_freq_id(unsigned int freq);
void cs35l56_fill_supply_names(struct regulator_bulk_data *data);

View file

@ -798,6 +798,7 @@ struct sdca_control_range {
* @sel: Identifier used for addressing.
* @nbits: Number of bits used in the Control.
* @values: Holds the Control value for constants and defaults.
* @reset: Defined reset value for the Control.
* @cn_list: A bitmask showing the valid Control Numbers within this Control,
* Control Numbers typically represent channels.
* @interrupt_position: SCDA interrupt line that will alert to changes on this
@ -808,6 +809,7 @@ struct sdca_control_range {
* @layers: Bitmask of access layers of the Control.
* @deferrable: Indicates if the access to the Control can be deferred.
* @has_default: Indicates the Control has a default value to be written.
* @has_reset: Indicates the Control has a defined reset value.
* @has_fixed: Indicates the Control only supports a single value.
*/
struct sdca_control {
@ -816,6 +818,7 @@ struct sdca_control {
int nbits;
int *values;
int reset;
u64 cn_list;
int interrupt_position;
@ -827,6 +830,7 @@ struct sdca_control {
bool deferrable;
bool is_volatile;
bool has_default;
bool has_reset;
bool has_fixed;
};

View file

@ -84,4 +84,11 @@ int sdca_irq_populate(struct sdca_function_data *function,
struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev,
struct regmap *regmap, int irq);
void sdca_irq_enable_early(struct sdca_function_data *function,
struct sdca_interrupt_info *info);
void sdca_irq_enable(struct sdca_function_data *function,
struct sdca_interrupt_info *info);
void sdca_irq_disable(struct sdca_function_data *function,
struct sdca_interrupt_info *info);
#endif

32
include/sound/sdca_jack.h Normal file
View file

@ -0,0 +1,32 @@
/* 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_JACK_H__
#define __SDCA_JACK_H__
struct sdca_interrupt;
struct snd_kcontrol;
struct snd_soc_jack;
/**
* struct jack_state - Jack state structure to keep data between interrupts
* @kctl: Pointer to the ALSA control attached to this jack
* @jack: Pointer to the ASoC jack struct for this jack
*/
struct jack_state {
struct snd_kcontrol *kctl;
struct snd_soc_jack *jack;
};
int sdca_jack_alloc_state(struct sdca_interrupt *interrupt);
int sdca_jack_process(struct sdca_interrupt *interrupt);
int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *jack);
int sdca_jack_report(struct sdca_interrupt *interrupt);
#endif // __SDCA_JACK_H__

View file

@ -43,6 +43,8 @@ struct snd_seq_device {
* Typically, call snd_device_free(dev->card, dev->driver_data)
*/
struct snd_seq_driver {
int (*probe)(struct snd_seq_device *dev);
void (*remove)(struct snd_seq_device *dev);
struct device_driver driver;
char *id;
int argsize;

View file

@ -37,6 +37,9 @@
#define RT5682_ACPI_HID "10EC5682"
#define RT5682S_ACPI_HID "RTL5682"
/* Texas Instruments */
#define TAS2563_ACPI_HID "TXNW2563"
enum snd_soc_acpi_intel_codec {
CODEC_NONE,
@ -63,6 +66,7 @@ enum snd_soc_acpi_intel_codec {
CODEC_RT1015P,
CODEC_RT1019P,
CODEC_RT1308,
CODEC_TAS2563,
};
enum snd_soc_acpi_intel_codec

View file

@ -237,8 +237,7 @@ struct snd_soc_component {
* the driver will be marked as BROKEN when these fields are removed.
*/
/* Don't use these, use snd_soc_component_get_dapm() */
struct snd_soc_dapm_context dapm;
struct snd_soc_dapm_context *dapm;
/* machine specific init */
int (*init)(struct snd_soc_component *component);
@ -268,12 +267,9 @@ struct snd_soc_component {
static inline struct snd_soc_dapm_context *snd_soc_component_to_dapm(
struct snd_soc_component *component)
{
return &component->dapm;
return component->dapm;
}
// FIXME
#define snd_soc_component_get_dapm snd_soc_component_to_dapm
/**
* snd_soc_component_cache_sync() - Sync the register cache with the hardware
* @component: COMPONENT to sync
@ -368,27 +364,6 @@ snd_soc_component_active(struct snd_soc_component *component)
return component->active;
}
/* component pin */
int snd_soc_component_enable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_disable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_nc_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_get_pin_status(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_force_enable_pin_unlocked(
struct snd_soc_component *component,
const char *pin);
/* component controls */
struct snd_kcontrol *snd_soc_component_get_kcontrol(struct snd_soc_component *component,
const char * const ctl);

View file

@ -20,6 +20,7 @@ struct regulator;
struct soc_enum;
struct snd_pcm_substream;
struct snd_soc_pcm_runtime;
struct snd_soc_dapm_context;
/* widget has no PM register bit */
#define SND_SOC_NOPM -1
@ -579,28 +580,6 @@ struct snd_soc_dapm_update {
bool has_second_set;
};
/* DAPM context */
struct snd_soc_dapm_context {
enum snd_soc_bias_level bias_level;
bool idle_bias; /* Use BIAS_OFF instead of STANDBY when false */
struct device *dev; /* from parent - for debug */ /* REMOVE ME */
struct snd_soc_component *component; /* parent component */
struct snd_soc_card *card; /* parent card */
/* used during DAPM updates */
enum snd_soc_bias_level target_bias_level;
struct list_head list;
struct snd_soc_dapm_widget *wcache_sink;
struct snd_soc_dapm_widget *wcache_source;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_dapm;
#endif
};
/* A list of widgets associated with an object, typically a snd_kcontrol */
struct snd_soc_dapm_widget_list {
int num_widgets;
@ -628,6 +607,8 @@ enum snd_soc_dapm_direction {
#define SND_SOC_DAPM_EP_SOURCE SND_SOC_DAPM_DIR_TO_EP(SND_SOC_DAPM_DIR_IN)
#define SND_SOC_DAPM_EP_SINK SND_SOC_DAPM_DIR_TO_EP(SND_SOC_DAPM_DIR_OUT)
struct snd_soc_dapm_context *snd_soc_dapm_alloc(struct device *dev);
int snd_soc_dapm_regulator_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event);
int snd_soc_dapm_clock_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event);
int snd_soc_dapm_pinctrl_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event);
@ -705,16 +686,6 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, co
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, const char *pin);
void snd_soc_dapm_mark_endpoints_dirty(struct snd_soc_card *card);
/*
* Marks the specified pin as being not connected, disabling it along
* any parent or child widgets. At present this is identical to
* snd_soc_dapm_disable_pin[_unlocked]() but in future it will be extended to do
* additional things such as disabling controls which only affect
* paths through the pin.
*/
#define snd_soc_dapm_nc_pin snd_soc_dapm_disable_pin
#define snd_soc_dapm_nc_pin_unlocked snd_soc_dapm_disable_pin_unlocked
/* dapm path query */
int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
struct snd_soc_dapm_widget_list **list,
@ -730,15 +701,6 @@ int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_so
enum snd_soc_bias_level snd_soc_dapm_get_bias_level(struct snd_soc_dapm_context *dapm);
void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level);
// REMOVE ME !!
#define snd_soc_component_force_bias_level(c, l) snd_soc_dapm_force_bias_level(&(c)->dapm, l)
#define snd_soc_component_get_bias_level(c) snd_soc_dapm_get_bias_level(&(c)->dapm)
#define snd_soc_component_init_bias_level(c, l) snd_soc_dapm_init_bias_level(&(c)->dapm, l)
#define snd_soc_dapm_kcontrol_widget snd_soc_dapm_kcontrol_to_widget
#define snd_soc_dapm_kcontrol_dapm snd_soc_dapm_kcontrol_to_dapm
#define dapm_kcontrol_get_value snd_soc_dapm_kcontrol_get_value
#define snd_soc_dapm_kcontrol_component snd_soc_dapm_kcontrol_to_component
#define for_each_dapm_widgets(list, i, widget) \
for ((i) = 0; \
(i) < list->num_widgets && (widget = list->widgets[i]); \

View file

@ -1076,7 +1076,7 @@ struct snd_soc_card {
struct list_head dobj_list;
/* Generic DAPM context for the card */
struct snd_soc_dapm_context dapm;
struct snd_soc_dapm_context *dapm;
struct snd_soc_dapm_stats dapm_stats;
#ifdef CONFIG_DEBUG_FS
@ -1136,7 +1136,7 @@ static inline int snd_soc_card_is_instantiated(struct snd_soc_card *card)
static inline struct snd_soc_dapm_context *snd_soc_card_to_dapm(struct snd_soc_card *card)
{
return &card->dapm;
return card->dapm;
}
/* SoC machine DAI configuration, glues a codec and cpu DAI together */

View file

@ -159,6 +159,9 @@ struct sof_dev_desc {
/* The platform supports DSPless mode */
bool dspless_mode_supported;
/* On demand DSP booting is possible on the platform */
bool on_demand_dsp_boot;
/* defaults paths for firmware, library and topology files */
const char *default_fw_path[SOF_IPC_TYPE_COUNT];
const char *default_lib_path[SOF_IPC_TYPE_COUNT];

View file

@ -352,6 +352,10 @@ struct sof_ipc4_base_module_cfg {
#define SOF_IPC4_MOD_EXT_DOMAIN_MASK BIT(28)
#define SOF_IPC4_MOD_EXT_DOMAIN(x) ((x) << SOF_IPC4_MOD_EXT_DOMAIN_SHIFT)
#define SOF_IPC4_MOD_EXT_EXTENDED_INIT_SHIFT 29
#define SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK BIT(29)
#define SOF_IPC4_MOD_EXT_EXTENDED_INIT(x) ((x) << SOF_IPC4_MOD_EXT_EXTENDED_SHIFT)
/* bind/unbind module ipc msg */
#define SOF_IPC4_MOD_EXT_DST_MOD_ID_SHIFT 0
#define SOF_IPC4_MOD_EXT_DST_MOD_ID_MASK GENMASK(15, 0)
@ -586,6 +590,77 @@ struct sof_ipc4_notify_module_data {
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL 0xA15A0000
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_PARAMID_MASK GENMASK(15, 0)
/*
* Macros for creating struct sof_ipc4_module_init_ext_init payload
* with its associated data. ext_init payload should be the first
* piece of payload following SOF_IPC4_MOD_INIT_INSTANCE msg, and its
* existence is indicated with SOF_IPC4_MOD_EXT_EXTENDED-bit.
*
* The macros below apply to sof_ipc4_module_init_ext_init.word0
*/
#define SOF_IPC4_MOD_INIT_EXT_RTOS_DOMAIN_SHIFT 0
#define SOF_IPC4_MOD_INIT_EXT_RTOS_DOMAIN_MASK BIT(0)
#define SOF_IPC4_MOD_INIT_EXT_RTOS_DOMAIN(x) ((x) << SOF_IPC4_MOD_INIT_EXT_RTOS_DOMAIN_SHIFT)
#define SOF_IPC4_MOD_INIT_EXT_GNA_USED_SHIFT 1
#define SOF_IPC4_MOD_INIT_EXT_GNA_USED_MASK BIT(1)
#define SOF_IPC4_MOD_INIT_EXT_GNA_USED(x) ((x) << SOF_IPC4_MOD_INIT_EXT_GNA_USED_SHIFT)
#define SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_SHIFT 2
#define SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_MASK BIT(2)
#define SOF_IPC4_MOD_INIT_EXT_DATA_ARRAY(x) ((x) << SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_SHIFT)
struct sof_ipc4_module_init_ext_init {
u32 word0;
u32 rsvd1;
u32 rsvd2;
} __packed __aligned(4);
/*
* SOF_IPC4_MOD_EXT_EXTENDED payload may be followed by arbitrary
* number of object array objects. SOF_IPC4_MOD_INIT_EXT_DATA_ARRAY
* -bit indicates that an array object follows struct
* sof_ipc4_module_init_ext_init.
*
* The object header's SOF_IPC4_MOD_INIT_EXT_OBJ_LAST-bit in struct
* sof_ipc4_module_init_ext_object indicates if the array is continued
* with another object. The header has also fields to identify the
* object, SOF_IPC4_MOD_INIT_EXT_OBJ_ID, and to indicate the object's
* size in 32-bit words, SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS, not
* including the header itself.
*
* The macros below apply to sof_ipc4_module_init_ext_object.header
*/
#define SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_SHIFT 0
#define SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_MASK BIT(0)
#define SOF_IPC4_MOD_INIT_EXT_OBJ_LAST(x) ((x) << SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_SHIFT)
#define SOF_IPC4_MOD_INIT_EXT_OBJ_ID_SHIFT 1
#define SOF_IPC4_MOD_INIT_EXT_OBJ_ID_MASK GENMASK(15, 1)
#define SOF_IPC4_MOD_INIT_EXT_OBJ_ID(x) ((x) << SOF_IPC4_MOD_INIT_EXT_OBJ_ID_SHIFT)
#define SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS_SHIFT 16
#define SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS_MASK GENMASK(31, 16)
#define SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS(x) ((x) << SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS_SHIFT)
struct sof_ipc4_module_init_ext_object {
u32 header;
u32 data[];
} __packed __aligned(4);
enum sof_ipc4_mod_init_ext_obj_id {
SOF_IPC4_MOD_INIT_DATA_ID_INVALID = 0,
SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA,
SOF_IPC4_MOD_INIT_DATA_ID_MAX = SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA,
};
/* DP module memory configuration data object for ext_init object array */
struct sof_ipc4_mod_init_ext_dp_memory_data {
u32 domain_id; /* userspace domain ID */
u32 stack_bytes; /* stack size in bytes, 0 means default size */
u32 heap_bytes; /* stack size in bytes, 0 means default size */
} __packed __aligned(4);
/** @}*/
#endif

View file

@ -2,7 +2,7 @@
//
// ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier
//
// Copyright (C) 2022 - 2025 Texas Instruments Incorporated
// Copyright (C) 2022 - 2026 Texas Instruments Incorporated
// https://www.ti.com
//
// The TAS2563/TAS2781 driver implements a flexible and configurable
@ -233,7 +233,6 @@ struct tasdevice_priv {
bool playback_started;
bool isacpi;
bool isspi;
bool is_user_space_calidata;
unsigned int global_addr;
int (*fw_parse_variable_header)(struct tasdevice_priv *tas_priv,

View file

@ -56,6 +56,9 @@
#define SOF_TKN_SCHED_LP_MODE 207
#define SOF_TKN_SCHED_MEM_USAGE 208
#define SOF_TKN_SCHED_USE_CHAIN_DMA 209
#define SOF_TKN_SCHED_KCPS 210
#define SOF_TKN_SCHED_DIRECTION 211
#define SOF_TKN_SCHED_DIRECTION_VALID 212
/* volume */
#define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250
@ -107,6 +110,9 @@
#define SOF_TKN_COMP_NO_WNAME_IN_KCONTROL_NAME 417
#define SOF_TKN_COMP_SCHED_DOMAIN 418
#define SOF_TKN_COMP_DOMAIN_ID 419
#define SOF_TKN_COMP_HEAP_BYTES_REQUIREMENT 420
#define SOF_TKN_COMP_STACK_BYTES_REQUIREMENT 421
/* SSP */
#define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500

View file

@ -18,16 +18,6 @@ config SND_ARMAACI
select SND_PCM
select SND_AC97_CODEC
config SND_PXA2XX_AC97
tristate "AC97 driver for the Intel PXA2xx chip"
depends on ARCH_PXA
select SND_AC97_CODEC
select SND_PXA2XX_LIB
select SND_PXA2XX_LIB_AC97
help
Say Y or M if you want to support any AC97 codec attached to
the PXA2xx AC97 interface.
endif # SND_ARM
config SND_PXA2XX_LIB

View file

@ -9,6 +9,3 @@ snd-aaci-y := aaci.o
obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2xx-lib.o
snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o
snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o
obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o
snd-pxa2xx-ac97-y := pxa2xx-ac97.o

View file

@ -13,10 +13,9 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/soc/pxa/cpu.h>
#include <sound/pxa2xx-lib.h>
@ -31,6 +30,7 @@ static volatile long gsr_bits;
static struct clk *ac97_clk;
static struct clk *ac97conf_clk;
static int reset_gpio;
struct gpio_desc *rst_gpio;
static void __iomem *ac97_reg_base;
/*
@ -321,7 +321,6 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
{
int ret;
int irq;
pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;
ac97_reg_base = devm_platform_ioremap_resource(dev, 0);
if (IS_ERR(ac97_reg_base)) {
@ -329,32 +328,15 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
return PTR_ERR(ac97_reg_base);
}
if (pdata) {
switch (pdata->reset_gpio) {
case 95:
case 113:
reset_gpio = pdata->reset_gpio;
break;
case 0:
reset_gpio = 113;
break;
case -1:
break;
default:
dev_err(&dev->dev, "Invalid reset GPIO %d\n",
pdata->reset_gpio);
}
} else if (!pdata && dev->dev.of_node) {
pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
pdata->reset_gpio = of_get_named_gpio(dev->dev.of_node,
"reset-gpios", 0);
if (pdata->reset_gpio == -ENOENT)
pdata->reset_gpio = -1;
else if (pdata->reset_gpio < 0)
return pdata->reset_gpio;
reset_gpio = pdata->reset_gpio;
if (dev->dev.of_node) {
/* Assert reset using GPIOD_OUT_HIGH, because reset is GPIO_ACTIVE_LOW */
rst_gpio = devm_gpiod_get(&dev->dev, "reset", GPIOD_OUT_HIGH);
ret = PTR_ERR(rst_gpio);
if (ret == -ENOENT)
reset_gpio = -1;
else if (ret)
return ret;
reset_gpio = desc_to_gpio(rst_gpio);
} else {
if (cpu_is_pxa27x())
reset_gpio = 113;
@ -367,13 +349,7 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
* here so that it is an output driven high when switching from
* AC97_nRESET alt function to generic gpio.
*/
ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH,
"pxa27x ac97 reset");
if (ret < 0) {
pr_err("%s: gpio_request_one() failed: %d\n",
__func__, ret);
goto err_conf;
}
gpiod_set_consumer_name(rst_gpio, "pxa27x ac97 reset");
pxa27x_configure_ac97reset(reset_gpio, false);
ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
@ -424,8 +400,6 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);
void pxa2xx_ac97_hw_remove(struct platform_device *dev)
{
if (cpu_is_pxa27x())
gpio_free(reset_gpio);
writel(readl(ac97_reg_base + GCR) | (GCR_ACLINK_OFF), ac97_reg_base + GCR);
free_irq(platform_get_irq(dev, 0), NULL);
if (ac97conf_clk) {

View file

@ -1,286 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip.
*
* Author: Nicolas Pitre
* Created: Dec 02, 2004
* Copyright: MontaVista Software Inc.
*/
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/initval.h>
#include <sound/pxa2xx-lib.h>
#include <sound/dmaengine_pcm.h>
#include <linux/platform_data/asoc-pxa.h>
static void pxa2xx_ac97_legacy_reset(struct snd_ac97 *ac97)
{
if (!pxa2xx_ac97_try_cold_reset())
pxa2xx_ac97_try_warm_reset();
pxa2xx_ac97_finish_reset();
}
static unsigned short pxa2xx_ac97_legacy_read(struct snd_ac97 *ac97,
unsigned short reg)
{
int ret;
ret = pxa2xx_ac97_read(ac97->num, reg);
if (ret < 0)
return 0;
else
return (unsigned short)(ret & 0xffff);
}
static void pxa2xx_ac97_legacy_write(struct snd_ac97 *ac97,
unsigned short reg, unsigned short val)
{
pxa2xx_ac97_write(ac97->num, reg, val);
}
static const struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
.read = pxa2xx_ac97_legacy_read,
.write = pxa2xx_ac97_legacy_write,
.reset = pxa2xx_ac97_legacy_reset,
};
static struct snd_pcm *pxa2xx_ac97_pcm;
static struct snd_ac97 *pxa2xx_ac97_ac97;
static int pxa2xx_ac97_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
pxa2xx_audio_ops_t *platform_ops;
int ret, i;
ret = pxa2xx_pcm_open(substream);
if (ret)
return ret;
runtime->hw.channels_min = 2;
runtime->hw.channels_max = 2;
i = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_RATES_FRONT_DAC : AC97_RATES_ADC;
runtime->hw.rates = pxa2xx_ac97_ac97->rates[i];
snd_pcm_limit_hw_rates(runtime);
platform_ops = substream->pcm->card->dev->platform_data;
if (platform_ops && platform_ops->startup) {
ret = platform_ops->startup(substream, platform_ops->priv);
if (ret < 0)
pxa2xx_pcm_close(substream);
}
return ret;
}
static int pxa2xx_ac97_pcm_close(struct snd_pcm_substream *substream)
{
pxa2xx_audio_ops_t *platform_ops;
platform_ops = substream->pcm->card->dev->platform_data;
if (platform_ops && platform_ops->shutdown)
platform_ops->shutdown(substream, platform_ops->priv);
return 0;
}
static int pxa2xx_ac97_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
int ret;
ret = pxa2xx_pcm_prepare(substream);
if (ret < 0)
return ret;
return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate);
}
static int pxa2xx_ac97_do_suspend(struct snd_card *card)
{
pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
snd_ac97_suspend(pxa2xx_ac97_ac97);
if (platform_ops && platform_ops->suspend)
platform_ops->suspend(platform_ops->priv);
return pxa2xx_ac97_hw_suspend();
}
static int pxa2xx_ac97_do_resume(struct snd_card *card)
{
pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
int rc;
rc = pxa2xx_ac97_hw_resume();
if (rc)
return rc;
if (platform_ops && platform_ops->resume)
platform_ops->resume(platform_ops->priv);
snd_ac97_resume(pxa2xx_ac97_ac97);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
static int pxa2xx_ac97_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
int ret = 0;
if (card)
ret = pxa2xx_ac97_do_suspend(card);
return ret;
}
static int pxa2xx_ac97_resume(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
int ret = 0;
if (card)
ret = pxa2xx_ac97_do_resume(card);
return ret;
}
static DEFINE_SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, pxa2xx_ac97_suspend, pxa2xx_ac97_resume);
static const struct snd_pcm_ops pxa2xx_ac97_pcm_ops = {
.open = pxa2xx_ac97_pcm_open,
.close = pxa2xx_ac97_pcm_close,
.hw_params = pxa2xx_pcm_hw_params,
.prepare = pxa2xx_ac97_pcm_prepare,
.trigger = pxa2xx_pcm_trigger,
.pointer = pxa2xx_pcm_pointer,
};
static int pxa2xx_ac97_pcm_new(struct snd_card *card)
{
struct snd_pcm *pcm;
int ret;
ret = snd_pcm_new(card, "PXA2xx-PCM", 0, 1, 1, &pcm);
if (ret)
goto out;
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret)
goto out;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pxa2xx_ac97_pcm_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pxa2xx_ac97_pcm_ops);
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm);
if (ret)
goto out;
pxa2xx_ac97_pcm = pcm;
ret = 0;
out:
return ret;
}
static int pxa2xx_ac97_probe(struct platform_device *dev)
{
struct snd_card *card;
struct snd_ac97_bus *ac97_bus;
struct snd_ac97_template ac97_template;
int ret;
pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;
if (dev->id >= 0) {
dev_err(&dev->dev, "PXA2xx has only one AC97 port.\n");
ret = -ENXIO;
goto err_dev;
}
ret = snd_card_new(&dev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
THIS_MODULE, 0, &card);
if (ret < 0)
goto err;
strscpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
ret = pxa2xx_ac97_pcm_new(card);
if (ret)
goto err;
ret = pxa2xx_ac97_hw_probe(dev);
if (ret)
goto err;
ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);
if (ret)
goto err_remove;
memset(&ac97_template, 0, sizeof(ac97_template));
ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97);
if (ret)
goto err_remove;
snprintf(card->shortname, sizeof(card->shortname),
"%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97));
snprintf(card->longname, sizeof(card->longname),
"%s (%s)", dev->dev.driver->name, card->mixername);
if (pdata && pdata->codec_pdata[0])
snd_ac97_dev_add_pdata(ac97_bus->codec[0], pdata->codec_pdata[0]);
ret = snd_card_register(card);
if (ret == 0) {
platform_set_drvdata(dev, card);
return 0;
}
err_remove:
pxa2xx_ac97_hw_remove(dev);
err:
if (card)
snd_card_free(card);
err_dev:
return ret;
}
static void pxa2xx_ac97_remove(struct platform_device *dev)
{
struct snd_card *card = platform_get_drvdata(dev);
if (card) {
snd_card_free(card);
pxa2xx_ac97_hw_remove(dev);
}
}
static struct platform_driver pxa2xx_ac97_driver = {
.probe = pxa2xx_ac97_probe,
.remove = pxa2xx_ac97_remove,
.driver = {
.name = "pxa2xx-ac97",
.pm = &pxa2xx_ac97_pm_ops,
},
};
module_platform_driver(pxa2xx_ac97_driver);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pxa2xx-ac97");

View file

@ -514,12 +514,12 @@ static int
snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
{
int retval;
struct snd_compr_codec_caps *caps __free(kfree) = NULL;
if (!stream->ops->get_codec_caps)
return -ENXIO;
caps = kzalloc(sizeof(*caps), GFP_KERNEL);
struct snd_compr_codec_caps *caps __free(kfree) =
kzalloc(sizeof(*caps), GFP_KERNEL);
if (!caps)
return -ENOMEM;
@ -647,7 +647,6 @@ snd_compress_check_input(struct snd_compr_stream *stream, struct snd_compr_param
static int
snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
{
struct snd_compr_params *params __free(kfree) = NULL;
int retval;
if (stream->runtime->state == SNDRV_PCM_STATE_OPEN || stream->next_track) {
@ -655,7 +654,9 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
* we should allow parameter change only when stream has been
* opened not in other cases
*/
params = memdup_user((void __user *)arg, sizeof(*params));
struct snd_compr_params *params __free(kfree) =
memdup_user((void __user *)arg, sizeof(*params));
if (IS_ERR(params))
return PTR_ERR(params);
@ -687,13 +688,13 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
static int
snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
{
struct snd_codec *params __free(kfree) = NULL;
int retval;
if (!stream->ops->get_params)
return -EBADFD;
params = kzalloc(sizeof(*params), GFP_KERNEL);
struct snd_codec *params __free(kfree) =
kzalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
retval = stream->ops->get_params(stream, params);
@ -1104,12 +1105,13 @@ cleanup:
static int snd_compr_task_create(struct snd_compr_stream *stream, unsigned long arg)
{
struct snd_compr_task *task __free(kfree) = NULL;
int retval;
if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
return -EPERM;
task = memdup_user((void __user *)arg, sizeof(*task));
struct snd_compr_task *task __free(kfree) =
memdup_user((void __user *)arg, sizeof(*task));
if (IS_ERR(task))
return PTR_ERR(task);
retval = snd_compr_task_new(stream, task);
@ -1165,12 +1167,13 @@ static int snd_compr_task_start(struct snd_compr_stream *stream, struct snd_comp
static int snd_compr_task_start_ioctl(struct snd_compr_stream *stream, unsigned long arg)
{
struct snd_compr_task *task __free(kfree) = NULL;
int retval;
if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
return -EPERM;
task = memdup_user((void __user *)arg, sizeof(*task));
struct snd_compr_task *task __free(kfree) =
memdup_user((void __user *)arg, sizeof(*task));
if (IS_ERR(task))
return PTR_ERR(task);
retval = snd_compr_task_start(stream, task);
@ -1256,12 +1259,13 @@ static int snd_compr_task_status(struct snd_compr_stream *stream,
static int snd_compr_task_status_ioctl(struct snd_compr_stream *stream, unsigned long arg)
{
struct snd_compr_task_status *status __free(kfree) = NULL;
int retval;
if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
return -EPERM;
status = memdup_user((void __user *)arg, sizeof(*status));
struct snd_compr_task_status *status __free(kfree) =
memdup_user((void __user *)arg, sizeof(*status));
if (IS_ERR(status))
return PTR_ERR(status);
retval = snd_compr_task_status(stream, status);

View file

@ -867,9 +867,9 @@ EXPORT_SYMBOL(snd_ctl_find_id);
static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
unsigned int cmd, void __user *arg)
{
struct snd_ctl_card_info *info __free(kfree) = NULL;
struct snd_ctl_card_info *info __free(kfree) =
kzalloc(sizeof(*info), GFP_KERNEL);
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
scoped_guard(rwsem_read, &snd_ioctl_rwsem) {
@ -1244,10 +1244,10 @@ static int snd_ctl_elem_read(struct snd_card *card,
static int snd_ctl_elem_read_user(struct snd_card *card,
struct snd_ctl_elem_value __user *_control)
{
struct snd_ctl_elem_value *control __free(kfree) = NULL;
int result;
struct snd_ctl_elem_value *control __free(kfree) =
memdup_user(_control, sizeof(*control));
control = memdup_user(_control, sizeof(*control));
if (IS_ERR(control))
return PTR_ERR(control);
@ -1320,11 +1320,11 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
struct snd_ctl_elem_value __user *_control)
{
struct snd_ctl_elem_value *control __free(kfree) = NULL;
struct snd_card *card;
int result;
struct snd_ctl_elem_value *control __free(kfree) =
memdup_user(_control, sizeof(*control));
control = memdup_user(_control, sizeof(*control));
if (IS_ERR(control))
return PTR_ERR(control);

View file

@ -80,10 +80,10 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
struct snd_ctl_elem_info32 __user *data32)
{
struct snd_card *card = ctl->card;
struct snd_ctl_elem_info *data __free(kfree) = NULL;
int err;
struct snd_ctl_elem_info *data __free(kfree) =
kzalloc(sizeof(*data), GFP_KERNEL);
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (! data)
return -ENOMEM;
@ -169,14 +169,15 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
int *countp)
{
struct snd_kcontrol *kctl;
struct snd_ctl_elem_info *info __free(kfree) = NULL;
int err;
guard(rwsem_read)(&card->controls_rwsem);
kctl = snd_ctl_find_id(card, id);
if (!kctl)
return -ENOENT;
info = kzalloc(sizeof(*info), GFP_KERNEL);
struct snd_ctl_elem_info *info __free(kfree) =
kzalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL)
return -ENOMEM;
info->id = *id;
@ -280,10 +281,10 @@ static int copy_ctl_value_to_user(void __user *userdata,
static int __ctl_elem_read_user(struct snd_card *card,
void __user *userdata, void __user *valuep)
{
struct snd_ctl_elem_value *data __free(kfree) = NULL;
int err, type, count;
struct snd_ctl_elem_value *data __free(kfree) =
kzalloc(sizeof(*data), GFP_KERNEL);
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@ -314,11 +315,11 @@ static int ctl_elem_read_user(struct snd_card *card,
static int __ctl_elem_write_user(struct snd_ctl_file *file,
void __user *userdata, void __user *valuep)
{
struct snd_ctl_elem_value *data __free(kfree) = NULL;
struct snd_card *card = file->card;
int err, type, count;
struct snd_ctl_elem_value *data __free(kfree) =
kzalloc(sizeof(*data), GFP_KERNEL);
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@ -378,9 +379,9 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
struct snd_ctl_elem_info32 __user *data32,
int replace)
{
struct snd_ctl_elem_info *data __free(kfree) = NULL;
struct snd_ctl_elem_info *data __free(kfree) =
kzalloc(sizeof(*data), GFP_KERNEL);
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (! data)
return -ENOMEM;

View file

@ -245,12 +245,12 @@ DEFINE_FREE(snd_card_unref, struct snd_card *, if (_T) snd_card_unref(_T))
static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id,
unsigned int group, bool set)
{
struct snd_card *card __free(snd_card_unref) = NULL;
struct snd_kcontrol *kctl;
struct snd_kcontrol_volatile *vd;
unsigned int ioff, access, new_access;
struct snd_card *card __free(snd_card_unref) =
snd_card_ref(card_number);
card = snd_card_ref(card_number);
if (!card)
return -ENXIO;
guard(rwsem_write)(&card->controls_rwsem);
@ -302,13 +302,13 @@ static void snd_ctl_led_clean(struct snd_card *card)
static int snd_ctl_led_reset(int card_number, unsigned int group)
{
struct snd_card *card __free(snd_card_unref) = NULL;
struct snd_ctl_led_ctl *lctl, *_lctl;
struct snd_ctl_led *led;
struct snd_kcontrol_volatile *vd;
bool change = false;
struct snd_card *card __free(snd_card_unref) =
snd_card_ref(card_number);
card = snd_card_ref(card_number);
if (!card)
return -ENXIO;
@ -598,11 +598,11 @@ static ssize_t list_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
struct snd_card *card __free(snd_card_unref) = NULL;
struct snd_ctl_led_ctl *lctl;
size_t l = 0;
struct snd_card *card __free(snd_card_unref) =
snd_card_ref(led_card->number);
card = snd_card_ref(led_card->number);
if (!card)
return -ENXIO;
guard(rwsem_read)(&card->controls_rwsem);

View file

@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/string.h>
#include <sound/core.h>
#include <sound/control.h>
@ -46,17 +47,20 @@ static int get_available_index(struct snd_card *card, const char *name)
return sid.index;
}
static void jack_kctl_name_gen(char *name, const char *src_name, int size)
static void jack_kctl_name_gen(char *name, const char *src_name, size_t size)
{
size_t count = strlen(src_name);
bool need_cat = true;
const char *suf = " Jack";
size_t suf_len = strlen(suf);
bool append_suf = true;
/* remove redundant " Jack" from src_name */
if (count >= 5)
need_cat = strncmp(&src_name[count - 5], " Jack", 5) ? true : false;
snprintf(name, size, need_cat ? "%s Jack" : "%s", src_name);
if (count >= suf_len)
append_suf = strncmp(&src_name[count - suf_len], suf, suf_len) != 0;
if (append_suf)
snprintf(name, size, "%s%s", src_name, suf);
else
strscpy(name, src_name, size);
}
struct snd_kcontrol *

View file

@ -517,19 +517,22 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
unsigned int numid,
int *left, int *right)
{
struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
struct snd_kcontrol *kctl;
struct snd_card *card = fmixer->card;
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
if (card->shutdown)
return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
struct snd_ctl_elem_info *uinfo __free(kfree) =
kzalloc(sizeof(*uinfo), GFP_KERNEL);
struct snd_ctl_elem_value *uctl __free(kfree) =
kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
return;
if (kctl->info(kctl, uinfo))
@ -550,19 +553,22 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer,
int *left, int *right,
int route)
{
struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
struct snd_kcontrol *kctl;
struct snd_card *card = fmixer->card;
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
if (card->shutdown)
return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
struct snd_ctl_elem_info *uinfo __free(kfree) =
kzalloc(sizeof(*uinfo), GFP_KERNEL);
struct snd_ctl_elem_value *uctl __free(kfree) =
kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
return;
if (kctl->info(kctl, uinfo))
@ -609,8 +615,6 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
unsigned int numid,
int left, int right)
{
struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
struct snd_kcontrol *kctl;
struct snd_card *card = fmixer->card;
int res;
@ -618,11 +622,16 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
if (card->shutdown)
return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
struct snd_ctl_elem_info *uinfo __free(kfree) =
kzalloc(sizeof(*uinfo), GFP_KERNEL);
struct snd_ctl_elem_value *uctl __free(kfree) =
kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
return;
if (kctl->info(kctl, uinfo))
@ -646,8 +655,6 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
int left, int right,
int route)
{
struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
struct snd_kcontrol *kctl;
struct snd_card *card = fmixer->card;
int res;
@ -655,11 +662,16 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
if (card->shutdown)
return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
struct snd_ctl_elem_info *uinfo __free(kfree) =
kzalloc(sizeof(*uinfo), GFP_KERNEL);
struct snd_ctl_elem_value *uctl __free(kfree) =
kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
return;
if (kctl->info(kctl, uinfo))
@ -783,15 +795,17 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
struct snd_kcontrol *kctl;
struct snd_mixer_oss_slot *pslot;
struct slot *slot;
struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
int err, idx;
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
struct snd_ctl_elem_info *uinfo __free(kfree) =
kzalloc(sizeof(*uinfo), GFP_KERNEL);
struct snd_ctl_elem_value *uctl __free(kfree) =
kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
return -ENOMEM;
guard(rwsem_read)(&card->controls_rwsem);
if (card->shutdown)
return -ENODEV;
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
if (!kctl)
return -ENOENT;
@ -825,16 +839,18 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
struct snd_kcontrol *kctl;
struct snd_mixer_oss_slot *pslot;
struct slot *slot = NULL;
struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
int err;
unsigned int idx;
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
struct snd_ctl_elem_info *uinfo __free(kfree) =
kzalloc(sizeof(*uinfo), GFP_KERNEL);
struct snd_ctl_elem_value *uctl __free(kfree) =
kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
return -ENOMEM;
guard(rwsem_read)(&card->controls_rwsem);
if (card->shutdown)
return -ENODEV;
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
if (!kctl)
return -ENOENT;
@ -872,18 +888,20 @@ struct snd_mixer_oss_assign_table {
static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *slot, const char *name, int index, int item)
{
struct snd_ctl_elem_info *info __free(kfree) = NULL;
struct snd_kcontrol *kcontrol;
struct snd_card *card = mixer->card;
int err;
struct snd_ctl_elem_info *info __free(kfree) =
kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
scoped_guard(rwsem_read, &card->controls_rwsem) {
if (card->shutdown)
return -ENODEV;
kcontrol = snd_mixer_oss_test_id(mixer, name, index);
if (kcontrol == NULL)
return 0;
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
err = kcontrol->info(kcontrol, info);
if (err < 0)
return err;
@ -1002,13 +1020,15 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer,
if (snd_mixer_oss_build_test_all(mixer, ptr, &slot))
return 0;
guard(rwsem_read)(&mixer->card->controls_rwsem);
if (mixer->card->shutdown)
return -ENODEV;
kctl = NULL;
if (!ptr->index)
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
if (kctl) {
struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
struct snd_ctl_elem_info *uinfo __free(kfree) =
kzalloc(sizeof(*uinfo), GFP_KERNEL);
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
if (!uinfo)
return -ENOMEM;

View file

@ -377,7 +377,6 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
snd_pcm_hw_param_t var, unsigned int best,
int *dir)
{
struct snd_pcm_hw_params *save __free(kfree) = NULL;
int v;
unsigned int saved_min;
int last = 0;
@ -397,19 +396,22 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
maxdir = 1;
max--;
}
save = kmalloc(sizeof(*save), GFP_KERNEL);
struct snd_pcm_hw_params *save __free(kfree) =
kmalloc(sizeof(*save), GFP_KERNEL);
if (save == NULL)
return -ENOMEM;
*save = *params;
saved_min = min;
min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
if (min >= 0) {
struct snd_pcm_hw_params *params1 __free(kfree) = NULL;
if (max < 0)
goto _end;
if ((unsigned int)min == saved_min && mindir == valdir)
goto _end;
params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
struct snd_pcm_hw_params *params1 __free(kfree) =
kmalloc(sizeof(*params1), GFP_KERNEL);
if (params1 == NULL)
return -ENOMEM;
*params1 = *save;
@ -781,10 +783,10 @@ static int choose_rate(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, unsigned int best_rate)
{
const struct snd_interval *it;
struct snd_pcm_hw_params *save __free(kfree) = NULL;
unsigned int rate, prev;
save = kmalloc(sizeof(*save), GFP_KERNEL);
struct snd_pcm_hw_params *save __free(kfree) =
kmalloc(sizeof(*save), GFP_KERNEL);
if (save == NULL)
return -ENOMEM;
*save = *params;
@ -1836,7 +1838,6 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
struct snd_pcm_substream *substream;
int err;
int direct;
struct snd_pcm_hw_params *params __free(kfree) = NULL;
unsigned int formats = 0;
const struct snd_mask *format_mask;
int fmt;
@ -1856,7 +1857,9 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
AFMT_S32_LE | AFMT_S32_BE |
AFMT_S24_LE | AFMT_S24_BE |
AFMT_S24_PACKED;
params = kmalloc(sizeof(*params), GFP_KERNEL);
struct snd_pcm_hw_params *params __free(kfree) =
kmalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
_snd_pcm_hw_params_any(params);

View file

@ -328,13 +328,13 @@ static const char *snd_pcm_oss_format_name(int format)
static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
struct snd_info_buffer *buffer)
{
struct snd_pcm_info *info __free(kfree) = NULL;
int err;
if (! substream)
return;
info = kmalloc(sizeof(*info), GFP_KERNEL);
struct snd_pcm_info *info __free(kfree) =
kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return;

View file

@ -235,7 +235,6 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
int refine,
struct snd_pcm_hw_params32 __user *data32)
{
struct snd_pcm_hw_params *data __free(kfree) = NULL;
struct snd_pcm_runtime *runtime;
int err;
@ -243,7 +242,8 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
if (!runtime)
return -ENOTTY;
data = kmalloc(sizeof(*data), GFP_KERNEL);
struct snd_pcm_hw_params *data __free(kfree) =
kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@ -332,7 +332,6 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
compat_caddr_t buf;
compat_caddr_t __user *bufptr;
u32 frames;
void __user **bufs __free(kfree) = NULL;
int err, ch, i;
if (! substream->runtime)
@ -349,7 +348,9 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
get_user(frames, &data32->frames))
return -EFAULT;
bufptr = compat_ptr(buf);
bufs = kmalloc_array(ch, sizeof(void __user *), GFP_KERNEL);
void __user **bufs __free(kfree) =
kmalloc_array(ch, sizeof(void __user *), GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < ch; i++) {

View file

@ -242,10 +242,10 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
int snd_pcm_info_user(struct snd_pcm_substream *substream,
struct snd_pcm_info __user * _info)
{
struct snd_pcm_info *info __free(kfree) = NULL;
int err;
struct snd_pcm_info *info __free(kfree) =
kmalloc(sizeof(*info), GFP_KERNEL);
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
err = snd_pcm_info(substream, info);
@ -364,7 +364,6 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
struct snd_pcm_hw_constraints *constrs =
&substream->runtime->hw_constraints;
unsigned int k;
unsigned int *rstamps __free(kfree) = NULL;
unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
unsigned int stamp;
struct snd_pcm_hw_rule *r;
@ -380,7 +379,8 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
* Each member of 'rstamps' array represents the sequence number of
* recent application of corresponding rule.
*/
rstamps = kcalloc(constrs->rules_num, sizeof(unsigned int), GFP_KERNEL);
unsigned int *rstamps __free(kfree) =
kcalloc(constrs->rules_num, sizeof(unsigned int), GFP_KERNEL);
if (!rstamps)
return -ENOMEM;
@ -583,10 +583,10 @@ EXPORT_SYMBOL(snd_pcm_hw_refine);
static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params __user * _params)
{
struct snd_pcm_hw_params *params __free(kfree) = NULL;
int err;
struct snd_pcm_hw_params *params __free(kfree) =
memdup_user(_params, sizeof(*params));
params = memdup_user(_params, sizeof(*params));
if (IS_ERR(params))
return PTR_ERR(params);
@ -889,10 +889,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params __user * _params)
{
struct snd_pcm_hw_params *params __free(kfree) = NULL;
int err;
struct snd_pcm_hw_params *params __free(kfree) =
memdup_user(_params, sizeof(*params));
params = memdup_user(_params, sizeof(*params));
if (IS_ERR(params))
return PTR_ERR(params);
@ -2267,7 +2267,6 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream1;
struct snd_pcm_group *group __free(kfree) = NULL;
struct snd_pcm_group *target_group;
bool nonatomic = substream->pcm->nonatomic;
CLASS(fd, f)(fd);
@ -2283,7 +2282,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
if (substream == substream1)
return -EINVAL;
group = kzalloc(sizeof(*group), GFP_KERNEL);
struct snd_pcm_group *group __free(kfree) =
kzalloc(sizeof(*group), GFP_KERNEL);
if (!group)
return -ENOMEM;
snd_pcm_group_init(group);
@ -3577,7 +3577,6 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result;
unsigned long i;
void __user **bufs __free(kfree) = NULL;
snd_pcm_uframes_t frames;
const struct iovec *iov = iter_iov(to);
@ -3596,7 +3595,9 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
if (!frame_aligned(runtime, iov->iov_len))
return -EINVAL;
frames = bytes_to_samples(runtime, iov->iov_len);
bufs = kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL);
void __user **bufs __free(kfree) =
kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < to->nr_segs; ++i) {
@ -3616,7 +3617,6 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result;
unsigned long i;
void __user **bufs __free(kfree) = NULL;
snd_pcm_uframes_t frames;
const struct iovec *iov = iter_iov(from);
@ -3634,7 +3634,9 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
!frame_aligned(runtime, iov->iov_len))
return -EINVAL;
frames = bytes_to_samples(runtime, iov->iov_len);
bufs = kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL);
void __user **bufs __free(kfree) =
kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < from->nr_segs; ++i) {
@ -4106,15 +4108,15 @@ static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *opara
static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params_old __user * _oparams)
{
struct snd_pcm_hw_params *params __free(kfree) = NULL;
struct snd_pcm_hw_params_old *oparams __free(kfree) = NULL;
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
struct snd_pcm_hw_params *params __free(kfree) =
kmalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
oparams = memdup_user(_oparams, sizeof(*oparams));
struct snd_pcm_hw_params_old *oparams __free(kfree) =
memdup_user(_oparams, sizeof(*oparams));
if (IS_ERR(oparams))
return PTR_ERR(oparams);
snd_pcm_hw_convert_from_old_params(params, oparams);
@ -4135,15 +4137,15 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params_old __user * _oparams)
{
struct snd_pcm_hw_params *params __free(kfree) = NULL;
struct snd_pcm_hw_params_old *oparams __free(kfree) = NULL;
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
struct snd_pcm_hw_params *params __free(kfree) =
kmalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
oparams = memdup_user(_oparams, sizeof(*oparams));
struct snd_pcm_hw_params_old *oparams __free(kfree) =
memdup_user(_oparams, sizeof(*oparams));
if (IS_ERR(oparams))
return PTR_ERR(oparams);

View file

@ -54,10 +54,10 @@ static __poll_t odev_poll(struct file *file, poll_table * wait);
*/
static struct snd_seq_driver seq_oss_synth_driver = {
.probe = snd_seq_oss_synth_probe,
.remove = snd_seq_oss_synth_remove,
.driver = {
.name = KBUILD_MODNAME,
.probe = snd_seq_oss_synth_probe,
.remove = snd_seq_oss_synth_remove,
},
.id = SNDRV_SEQ_DEV_ID_OSS,
.argsize = sizeof(struct snd_seq_oss_reg),

View file

@ -63,10 +63,10 @@ int __init
snd_seq_oss_create_client(void)
{
int rc;
struct snd_seq_port_info *port __free(kfree) = NULL;
struct snd_seq_port_callback port_callback;
struct snd_seq_port_info *port __free(kfree) =
kzalloc(sizeof(*port), GFP_KERNEL);
port = kzalloc(sizeof(*port), GFP_KERNEL);
if (!port)
return -ENOMEM;

View file

@ -65,11 +65,11 @@ static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev,
int
snd_seq_oss_midi_lookup_ports(int client)
{
struct snd_seq_client_info *clinfo __free(kfree) = NULL;
struct snd_seq_port_info *pinfo __free(kfree) = NULL;
struct snd_seq_client_info *clinfo __free(kfree) =
kzalloc(sizeof(*clinfo), GFP_KERNEL);
struct snd_seq_port_info *pinfo __free(kfree) =
kzalloc(sizeof(*pinfo), GFP_KERNEL);
clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
if (!clinfo || !pinfo)
return -ENOMEM;
clinfo->client = -1;
@ -305,10 +305,10 @@ int
snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
{
int perm;
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
struct snd_seq_port_subscribe subs;
struct seq_oss_midi *mdev __free(seq_oss_midi) =
get_mididev(dp, dev);
mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV;
@ -364,10 +364,10 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
int
snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
{
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
struct snd_seq_port_subscribe subs;
struct seq_oss_midi *mdev __free(seq_oss_midi) =
get_mididev(dp, dev);
mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV;
guard(mutex)(&mdev->open_mutex);
@ -399,10 +399,10 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
int
snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
{
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
int mode;
struct seq_oss_midi *mdev __free(seq_oss_midi) =
get_mididev(dp, dev);
mdev = get_mididev(dp, dev);
if (!mdev)
return 0;
@ -422,9 +422,9 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
void
snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
{
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
struct seq_oss_midi *mdev __free(seq_oss_midi) =
get_mididev(dp, dev);
mdev = get_mididev(dp, dev);
if (!mdev)
return;
if (!mdev->opened)
@ -468,9 +468,9 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
void
snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr)
{
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
struct seq_oss_midi *mdev __free(seq_oss_midi) =
get_mididev(dp, dev);
mdev = get_mididev(dp, dev);
if (!mdev)
return;
addr->client = mdev->client;
@ -485,11 +485,11 @@ int
snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data)
{
struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
if (dp->readq == NULL)
return 0;
mdev = find_slot(ev->source.client, ev->source.port);
struct seq_oss_midi *mdev __free(seq_oss_midi) =
find_slot(ev->source.client, ev->source.port);
if (!mdev)
return 0;
if (!(mdev->opened & PERM_READ))
@ -595,9 +595,9 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq
int
snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
{
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
struct seq_oss_midi *mdev __free(seq_oss_midi) =
get_mididev(dp, dev);
mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV;
if (snd_midi_event_encode_byte(mdev->coder, c, ev)) {
@ -613,9 +613,9 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru
int
snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf)
{
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
struct seq_oss_midi *mdev __free(seq_oss_midi) =
get_mididev(dp, dev);
mdev = get_mididev(dp, dev);
if (!mdev)
return -ENXIO;
inf->device = dev;
@ -651,10 +651,9 @@ snd_seq_oss_midi_info_read(struct snd_info_buffer *buf)
snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs);
for (i = 0; i < max_midi_devs; i++) {
struct seq_oss_midi *mdev __free(seq_oss_midi) = NULL;
snd_iprintf(buf, "\nmidi %d: ", i);
mdev = get_mdev(i);
struct seq_oss_midi *mdev __free(seq_oss_midi) =
get_mdev(i);
if (mdev == NULL) {
snd_iprintf(buf, "*empty*\n");
continue;

View file

@ -80,9 +80,8 @@ snd_seq_oss_synth_init(void)
* registration of the synth device
*/
int
snd_seq_oss_synth_probe(struct device *_dev)
snd_seq_oss_synth_probe(struct snd_seq_device *dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
int i;
struct seq_oss_synth *rec;
struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
@ -128,10 +127,9 @@ snd_seq_oss_synth_probe(struct device *_dev)
}
int
snd_seq_oss_synth_remove(struct device *_dev)
void
snd_seq_oss_synth_remove(struct snd_seq_device *dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
int index;
struct seq_oss_synth *rec = dev->driver_data;
@ -142,7 +140,7 @@ snd_seq_oss_synth_remove(struct device *_dev)
}
if (index >= max_synth_devs) {
pr_err("ALSA: seq_oss: can't unregister synth\n");
return -EINVAL;
return;
}
synth_devs[index] = NULL;
if (index == max_synth_devs - 1) {
@ -160,8 +158,6 @@ snd_seq_oss_synth_remove(struct device *_dev)
snd_use_lock_sync(&rec->use_lock);
kfree(rec);
return 0;
}
@ -368,7 +364,6 @@ reset_channels(struct seq_oss_synthinfo *info)
void
snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
{
struct seq_oss_synth *rec __free(seq_oss_synth) = NULL;
struct seq_oss_synthinfo *info;
info = get_synthinfo_nospec(dp, dev);
@ -391,7 +386,8 @@ snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
return;
}
rec = get_sdev(dev);
struct seq_oss_synth *rec __free(seq_oss_synth) =
get_sdev(dev);
if (rec == NULL)
return;
if (rec->oper.reset) {
@ -415,7 +411,6 @@ int
snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
const char __user *buf, int p, int c)
{
struct seq_oss_synth *rec __free(seq_oss_synth) = NULL;
struct seq_oss_synthinfo *info;
info = get_synthinfo_nospec(dp, dev);
@ -424,7 +419,9 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
if (info->is_midi)
return 0;
rec = get_synthdev(dp, dev);
struct seq_oss_synth *rec __free(seq_oss_synth) =
get_synthdev(dp, dev);
if (!rec)
return -ENXIO;
@ -440,9 +437,9 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
struct seq_oss_synthinfo *
snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev)
{
struct seq_oss_synth *rec __free(seq_oss_synth) = NULL;
struct seq_oss_synth *rec __free(seq_oss_synth) =
get_synthdev(dp, dev);
rec = get_synthdev(dp, dev);
if (rec)
return get_synthinfo_nospec(dp, dev);
return NULL;
@ -495,13 +492,14 @@ snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event
int
snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
{
struct seq_oss_synth *rec __free(seq_oss_synth) = NULL;
struct seq_oss_synthinfo *info;
info = get_synthinfo_nospec(dp, dev);
if (!info || info->is_midi)
return -ENXIO;
rec = get_synthdev(dp, dev);
struct seq_oss_synth *rec __free(seq_oss_synth) =
get_synthdev(dp, dev);
if (!rec)
return -ENXIO;
if (rec->oper.ioctl == NULL)
@ -575,10 +573,9 @@ snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs);
for (i = 0; i < max_synth_devs; i++) {
struct seq_oss_synth *rec __free(seq_oss_synth) = NULL;
snd_iprintf(buf, "\nsynth %d: ", i);
rec = get_sdev(i);
struct seq_oss_synth *rec __free(seq_oss_synth) =
get_sdev(i);
if (rec == NULL) {
snd_iprintf(buf, "*empty*\n");
continue;

View file

@ -15,8 +15,8 @@
#include <sound/seq_device.h>
void snd_seq_oss_synth_init(void);
int snd_seq_oss_synth_probe(struct device *dev);
int snd_seq_oss_synth_remove(struct device *dev);
int snd_seq_oss_synth_probe(struct snd_seq_device *dev);
void snd_seq_oss_synth_remove(struct snd_seq_device *dev);
void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp);
void snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp);
void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp);

View file

@ -494,9 +494,9 @@ static int check_port_perm(struct snd_seq_client_port *port, unsigned int flags)
*/
static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event)
{
struct snd_seq_client *dest __free(snd_seq_client) = NULL;
struct snd_seq_client *dest __free(snd_seq_client) =
snd_seq_client_use_ptr(event->dest.client);
dest = snd_seq_client_use_ptr(event->dest.client);
if (dest == NULL)
return NULL;
if (! dest->accept_input)
@ -565,9 +565,9 @@ static int bounce_error_event(struct snd_seq_client *client,
static int update_timestamp_of_queue(struct snd_seq_event *event,
int queue, int real_time)
{
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
struct snd_seq_queue *q __free(snd_seq_queue) =
queueptr(queue);
q = queueptr(queue);
if (! q)
return 0;
event->queue = queue;
@ -609,13 +609,13 @@ static int _snd_seq_deliver_single_event(struct snd_seq_client *client,
struct snd_seq_event *event,
int atomic, int hop)
{
struct snd_seq_client *dest __free(snd_seq_client) = NULL;
struct snd_seq_client_port *dest_port __free(snd_seq_port) = NULL;
dest = get_event_dest_client(event);
struct snd_seq_client *dest __free(snd_seq_client) =
get_event_dest_client(event);
if (dest == NULL)
return -ENOENT;
dest_port = snd_seq_port_use_ptr(dest, event->dest.port);
struct snd_seq_client_port *dest_port __free(snd_seq_port) =
snd_seq_port_use_ptr(dest, event->dest.port);
if (dest_port == NULL)
return -ENOENT;
@ -672,7 +672,6 @@ static int __deliver_to_subscribers(struct snd_seq_client *client,
struct snd_seq_event *event,
int port, int atomic, int hop)
{
struct snd_seq_client_port *src_port __free(snd_seq_port) = NULL;
struct snd_seq_subscribers *subs;
int err, result = 0, num_ev = 0;
union __snd_seq_event event_saved;
@ -681,7 +680,9 @@ static int __deliver_to_subscribers(struct snd_seq_client *client,
if (port < 0)
return 0;
src_port = snd_seq_port_use_ptr(client, port);
struct snd_seq_client_port *src_port __free(snd_seq_port) =
snd_seq_port_use_ptr(client, port);
if (!src_port)
return 0;
@ -801,13 +802,13 @@ static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_e
*/
int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)
{
struct snd_seq_client *client __free(snd_seq_client) = NULL;
int result;
if (snd_BUG_ON(!cell))
return -EINVAL;
client = snd_seq_client_use_ptr(cell->event.source.client);
struct snd_seq_client *client __free(snd_seq_client) =
snd_seq_client_use_ptr(cell->event.source.client);
if (client == NULL) {
snd_seq_cell_free(cell); /* release this cell */
return -EINVAL;
@ -1154,10 +1155,10 @@ static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg)
static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg)
{
struct snd_seq_running_info *info = arg;
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
/* requested client number */
cptr = client_load_and_use_ptr(info->client);
struct snd_seq_client *cptr __free(snd_seq_client) =
client_load_and_use_ptr(info->client);
if (cptr == NULL)
return -ENOENT; /* don't change !!! */
@ -1207,10 +1208,10 @@ static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_client_info *client_info = arg;
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
/* requested client number */
cptr = client_load_and_use_ptr(client_info->client);
struct snd_seq_client *cptr __free(snd_seq_client) =
client_load_and_use_ptr(client_info->client);
if (cptr == NULL)
return -ENOENT; /* don't change !!! */
@ -1344,14 +1345,14 @@ static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg)
static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)
{
struct snd_seq_port_info *info = arg;
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
struct snd_seq_client_port *port __free(snd_seq_port) = NULL;
cptr = client_load_and_use_ptr(info->addr.client);
struct snd_seq_client *cptr __free(snd_seq_client) =
client_load_and_use_ptr(info->addr.client);
if (cptr == NULL)
return -ENXIO;
port = snd_seq_port_use_ptr(cptr, info->addr.port);
struct snd_seq_client_port *port __free(snd_seq_port) =
snd_seq_port_use_ptr(cptr, info->addr.port);
if (port == NULL)
return -ENOENT; /* don't change */
@ -1367,11 +1368,12 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)
static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, void *arg)
{
struct snd_seq_port_info *info = arg;
struct snd_seq_client_port *port __free(snd_seq_port) = NULL;
if (info->addr.client != client->number) /* only set our own ports ! */
return -EPERM;
port = snd_seq_port_use_ptr(client, info->addr.port);
struct snd_seq_client_port *port __free(snd_seq_port) =
snd_seq_port_use_ptr(client, info->addr.port);
if (port) {
snd_seq_set_port_info(port, info);
/* notify the change */
@ -1444,22 +1446,22 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_port_subscribe *subs = arg;
struct snd_seq_client *receiver __free(snd_seq_client) = NULL;
struct snd_seq_client *sender __free(snd_seq_client) = NULL;
struct snd_seq_client_port *sport __free(snd_seq_port) = NULL;
struct snd_seq_client_port *dport __free(snd_seq_port) = NULL;
int result;
receiver = client_load_and_use_ptr(subs->dest.client);
struct snd_seq_client *receiver __free(snd_seq_client) =
client_load_and_use_ptr(subs->dest.client);
if (!receiver)
return -EINVAL;
sender = client_load_and_use_ptr(subs->sender.client);
struct snd_seq_client *sender __free(snd_seq_client) =
client_load_and_use_ptr(subs->sender.client);
if (!sender)
return -EINVAL;
sport = snd_seq_port_use_ptr(sender, subs->sender.port);
struct snd_seq_client_port *sport __free(snd_seq_port) =
snd_seq_port_use_ptr(sender, subs->sender.port);
if (!sport)
return -EINVAL;
dport = snd_seq_port_use_ptr(receiver, subs->dest.port);
struct snd_seq_client_port *dport __free(snd_seq_port) =
snd_seq_port_use_ptr(receiver, subs->dest.port);
if (!dport)
return -EINVAL;
@ -1483,22 +1485,22 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_port_subscribe *subs = arg;
struct snd_seq_client *receiver __free(snd_seq_client) = NULL;
struct snd_seq_client *sender __free(snd_seq_client) = NULL;
struct snd_seq_client_port *sport __free(snd_seq_port) = NULL;
struct snd_seq_client_port *dport __free(snd_seq_port) = NULL;
int result;
receiver = snd_seq_client_use_ptr(subs->dest.client);
struct snd_seq_client *receiver __free(snd_seq_client) =
snd_seq_client_use_ptr(subs->dest.client);
if (!receiver)
return -ENXIO;
sender = snd_seq_client_use_ptr(subs->sender.client);
struct snd_seq_client *sender __free(snd_seq_client) =
snd_seq_client_use_ptr(subs->sender.client);
if (!sender)
return -ENXIO;
sport = snd_seq_port_use_ptr(sender, subs->sender.port);
struct snd_seq_client_port *sport __free(snd_seq_port) =
snd_seq_port_use_ptr(sender, subs->sender.port);
if (!sport)
return -ENXIO;
dport = snd_seq_port_use_ptr(receiver, subs->dest.port);
struct snd_seq_client_port *dport __free(snd_seq_port) =
snd_seq_port_use_ptr(receiver, subs->dest.port);
if (!dport)
return -ENXIO;
@ -1518,9 +1520,9 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg)
{
struct snd_seq_queue_info *info = arg;
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
struct snd_seq_queue *q __free(snd_seq_queue) =
snd_seq_queue_alloc(client->number, info->locked, info->flags);
q = snd_seq_queue_alloc(client->number, info->locked, info->flags);
if (IS_ERR(q))
return PTR_ERR(q);
@ -1549,9 +1551,9 @@ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_info *info = arg;
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
struct snd_seq_queue *q __free(snd_seq_queue) =
queueptr(info->queue);
q = queueptr(info->queue);
if (q == NULL)
return -EINVAL;
@ -1569,7 +1571,6 @@ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_info *info = arg;
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
if (info->owner != client->number)
return -EINVAL;
@ -1584,7 +1585,8 @@ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client,
return -EPERM;
}
q = queueptr(info->queue);
struct snd_seq_queue *q __free(snd_seq_queue) =
queueptr(info->queue);
if (! q)
return -EINVAL;
if (q->owner != client->number)
@ -1599,9 +1601,9 @@ static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_info *info = arg;
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
struct snd_seq_queue *q __free(snd_seq_queue) =
snd_seq_queue_find_name(info->name);
q = snd_seq_queue_find_name(info->name);
if (q == NULL)
return -EINVAL;
info->queue = q->queue;
@ -1616,10 +1618,10 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_status *status = arg;
struct snd_seq_queue *queue __free(snd_seq_queue) = NULL;
struct snd_seq_timer *tmr;
struct snd_seq_queue *queue __free(snd_seq_queue) =
queueptr(status->queue);
queue = queueptr(status->queue);
if (queue == NULL)
return -EINVAL;
memset(status, 0, sizeof(*status));
@ -1644,10 +1646,10 @@ static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_tempo *tempo = arg;
struct snd_seq_queue *queue __free(snd_seq_queue) = NULL;
struct snd_seq_timer *tmr;
struct snd_seq_queue *queue __free(snd_seq_queue) =
queueptr(tempo->queue);
queue = queueptr(tempo->queue);
if (queue == NULL)
return -EINVAL;
memset(tempo, 0, sizeof(*tempo));
@ -1693,10 +1695,10 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_timer *timer = arg;
struct snd_seq_queue *queue __free(snd_seq_queue) = NULL;
struct snd_seq_timer *tmr;
struct snd_seq_queue *queue __free(snd_seq_queue) =
queueptr(timer->queue);
queue = queueptr(timer->queue);
if (queue == NULL)
return -EINVAL;
@ -1726,10 +1728,10 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
return -EINVAL;
if (snd_seq_queue_check_access(timer->queue, client->number)) {
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
struct snd_seq_timer *tmr;
struct snd_seq_queue *q __free(snd_seq_queue) =
queueptr(timer->queue);
q = queueptr(timer->queue);
if (q == NULL)
return -ENXIO;
guard(mutex)(&q->timer_mutex);
@ -1788,9 +1790,9 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_client_pool *info = arg;
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
struct snd_seq_client *cptr __free(snd_seq_client) =
client_load_and_use_ptr(info->client);
cptr = client_load_and_use_ptr(info->client);
if (cptr == NULL)
return -ENOENT;
memset(info, 0, sizeof(*info));
@ -1888,13 +1890,13 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_port_subscribe *subs = arg;
struct snd_seq_client *sender __free(snd_seq_client) = NULL;
struct snd_seq_client_port *sport __free(snd_seq_port) = NULL;
sender = client_load_and_use_ptr(subs->sender.client);
struct snd_seq_client *sender __free(snd_seq_client) =
client_load_and_use_ptr(subs->sender.client);
if (!sender)
return -EINVAL;
sport = snd_seq_port_use_ptr(sender, subs->sender.port);
struct snd_seq_client_port *sport __free(snd_seq_port) =
snd_seq_port_use_ptr(sender, subs->sender.port);
if (!sport)
return -EINVAL;
return snd_seq_port_get_subscription(&sport->c_src, &subs->dest, subs);
@ -1907,16 +1909,16 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
{
struct snd_seq_query_subs *subs = arg;
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
struct snd_seq_client_port *port __free(snd_seq_port) = NULL;
struct snd_seq_port_subs_info *group;
struct list_head *p;
int i;
cptr = client_load_and_use_ptr(subs->root.client);
struct snd_seq_client *cptr __free(snd_seq_client) =
client_load_and_use_ptr(subs->root.client);
if (!cptr)
return -ENXIO;
port = snd_seq_port_use_ptr(cptr, subs->root.port);
struct snd_seq_client_port *port __free(snd_seq_port) =
snd_seq_port_use_ptr(cptr, subs->root.port);
if (!port)
return -ENXIO;
@ -1963,7 +1965,6 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_client_info *info = arg;
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
/* search for next client */
if (info->client < INT_MAX)
@ -1971,7 +1972,8 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
if (info->client < 0)
info->client = 0;
for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) {
cptr = client_load_and_use_ptr(info->client);
struct snd_seq_client *cptr __free(snd_seq_client) =
client_load_and_use_ptr(info->client);
if (cptr) {
get_client_info(cptr, info);
return 0; /* found */
@ -1987,16 +1989,16 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_port_info *info = arg;
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
struct snd_seq_client_port *port __free(snd_seq_port) = NULL;
cptr = client_load_and_use_ptr(info->addr.client);
struct snd_seq_client *cptr __free(snd_seq_client) =
client_load_and_use_ptr(info->addr.client);
if (cptr == NULL)
return -ENXIO;
/* search for next port */
info->addr.port++;
port = snd_seq_port_query_nearest(cptr, info);
struct snd_seq_client_port *port __free(snd_seq_port) =
snd_seq_port_query_nearest(cptr, info);
if (port == NULL)
return -ENOENT;
@ -2067,7 +2069,6 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,
{
struct snd_seq_client_ump_info __user *argp =
(struct snd_seq_client_ump_info __user *)arg;
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
int client, type, err = 0;
size_t size;
void *p;
@ -2083,7 +2084,9 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,
size = sizeof(struct snd_ump_endpoint_info);
else
size = sizeof(struct snd_ump_block_info);
cptr = client_load_and_use_ptr(client);
struct snd_seq_client *cptr __free(snd_seq_client) =
client_load_and_use_ptr(client);
if (!cptr)
return -ENOENT;
@ -2342,8 +2345,6 @@ EXPORT_SYMBOL(snd_seq_delete_kernel_client);
int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
struct file *file, bool blocking)
{
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
if (snd_BUG_ON(!ev))
return -EINVAL;
@ -2360,7 +2361,8 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
if (check_event_type_and_length(ev))
return -EINVAL;
cptr = client_load_and_use_ptr(client);
struct snd_seq_client *cptr __free(snd_seq_client) =
client_load_and_use_ptr(client);
if (cptr == NULL)
return -EINVAL;
@ -2385,8 +2387,6 @@ EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
int atomic, int hop)
{
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
if (snd_BUG_ON(!ev))
return -EINVAL;
@ -2397,7 +2397,8 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
if (check_event_type_and_length(ev))
return -EINVAL;
cptr = snd_seq_client_use_ptr(client);
struct snd_seq_client *cptr __free(snd_seq_client) =
snd_seq_client_use_ptr(client);
if (cptr == NULL)
return -EINVAL;
@ -2450,9 +2451,9 @@ EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
/* a similar like above but taking locks; used only from OSS sequencer layer */
int snd_seq_kernel_client_ioctl(int clientid, unsigned int cmd, void *arg)
{
struct snd_seq_client *client __free(snd_seq_client) = NULL;
struct snd_seq_client *client __free(snd_seq_client) =
client_load_and_use_ptr(clientid);
client = client_load_and_use_ptr(clientid);
if (!client)
return -ENXIO;
guard(mutex)(&client->ioctl_mutex);
@ -2597,9 +2598,9 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,
/* list the client table */
for (c = 0; c < SNDRV_SEQ_MAX_CLIENTS; c++) {
struct snd_seq_client *client __free(snd_seq_client) = NULL;
struct snd_seq_client *client __free(snd_seq_client) =
client_load_and_use_ptr(c);
client = client_load_and_use_ptr(c);
if (client == NULL)
continue;
if (client->type == NO_CLIENT)

View file

@ -31,10 +31,10 @@ struct snd_seq_port_info32 {
static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned int cmd,
struct snd_seq_port_info32 __user *data32)
{
struct snd_seq_port_info *data __free(kfree) = NULL;
int err;
struct snd_seq_port_info *data __free(kfree) =
kmalloc(sizeof(*data), GFP_KERNEL);
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;

View file

@ -265,13 +265,10 @@ static void snd_seq_midisynth_delete(struct seq_midisynth *msynth)
/* register new midi synth port */
static int
snd_seq_midisynth_probe(struct device *_dev)
snd_seq_midisynth_probe(struct snd_seq_device *dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct seq_midisynth_client *client;
struct seq_midisynth *msynth, *ms;
struct snd_seq_port_info *port __free(kfree) = NULL;
struct snd_rawmidi_info *info __free(kfree) = NULL;
struct snd_rawmidi *rmidi = dev->private_data;
int newclient = 0;
unsigned int p, ports;
@ -282,7 +279,9 @@ snd_seq_midisynth_probe(struct device *_dev)
if (snd_BUG_ON(!card || device < 0 || device >= SNDRV_RAWMIDI_DEVICES))
return -EINVAL;
info = kmalloc(sizeof(*info), GFP_KERNEL);
struct snd_rawmidi_info *info __free(kfree) =
kmalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
info->device = device;
@ -320,7 +319,9 @@ snd_seq_midisynth_probe(struct device *_dev)
}
msynth = kcalloc(ports, sizeof(struct seq_midisynth), GFP_KERNEL);
port = kmalloc(sizeof(*port), GFP_KERNEL);
struct snd_seq_port_info *port __free(kfree) =
kmalloc(sizeof(*port), GFP_KERNEL);
if (msynth == NULL || port == NULL)
goto __nomem;
@ -411,10 +412,9 @@ snd_seq_midisynth_probe(struct device *_dev)
}
/* release midi synth port */
static int
snd_seq_midisynth_remove(struct device *_dev)
static void
snd_seq_midisynth_remove(struct snd_seq_device *dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct seq_midisynth_client *client;
struct seq_midisynth *msynth;
struct snd_card *card = dev->card;
@ -423,7 +423,7 @@ snd_seq_midisynth_remove(struct device *_dev)
guard(mutex)(&register_mutex);
client = synths[card->number];
if (client == NULL || client->ports[device] == NULL)
return -ENODEV;
return;
ports = client->ports_per_device[device];
client->ports_per_device[device] = 0;
msynth = client->ports[device];
@ -437,14 +437,13 @@ snd_seq_midisynth_remove(struct device *_dev)
synths[card->number] = NULL;
kfree(client);
}
return 0;
}
static struct snd_seq_driver seq_midisynth_driver = {
.probe = snd_seq_midisynth_probe,
.remove = snd_seq_midisynth_remove,
.driver = {
.name = KBUILD_MODNAME,
.probe = snd_seq_midisynth_probe,
.remove = snd_seq_midisynth_remove,
},
.id = SNDRV_SEQ_DEV_ID_MIDISYNTH,
.argsize = 0,

View file

@ -211,14 +211,13 @@ static void clear_subscriber_list(struct snd_seq_client *client,
list_for_each_safe(p, n, &grp->list_head) {
struct snd_seq_subscribers *subs;
struct snd_seq_client *c __free(snd_seq_client) = NULL;
struct snd_seq_client_port *aport __free(snd_seq_port) = NULL;
subs = get_subscriber(p, is_src);
if (is_src)
aport = get_client_port(&subs->info.dest, &c);
else
aport = get_client_port(&subs->info.sender, &c);
struct snd_seq_client *c __free(snd_seq_client) = NULL;
struct snd_seq_client_port *aport __free(snd_seq_port) =
is_src ?
get_client_port(&subs->info.dest, &c) :
get_client_port(&subs->info.sender, &c);
delete_and_unsubscribe_port(client, port, subs, is_src, false);
if (!aport) {

View file

@ -211,8 +211,9 @@ struct snd_seq_queue *snd_seq_queue_find_name(char *name)
int i;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
q = queueptr(i);
struct snd_seq_queue *q __free(snd_seq_queue) =
queueptr(i);
if (q) {
if (strncmp(q->name, name, sizeof(q->name)) == 0)
return no_free_ptr(q);
@ -285,12 +286,13 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop)
{
int dest, err;
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
if (snd_BUG_ON(!cell))
return -EINVAL;
dest = cell->event.queue; /* destination queue */
q = queueptr(dest);
struct snd_seq_queue *q __free(snd_seq_queue) =
queueptr(dest);
if (q == NULL)
return -EINVAL;
/* handle relative time stamps, convert them into absolute */
@ -403,10 +405,10 @@ int snd_seq_queue_set_owner(int queueid, int client, int locked)
int snd_seq_queue_timer_open(int queueid)
{
int result = 0;
struct snd_seq_queue *queue __free(snd_seq_queue) = NULL;
struct snd_seq_timer *tmr;
struct snd_seq_queue *queue __free(snd_seq_queue) =
queueptr(queueid);
queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
tmr = queue->timer;
@ -423,10 +425,10 @@ int snd_seq_queue_timer_open(int queueid)
*/
int snd_seq_queue_timer_close(int queueid)
{
struct snd_seq_queue *queue __free(snd_seq_queue) = NULL;
int result = 0;
struct snd_seq_queue *queue __free(snd_seq_queue) =
queueptr(queueid);
queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
snd_seq_timer_close(queue);
@ -479,9 +481,9 @@ static void queue_use(struct snd_seq_queue *queue, int client, int use)
*/
int snd_seq_queue_use(int queueid, int client, int use)
{
struct snd_seq_queue *queue __free(snd_seq_queue) = NULL;
struct snd_seq_queue *queue __free(snd_seq_queue) =
queueptr(queueid);
queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
guard(mutex)(&queue->timer_mutex);
@ -496,9 +498,9 @@ int snd_seq_queue_use(int queueid, int client, int use)
*/
int snd_seq_queue_is_used(int queueid, int client)
{
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
struct snd_seq_queue *q __free(snd_seq_queue) =
queueptr(queueid);
q = queueptr(queueid);
if (q == NULL)
return -EINVAL; /* invalid queue */
return test_bit(client, q->clients_bitmap) ? 1 : 0;
@ -642,11 +644,11 @@ static void snd_seq_queue_process_event(struct snd_seq_queue *q,
*/
int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop)
{
struct snd_seq_queue *q __free(snd_seq_queue) = NULL;
if (snd_BUG_ON(!ev))
return -EINVAL;
q = queueptr(ev->data.queue.queue);
struct snd_seq_queue *q __free(snd_seq_queue) =
queueptr(ev->data.queue.queue);
if (q == NULL)
return -EINVAL;

View file

@ -214,13 +214,13 @@ static bool skip_group(struct seq_ump_client *client, struct snd_ump_group *grou
static int seq_ump_group_init(struct seq_ump_client *client, int group_index)
{
struct snd_ump_group *group = &client->ump->groups[group_index];
struct snd_seq_port_info *port __free(kfree) = NULL;
struct snd_seq_port_callback pcallbacks;
if (skip_group(client, group))
return 0;
port = kzalloc(sizeof(*port), GFP_KERNEL);
struct snd_seq_port_info *port __free(kfree) =
kzalloc(sizeof(*port), GFP_KERNEL);
if (!port)
return -ENOMEM;
@ -243,12 +243,12 @@ static int seq_ump_group_init(struct seq_ump_client *client, int group_index)
/* update the sequencer ports; called from notify_fb_change callback */
static void update_port_infos(struct seq_ump_client *client)
{
struct snd_seq_port_info *old __free(kfree) = NULL;
struct snd_seq_port_info *new __free(kfree) = NULL;
int i, err;
old = kzalloc(sizeof(*old), GFP_KERNEL);
new = kzalloc(sizeof(*new), GFP_KERNEL);
struct snd_seq_port_info *old __free(kfree) =
kzalloc(sizeof(*old), GFP_KERNEL);
struct snd_seq_port_info *new __free(kfree) =
kzalloc(sizeof(*new), GFP_KERNEL);
if (!old || !new)
return;
@ -278,12 +278,12 @@ static void update_port_infos(struct seq_ump_client *client)
/* create a UMP Endpoint port */
static int create_ump_endpoint_port(struct seq_ump_client *client)
{
struct snd_seq_port_info *port __free(kfree) = NULL;
struct snd_seq_port_callback pcallbacks;
unsigned int rawmidi_info = client->ump->core.info_flags;
int err;
port = kzalloc(sizeof(*port), GFP_KERNEL);
struct snd_seq_port_info *port __free(kfree) =
kzalloc(sizeof(*port), GFP_KERNEL);
if (!port)
return -ENOMEM;
@ -452,9 +452,8 @@ static const struct snd_seq_ump_ops seq_ump_ops = {
};
/* create a sequencer client and ports for the given UMP endpoint */
static int snd_seq_ump_probe(struct device *_dev)
static int snd_seq_ump_probe(struct snd_seq_device *dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct snd_ump_endpoint *ump = dev->private_data;
struct snd_card *card = dev->card;
struct seq_ump_client *client;
@ -513,21 +512,19 @@ static int snd_seq_ump_probe(struct device *_dev)
}
/* remove a sequencer client */
static int snd_seq_ump_remove(struct device *_dev)
static void snd_seq_ump_remove(struct snd_seq_device *dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct snd_ump_endpoint *ump = dev->private_data;
if (ump->seq_client)
seq_ump_client_free(ump->seq_client);
return 0;
}
static struct snd_seq_driver seq_ump_driver = {
.probe = snd_seq_ump_probe,
.remove = snd_seq_ump_remove,
.driver = {
.name = KBUILD_MODNAME,
.probe = snd_seq_ump_probe,
.remove = snd_seq_ump_remove,
},
.id = SNDRV_SEQ_DEV_ID_UMP,
.argsize = 0,

View file

@ -361,13 +361,13 @@ static int snd_virmidi_dev_attach_seq(struct snd_virmidi_dev *rdev)
{
int client;
struct snd_seq_port_callback pcallbacks;
struct snd_seq_port_info *pinfo __free(kfree) = NULL;
int err;
if (rdev->client >= 0)
return 0;
pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
struct snd_seq_port_info *pinfo __free(kfree) =
kzalloc(sizeof(*pinfo), GFP_KERNEL);
if (!pinfo)
return -ENOMEM;

View file

@ -49,9 +49,31 @@ static int snd_seq_bus_match(struct device *dev, const struct device_driver *drv
sdrv->argsize == sdev->argsize;
}
static int snd_seq_bus_probe(struct device *dev)
{
struct snd_seq_device *sdev = to_seq_dev(dev);
const struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
if (sdrv->probe)
return sdrv->probe(sdev);
else
return 0;
}
static void snd_seq_bus_remove(struct device *dev)
{
struct snd_seq_device *sdev = to_seq_dev(dev);
const struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
if (sdrv->remove)
sdrv->remove(sdev);
}
static const struct bus_type snd_seq_bus_type = {
.name = "snd_seq",
.match = snd_seq_bus_match,
.probe = snd_seq_bus_probe,
.remove = snd_seq_bus_remove,
};
/*
@ -247,10 +269,12 @@ EXPORT_SYMBOL(snd_seq_device_new);
*/
int __snd_seq_driver_register(struct snd_seq_driver *drv, struct module *mod)
{
if (WARN_ON(!drv->driver.name || !drv->id))
if (WARN_ON(!drv->driver.name || !drv->id || drv->driver.probe || drv->driver.remove))
return -EINVAL;
drv->driver.bus = &snd_seq_bus_type;
drv->driver.owner = mod;
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(__snd_seq_driver_register);

View file

@ -1614,12 +1614,12 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
static int snd_timer_user_ginfo(struct file *file,
struct snd_timer_ginfo __user *_ginfo)
{
struct snd_timer_ginfo *ginfo __free(kfree) = NULL;
struct snd_timer_id tid;
struct snd_timer *t;
struct list_head *p;
struct snd_timer_ginfo *ginfo __free(kfree) =
memdup_user(_ginfo, sizeof(*ginfo));
ginfo = memdup_user(_ginfo, sizeof(*ginfo));
if (IS_ERR(ginfo))
return PTR_ERR(ginfo);
@ -1756,7 +1756,6 @@ static int snd_timer_user_info(struct file *file,
struct snd_timer_info __user *_info)
{
struct snd_timer_user *tu;
struct snd_timer_info *info __free(kfree) = NULL;
struct snd_timer *t;
tu = file->private_data;
@ -1766,7 +1765,8 @@ static int snd_timer_user_info(struct file *file,
if (!t)
return -EBADFD;
info = kzalloc(sizeof(*info), GFP_KERNEL);
struct snd_timer_info *info __free(kfree) =
kzalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
info->card = t->card ? t->card->number : -1;
@ -2192,10 +2192,10 @@ static int snd_utimer_ioctl_create(struct file *file,
struct snd_timer_uinfo __user *_utimer_info)
{
struct snd_utimer *utimer;
struct snd_timer_uinfo *utimer_info __free(kfree) = NULL;
int err, timer_fd;
struct snd_timer_uinfo *utimer_info __free(kfree) =
memdup_user(_utimer_info, sizeof(*utimer_info));
utimer_info = memdup_user(_utimer_info, sizeof(*utimer_info));
if (IS_ERR(utimer_info))
return PTR_ERR(utimer_info);

View file

@ -56,10 +56,10 @@ struct link_follower {
static int follower_update(struct link_follower *follower)
{
struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
int err, ch;
struct snd_ctl_elem_value *uctl __free(kfree) =
kzalloc(sizeof(*uctl), GFP_KERNEL);
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (!uctl)
return -ENOMEM;
uctl->id = follower->follower.id;
@ -74,7 +74,6 @@ static int follower_update(struct link_follower *follower)
/* get the follower ctl info and save the initial values */
static int follower_init(struct link_follower *follower)
{
struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
int err;
if (follower->info.count) {
@ -84,7 +83,8 @@ static int follower_init(struct link_follower *follower)
return 0;
}
uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
struct snd_ctl_elem_info *uinfo __free(kfree) =
kmalloc(sizeof(*uinfo), GFP_KERNEL);
if (!uinfo)
return -ENOMEM;
uinfo->id = follower->follower.id;
@ -341,9 +341,9 @@ static int master_get(struct snd_kcontrol *kcontrol,
static int sync_followers(struct link_master *master, int old_val, int new_val)
{
struct link_follower *follower;
struct snd_ctl_elem_value *uval __free(kfree) = NULL;
struct snd_ctl_elem_value *uval __free(kfree) =
kmalloc(sizeof(*uval), GFP_KERNEL);
uval = kmalloc(sizeof(*uval), GFP_KERNEL);
if (!uval)
return -ENOMEM;
list_for_each_entry(follower, &master->followers, list) {

View file

@ -201,9 +201,8 @@ static int snd_opl3_synth_create_port(struct snd_opl3 * opl3)
/* ------------------------------ */
static int snd_opl3_seq_probe(struct device *_dev)
static int snd_opl3_seq_probe(struct snd_seq_device *dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct snd_opl3 *opl3;
int client, err;
char name[32];
@ -244,14 +243,13 @@ static int snd_opl3_seq_probe(struct device *_dev)
return 0;
}
static int snd_opl3_seq_remove(struct device *_dev)
static void snd_opl3_seq_remove(struct snd_seq_device *dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct snd_opl3 *opl3;
opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (opl3 == NULL)
return -EINVAL;
return;
#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
snd_opl3_free_seq_oss(opl3);
@ -260,14 +258,13 @@ static int snd_opl3_seq_remove(struct device *_dev)
snd_seq_delete_kernel_client(opl3->seq_client);
opl3->seq_client = -1;
}
return 0;
}
static struct snd_seq_driver opl3_seq_driver = {
.probe = snd_opl3_seq_probe,
.remove = snd_opl3_seq_remove,
.driver = {
.name = KBUILD_MODNAME,
.probe = snd_opl3_seq_probe,
.remove = snd_opl3_seq_remove,
},
.id = SNDRV_SEQ_DEV_ID_OPL3,
.argsize = sizeof(struct snd_opl3 *),

View file

@ -118,9 +118,8 @@ static void snd_opl4_seq_free_port(void *private_data)
snd_midi_channel_free_set(opl4->chset);
}
static int snd_opl4_seq_probe(struct device *_dev)
static int snd_opl4_seq_probe(struct snd_seq_device *dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct snd_opl4 *opl4;
int client;
struct snd_seq_port_callback pcallbacks;
@ -175,27 +174,25 @@ static int snd_opl4_seq_probe(struct device *_dev)
return 0;
}
static int snd_opl4_seq_remove(struct device *_dev)
static void snd_opl4_seq_remove(struct snd_seq_device *dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct snd_opl4 *opl4;
opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (!opl4)
return -EINVAL;
return;
if (opl4->seq_client >= 0) {
snd_seq_delete_kernel_client(opl4->seq_client);
opl4->seq_client = -1;
}
return 0;
}
static struct snd_seq_driver opl4_seq_driver = {
.probe = snd_opl4_seq_probe,
.remove = snd_opl4_seq_remove,
.driver = {
.name = KBUILD_MODNAME,
.probe = snd_opl4_seq_probe,
.remove = snd_opl4_seq_remove,
},
.id = SNDRV_SEQ_DEV_ID_OPL4,
.argsize = sizeof(struct snd_opl4 *),

View file

@ -34,6 +34,7 @@ comment "Set to Y if you want auto-loading the codec driver"
config SND_HDA_CODEC_CS8409
tristate "Build Cirrus Logic HDA bridge support"
select SND_HDA_GENERIC
select SND_HDA_SCODEC_COMPONENT
help
Say Y or M here to include Cirrus Logic HDA bridge support
such as CS8409.

View file

@ -468,6 +468,70 @@ struct sub_codec dolphin_cs42l42_1 = {
.no_type_dect = 1,
};
/******************************************************************************
* CDB35L56-FOUR-HD Specific Arrays
******************************************************************************/
const struct hda_verb cs8409_cdb35l56_four_init_verbs[] = {
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 }, /* Enable VPW processing */
{} /* terminator */
};
static const struct hda_pintbl cs8409_cdb35l56_four_pincfgs[] = {
/* 0xPPLLLLLLDDDDTTTTCCCCMMMMAAAASSSS
* P = PCON: AC_JACK_PORT_*
* L = LOC: AC_JACK_LOC_*
* D = DD: device type AC_JACK_*
* T = CTYP: AC_JACK_CONN_*
* C = COL: AC_JACK_COLOR_*
* M = MISC: ?
* A = DA: AC_DEFCFG_DEF_ASSOC
* S = SEQ: Sequence number in DA group
*/
{ CS8409_PIN_ASP2_TRANSMITTER_A, 0x901000f0 }, /* ASP-2-TX */
/* "Mic" */
{ CS8409_PIN_ASP2_RECEIVER_A, 0x04a12050 }, /* ASP-2-RX */
{} /* terminator */
};
const struct cs8409_cir_param cs8409_cdb35l56_four_hw_cfg[] = {
/* +PLL1/2_EN, +I2C_EN */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
/* ASP1/2_EN=0, ASP1_STP=1 */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
/* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
/* ASP2.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
{ CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL1, 0x0800 },
/* ASP2.A: TX.RAP=1, TX.RSZ=24 bits, TX.RCS=0 */
{ CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL2, 0x2800 },
/* ASP2.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
{ CS8409_PIN_VENDOR_WIDGET, ASP2_A_RX_CTRL1, 0x0800 },
/* ASP2.A: RX.RAP=1, RX.RSZ=24 bits, RX.RCS=0 */
{ CS8409_PIN_VENDOR_WIDGET, ASP2_A_RX_CTRL2, 0x2800 },
/* ASP1: LCHI = 00h */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
/* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
/* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
/* ASP2: LCHI=1Fh */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL1, 0x801f },
/* ASP2: MC/SC_SRCSEL=PLL1, LCPR=3Fh */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL2, 0x283f },
/* ASP2: 5050=1, MCEN=0, FSD=010, SCPOL_IN/OUT=1, SCDIV=1:16 */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL3, 0x805c },
/* ASP1/2_BEEP=0 */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
/* ASP1/2_EN=1, ASP1_STP=1 */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0062 },
/* -PLL2_EN */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 }, /* TX2.A: pre-scale att.=0 dB */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PRE_SCALE_ATTN2, 0x0000 },
/* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=1 */
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0xfc03 },
{} /* Terminator */
};
/******************************************************************************
* CS8409 Patch Driver Structs
* Arrays Used for all projects using CS8409
@ -557,7 +621,6 @@ const struct hda_quirk cs8409_fixup_tbl[] = {
{} /* terminator */
};
/* Dell Inspiron models with cs8409/cs42l42 */
const struct hda_model_fixup cs8409_models[] = {
{ .id = CS8409_BULLSEYE, .name = "bullseye" },
{ .id = CS8409_WARLOCK, .name = "warlock" },
@ -566,6 +629,7 @@ const struct hda_model_fixup cs8409_models[] = {
{ .id = CS8409_CYBORG, .name = "cyborg" },
{ .id = CS8409_DOLPHIN, .name = "dolphin" },
{ .id = CS8409_ODIN, .name = "odin" },
{ .id = CS8409_CDB35L56_FOUR_HD, .name = "CDB35L56-FOUR-HD" },
{}
};
@ -620,4 +684,14 @@ const struct hda_fixup cs8409_fixups[] = {
.chained = true,
.chain_id = CS8409_FIXUPS,
},
[CS8409_CDB35L56_FOUR_HD] = {
.type = HDA_FIXUP_PINS,
.v.pins = cs8409_cdb35l56_four_pincfgs,
.chained = true,
.chain_id = CS8409_CDB35L56_FOUR_HD_FIXUP,
},
[CS8409_CDB35L56_FOUR_HD_FIXUP] = {
.type = HDA_FIXUP_FUNC,
.v.func = cs8409_cdb35l56_four_autodet_fixup,
},
};

View file

@ -6,14 +6,19 @@
* Cirrus Logic International Semiconductor Ltd.
*/
#include <linux/acpi.h>
#include <linux/cleanup.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <sound/core.h>
#include <linux/mutex.h>
#include <linux/iopoll.h>
#include "cs8409.h"
#include "../side-codecs/hda_component.h"
/******************************************************************************
* CS8409 Specific Functions
@ -1216,6 +1221,172 @@ void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix,
}
}
static int cs8409_comp_bind(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
struct cs8409_spec *spec = codec->spec;
return hda_component_manager_bind(codec, &spec->comps);
}
static void cs8409_comp_unbind(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
struct cs8409_spec *spec = codec->spec;
hda_component_manager_unbind(codec, &spec->comps);
}
static const struct component_master_ops cs8409_comp_master_ops = {
.bind = cs8409_comp_bind,
.unbind = cs8409_comp_unbind,
};
static void cs8409_comp_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *codec,
struct snd_pcm_substream *sub, int action)
{
struct cs8409_spec *spec = codec->spec;
hda_component_manager_playback_hook(&spec->comps, action);
}
static void cs8409_cdb35l56_four_hw_init(struct hda_codec *codec)
{
const struct cs8409_cir_param *seq = cs8409_cdb35l56_four_hw_cfg;
for (; seq->nid; seq++)
cs8409_vendor_coef_set(codec, seq->cir, seq->coeff);
}
static int cs8409_spk_sw_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cs8409_spec *spec = codec->spec;
ucontrol->value.integer.value[0] = !spec->speaker_muted;
return 0;
}
static int cs8409_spk_sw_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cs8409_spec *spec = codec->spec;
bool muted = !ucontrol->value.integer.value[0];
if (muted == spec->speaker_muted)
return 0;
spec->speaker_muted = muted;
return 1;
}
static const struct snd_kcontrol_new cs8409_spk_sw_component_ctrl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_ctl_boolean_mono_info,
.get = cs8409_spk_sw_get,
.put = cs8409_spk_sw_put,
};
void cs8409_cdb35l56_four_autodet_fixup(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
struct device *dev = hda_codec_dev(codec);
struct cs8409_spec *spec = codec->spec;
struct acpi_device *adev;
const char *bus = NULL;
static const struct {
const char *hid;
const char *name;
} acpi_ids[] = {{ "CSC3554", "cs35l54-hda" },
{ "CSC3556", "cs35l56-hda" },
{ "CSC3557", "cs35l57-hda" }};
char *match;
int i, count = 0, count_devindex = 0;
int ret;
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE: {
for (i = 0; i < ARRAY_SIZE(acpi_ids); ++i) {
adev = acpi_dev_get_first_match_dev(acpi_ids[i].hid, NULL, -1);
if (adev)
break;
}
if (!adev) {
dev_err(dev, "Failed to find ACPI entry for a Cirrus Amp\n");
return;
}
count = i2c_acpi_client_count(adev);
if (count > 0) {
bus = "i2c";
} else {
count = acpi_spi_count_resources(adev);
if (count > 0)
bus = "spi";
}
struct fwnode_handle *fwnode __free(fwnode_handle) =
fwnode_handle_get(acpi_fwnode_handle(adev));
acpi_dev_put(adev);
if (!bus) {
dev_err(dev, "Did not find any buses for %s\n", acpi_ids[i].hid);
return;
}
if (!fwnode) {
dev_err(dev, "Could not get fwnode for %s\n", acpi_ids[i].hid);
return;
}
/*
* When available the cirrus,dev-index property is an accurate
* count of the amps in a system and is used in preference to
* the count of bus devices that can contain additional address
* alias entries.
*/
count_devindex = fwnode_property_count_u32(fwnode, "cirrus,dev-index");
if (count_devindex > 0)
count = count_devindex;
match = devm_kasprintf(dev, GFP_KERNEL, "-%%s:00-%s.%%d", acpi_ids[i].name);
if (!match)
return;
dev_info(dev, "Found %d %s on %s (%s)\n", count, acpi_ids[i].hid, bus, match);
ret = hda_component_manager_init(codec, &spec->comps, count, bus,
acpi_ids[i].hid, match,
&cs8409_comp_master_ops);
if (ret)
return;
spec->gen.pcm_playback_hook = cs8409_comp_playback_hook;
snd_hda_add_verbs(codec, cs8409_cdb35l56_four_init_verbs);
snd_hda_sequence_write(codec, cs8409_cdb35l56_four_init_verbs);
break;
}
case HDA_FIXUP_ACT_PROBE:
spec->speaker_muted = 0; /* speakers begin enabled */
snd_hda_gen_add_kctl(&spec->gen, "Speaker Playback Switch",
&cs8409_spk_sw_component_ctrl);
spec->gen.stream_analog_playback = &cs42l42_48k_pcm_analog_playback;
snd_hda_codec_set_name(codec, "CS8409/CS35L56");
break;
case HDA_FIXUP_ACT_INIT:
cs8409_cdb35l56_four_hw_init(codec);
break;
case HDA_FIXUP_ACT_FREE:
hda_component_manager_free(&spec->comps, &cs8409_comp_master_ops);
break;
}
}
/******************************************************************************
* Dolphin Specific Functions
* CS8409/ 2 X CS42L42
@ -1473,3 +1644,4 @@ module_hda_codec_driver(cs8409_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cirrus Logic HDA bridge");
MODULE_IMPORT_NS("SND_HDA_SCODEC_COMPONENT");

View file

@ -18,6 +18,7 @@
#include "hda_auto_parser.h"
#include "hda_jack.h"
#include "../generic.h"
#include "../side-codecs/hda_component.h"
/* CS8409 Specific Definitions */
@ -271,6 +272,8 @@ enum {
CS8409_DOLPHIN,
CS8409_DOLPHIN_FIXUPS,
CS8409_ODIN,
CS8409_CDB35L56_FOUR_HD,
CS8409_CDB35L56_FOUR_HD_FIXUP,
};
enum {
@ -341,12 +344,17 @@ struct cs8409_spec {
unsigned int capture_started:1;
unsigned int init_done:1;
unsigned int build_ctrl_done:1;
unsigned int speaker_muted:1;
/* verb exec op override */
int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
unsigned int *res);
/* unsol_event op override */
void (*unsol_event)(struct hda_codec *codec, unsigned int res);
/* component binding */
struct component_match *match;
struct hda_component_parent comps;
};
extern const struct snd_kcontrol_new cs42l42_dac_volume_mixer;
@ -374,4 +382,9 @@ extern struct sub_codec dolphin_cs42l42_1;
void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
extern const struct cs8409_cir_param cs8409_cdb35l56_four_hw_cfg[];
extern const struct hda_verb cs8409_cdb35l56_four_init_verbs[];
void cs8409_cdb35l56_four_autodet_fixup(struct hda_codec *codec, const struct hda_fixup *fix,
int action);
#endif

View file

@ -13,6 +13,11 @@
#include "hda_jack.h"
#include "generic.h"
enum {
QUIRK_CM_STD = 0x0,
QUIRK_GENE_TWL7_SSID = 0x160dc000
};
/* CM9825 Offset Definitions */
#define CM9825_VERB_SET_HPF_1 0x781
@ -25,6 +30,7 @@
#define CM9825_VERB_SET_VNEG 0x7a8
#define CM9825_VERB_SET_D2S 0x7a9
#define CM9825_VERB_SET_DACTRL 0x7aa
#define CM9825_VERB_SET_P3BCP 0x7ab
#define CM9825_VERB_SET_PDNEG 0x7ac
#define CM9825_VERB_SET_VDO 0x7ad
#define CM9825_VERB_SET_CDALR 0x7b0
@ -42,7 +48,12 @@ struct cmi_spec {
const struct hda_verb *chip_hp_present_verbs;
const struct hda_verb *chip_hp_remove_verbs;
struct hda_codec *codec;
struct delayed_work unsol_inputs_work;
struct delayed_work unsol_lineout_work;
struct delayed_work unsol_hp_work;
hda_nid_t jd_cap_hp;
hda_nid_t jd_cap_lineout;
hda_nid_t jd_cap_inputs[AUTO_CFG_MAX_INS];
int quirk;
};
@ -111,6 +122,121 @@ static const struct hda_verb cm9825_hp_remove_verbs[] = {
{}
};
/*
* To save power, AD/CLK is turned off.
*/
static const struct hda_verb cm9825_gene_twl7_d3_verbs[] = {
{0x43, CM9825_VERB_SET_D2S, 0x62},
{0x43, CM9825_VERB_SET_PLL, 0x01},
{0x43, CM9825_VERB_SET_NEG, 0xc2},
{0x43, CM9825_VERB_SET_ADCL, 0x00},
{0x43, CM9825_VERB_SET_DACL, 0x02},
{0x43, CM9825_VERB_SET_MBIAS, 0x00},
{0x43, CM9825_VERB_SET_VNEG, 0x50},
{0x43, CM9825_VERB_SET_PDNEG, 0x04},
{0x43, CM9825_VERB_SET_CDALR, 0xf6},
{0x43, CM9825_VERB_SET_OTP, 0xcd},
{}
};
/*
* These settings are required to properly enable the PLL, clock, ADC and
* DAC paths, and to select the correct analog input routing. Without
* these explicit configurations, the ADC does not start correctly and
* recording does not work reliably on this hardware.
*
* D0 configuration: enable PLL/CLK/ADC/DAC and optimize performance
*/
static const struct hda_verb cm9825_gene_twl7_d0_verbs[] = {
{0x34, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
{0x43, CM9825_VERB_SET_SNR, 0x38},
{0x43, CM9825_VERB_SET_PLL, 0x00},
{0x43, CM9825_VERB_SET_ADCL, 0xcf},
{0x43, CM9825_VERB_SET_DACL, 0xaa},
{0x43, CM9825_VERB_SET_MBIAS, 0x1c},
{0x43, CM9825_VERB_SET_VNEG, 0x56},
{0x43, CM9825_VERB_SET_D2S, 0x62},
{0x43, CM9825_VERB_SET_DACTRL, 0x00},
{0x43, CM9825_VERB_SET_PDNEG, 0x0c},
{0x43, CM9825_VERB_SET_CDALR, 0xf4},
{0x43, CM9825_VERB_SET_OTP, 0xcd},
{0x43, CM9825_VERB_SET_MTCBA, 0x61},
{0x43, CM9825_VERB_SET_OCP, 0x33},
{0x43, CM9825_VERB_SET_GAD, 0x07},
{0x43, CM9825_VERB_SET_TMOD, 0x26},
{0x43, CM9825_VERB_SET_HPF_1, 0x40},
{0x43, CM9825_VERB_SET_HPF_2, 0x40},
{0x40, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x3d, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x46, CM9825_VERB_SET_P3BCP, 0x20},
{}
};
/*
* Enable DAC to start playback.
*/
static const struct hda_verb cm9825_gene_twl7_playback_start_verbs[] = {
{0x43, CM9825_VERB_SET_D2S, 0xf2},
{0x43, CM9825_VERB_SET_VDO, 0xd4},
{0x43, CM9825_VERB_SET_SNR, 0x30},
{}
};
/*
* Disable DAC and enable de-pop noise mechanism.
*/
static const struct hda_verb cm9825_gene_twl7_playback_stop_verbs[] = {
{0x43, CM9825_VERB_SET_VDO, 0xc0},
{0x43, CM9825_VERB_SET_D2S, 0x62},
{0x43, CM9825_VERB_SET_VDO, 0xd0},
{0x43, CM9825_VERB_SET_SNR, 0x38},
{}
};
static void cm9825_update_jk_plug_status(struct hda_codec *codec, hda_nid_t nid)
{
struct cmi_spec *spec = codec->spec;
bool jack_plugin;
struct hda_jack_tbl *jack;
jack_plugin = snd_hda_jack_detect(spec->codec, nid);
jack = snd_hda_jack_tbl_get(spec->codec, nid);
if (jack) {
jack->block_report = 0;
snd_hda_jack_report_sync(spec->codec);
}
codec_dbg(spec->codec,
"%s, jack_plugin %d, nid 0x%X, line%d\n",
__func__, (int)jack_plugin, nid, __LINE__);
}
static void cm9825_unsol_inputs_delayed(struct work_struct *work)
{
struct cmi_spec *spec =
container_of(to_delayed_work(work), struct cmi_spec,
unsol_inputs_work);
int i;
for (i = 0; i < spec->gen.autocfg.num_inputs; i++) {
if (!spec->jd_cap_inputs[i])
continue;
cm9825_update_jk_plug_status(spec->codec,
spec->gen.autocfg.inputs[i].pin);
}
}
static void cm9825_unsol_lineout_delayed(struct work_struct *work)
{
struct cmi_spec *spec =
container_of(to_delayed_work(work), struct cmi_spec,
unsol_lineout_work);
cm9825_update_jk_plug_status(spec->codec,
spec->gen.autocfg.line_out_pins[0]);
}
static void cm9825_unsol_hp_delayed(struct work_struct *work)
{
struct cmi_spec *spec =
@ -159,16 +285,93 @@ static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
tbl = snd_hda_jack_tbl_get(codec, cb->nid);
if (tbl)
tbl->block_report = 1;
schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(200));
if (cb->nid == spec->jd_cap_hp)
schedule_delayed_work(&spec->unsol_hp_work,
msecs_to_jiffies(200));
else if (cb->nid == spec->jd_cap_lineout)
schedule_delayed_work(&spec->unsol_lineout_work,
msecs_to_jiffies(200));
for (int i = 0; i < spec->gen.autocfg.num_inputs; i++) {
if (cb->nid == spec->jd_cap_inputs[i])
schedule_delayed_work(&spec->unsol_inputs_work,
msecs_to_jiffies(200));
}
}
static void cm9825_setup_unsol(struct hda_codec *codec)
{
struct cmi_spec *spec = codec->spec;
int i;
hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
snd_hda_jack_detect_enable_callback(codec, hp_pin, hp_callback);
hda_nid_t lineout_pin = spec->gen.autocfg.line_out_pins[0];
if (hp_pin != 0) {
if (is_jack_detectable(codec, hp_pin)) {
spec->jd_cap_hp = hp_pin;
snd_hda_jack_detect_enable_callback(codec, hp_pin,
hp_callback);
} else
spec->jd_cap_hp = 0;
} else
spec->jd_cap_hp = 0;
if (lineout_pin != 0) {
if (is_jack_detectable(codec, lineout_pin)) {
spec->jd_cap_lineout = lineout_pin;
snd_hda_jack_detect_enable_callback(codec, lineout_pin,
hp_callback);
} else
spec->jd_cap_lineout = 0;
} else
spec->jd_cap_lineout = 0;
codec_dbg(codec,
"%s, jd_cap_hp 0x%02X, jd_cap_lineout 0x%02X, line%d\n",
__func__, spec->jd_cap_hp, spec->jd_cap_lineout, __LINE__);
for (i = 0; i < spec->gen.autocfg.num_inputs; i++) {
if (spec->gen.autocfg.inputs[i].pin != 0) {
if (is_jack_detectable
(codec, spec->gen.autocfg.inputs[i].pin)) {
spec->jd_cap_inputs[i] =
spec->gen.autocfg.inputs[i].pin;
snd_hda_jack_detect_enable_callback(codec,
spec->gen.autocfg.inputs[i].pin,
hp_callback);
} else
spec->jd_cap_inputs[i] = 0;
} else
spec->jd_cap_inputs[i] = 0;
codec_dbg(codec,
"%s, input jd_cap_inputs[%d] 0x%02X, line%d\n",
__func__, i, spec->jd_cap_inputs[i], __LINE__);
}
}
static void cm9825_playback_pcm_hook(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream,
int action)
{
struct cmi_spec *spec = codec->spec;
switch (action) {
case HDA_GEN_PCM_ACT_PREPARE:
snd_hda_sequence_write(spec->codec,
cm9825_gene_twl7_playback_start_verbs);
break;
case HDA_GEN_PCM_ACT_CLEANUP:
snd_hda_sequence_write(spec->codec,
cm9825_gene_twl7_playback_stop_verbs);
break;
default:
return;
}
}
static int cm9825_init(struct hda_codec *codec)
@ -182,23 +385,48 @@ static int cm9825_init(struct hda_codec *codec)
static void cm9825_remove(struct hda_codec *codec)
{
struct cmi_spec *spec = codec->spec;
int i;
if (spec->jd_cap_hp)
cancel_delayed_work_sync(&spec->unsol_hp_work);
if (spec->jd_cap_lineout)
cancel_delayed_work_sync(&spec->unsol_lineout_work);
for (i = 0; i < spec->gen.autocfg.num_inputs; i++) {
if (spec->jd_cap_inputs[i]) {
cancel_delayed_work_sync(&spec->unsol_inputs_work);
break;
}
}
cancel_delayed_work_sync(&spec->unsol_hp_work);
snd_hda_gen_remove(codec);
}
static int cm9825_suspend(struct hda_codec *codec)
{
struct cmi_spec *spec = codec->spec;
int i;
cancel_delayed_work_sync(&spec->unsol_hp_work);
if (spec->jd_cap_hp)
cancel_delayed_work_sync(&spec->unsol_hp_work);
if (spec->jd_cap_lineout)
cancel_delayed_work_sync(&spec->unsol_lineout_work);
for (i = 0; i < spec->gen.autocfg.num_inputs; i++) {
if (spec->jd_cap_inputs[i]) {
cancel_delayed_work_sync(&spec->unsol_inputs_work);
break;
}
}
snd_hda_sequence_write(codec, spec->chip_d3_verbs);
return 0;
}
static int cm9825_resume(struct hda_codec *codec)
static int cm9825_cm_std_resume(struct hda_codec *codec)
{
struct cmi_spec *spec = codec->spec;
hda_nid_t hp_pin = 0;
@ -215,6 +443,8 @@ static int cm9825_resume(struct hda_codec *codec)
snd_hda_codec_init(codec);
snd_hda_sequence_write(codec, spec->chip_d0_verbs);
hp_pin = spec->gen.autocfg.hp_pins[0];
hp_jack_plugin = snd_hda_jack_detect(spec->codec, hp_pin);
@ -232,6 +462,20 @@ static int cm9825_resume(struct hda_codec *codec)
snd_hda_sequence_write(codec, cm9825_hp_remove_verbs);
}
return 0;
}
static int cm9825_resume(struct hda_codec *codec)
{
struct cmi_spec *spec = codec->spec;
if (codec->core.subsystem_id == QUIRK_CM_STD)
cm9825_cm_std_resume(codec);
else if (codec->core.subsystem_id == QUIRK_GENE_TWL7_SSID) {
snd_hda_codec_init(codec);
snd_hda_sequence_write(codec, spec->chip_d0_verbs);
}
snd_hda_regmap_sync(codec);
hda_call_check_power_status(codec, 0x01);
@ -242,13 +486,15 @@ static int cm9825_probe(struct hda_codec *codec, const struct hda_device_id *id)
{
struct cmi_spec *spec;
struct auto_pin_cfg *cfg;
int err;
int err = 0;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
INIT_DELAYED_WORK(&spec->unsol_hp_work, cm9825_unsol_hp_delayed);
codec_dbg(codec, "chip_name: %s, ssid: 0x%X\n",
codec->core.chip_name, codec->core.subsystem_id);
codec->spec = spec;
spec->codec = codec;
cfg = &spec->gen.autocfg;
@ -258,6 +504,36 @@ static int cm9825_probe(struct hda_codec *codec, const struct hda_device_id *id)
spec->chip_hp_present_verbs = cm9825_hp_present_verbs;
spec->chip_hp_remove_verbs = cm9825_hp_remove_verbs;
INIT_DELAYED_WORK(&spec->unsol_hp_work, cm9825_unsol_hp_delayed);
INIT_DELAYED_WORK(&spec->unsol_inputs_work,
cm9825_unsol_inputs_delayed);
INIT_DELAYED_WORK(&spec->unsol_lineout_work,
cm9825_unsol_lineout_delayed);
switch (codec->core.subsystem_id) {
case QUIRK_CM_STD:
snd_hda_codec_set_name(codec, "CM9825 STD");
spec->chip_d0_verbs = cm9825_std_d0_verbs;
spec->chip_d3_verbs = cm9825_std_d3_verbs;
spec->chip_hp_present_verbs = cm9825_hp_present_verbs;
spec->chip_hp_remove_verbs = cm9825_hp_remove_verbs;
break;
case QUIRK_GENE_TWL7_SSID:
snd_hda_codec_set_name(codec, "CM9825 GENE_TWL7");
spec->chip_d0_verbs = cm9825_gene_twl7_d0_verbs;
spec->chip_d3_verbs = cm9825_gene_twl7_d3_verbs;
spec->gen.pcm_playback_hook = cm9825_playback_pcm_hook;
/* Internal fixed device, Rear, Mic-in, 3.5mm */
snd_hda_codec_set_pincfg(codec, 0x37, 0x24A70100);
break;
default:
err = -ENXIO;
break;
}
if (err < 0)
goto error;
snd_hda_sequence_write(codec, spec->chip_d0_verbs);
err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);

View file

@ -1081,6 +1081,7 @@ static const struct hda_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO),
SND_PCI_QUIRK(0x103c, 0x8231, "HP ProBook 450 G4", CXT_FIXUP_MUTE_LED_GPIO),
SND_PCI_QUIRK(0x103c, 0x826b, "HP ZBook Studio G4", CXT_FIXUP_MUTE_LED_GPIO),
SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
@ -1123,6 +1124,7 @@ static const struct hda_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad/Ideapad", CXT_FIXUP_LENOVO_XPAD_ACPI),
SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
SND_PCI_QUIRK(0x1d05, 0x3012, "MECHREVO Wujie 15X Pro", CXT_FIXUP_HEADSET_MIC),
HDA_CODEC_QUIRK(0x2782, 0x12c3, "Sirius Gen1", CXT_PINCFG_TOP_SPEAKER),
HDA_CODEC_QUIRK(0x2782, 0x12c5, "Sirius Gen2", CXT_PINCFG_TOP_SPEAKER),
{}

View file

@ -1517,7 +1517,7 @@ static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
/*
* multi-io helper
*
* When hardwired is set, try to fill ony hardwired pins, and returns
* When hardwired is set, try to fill only hardwired pins, and returns
* zero if any pins are filled, non-zero if nothing found.
* When hardwired is off, try to fill possible input pins, and returns
* the badness value.
@ -1984,15 +1984,15 @@ static int parse_output_paths(struct hda_codec *codec)
{
struct hda_gen_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
struct auto_pin_cfg *best_cfg __free(kfree) = NULL;
unsigned int val;
int best_badness = INT_MAX;
int badness;
bool fill_hardwired = true, fill_mio_first = true;
bool best_wired = true, best_mio = true;
bool hp_spk_swapped = false;
struct auto_pin_cfg *best_cfg __free(kfree) =
kmalloc(sizeof(*best_cfg), GFP_KERNEL);
best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
if (!best_cfg)
return -ENOMEM;
*best_cfg = *cfg;
@ -4889,7 +4889,7 @@ static int check_auto_mic_availability(struct hda_codec *codec)
* snd_hda_gen_path_power_filter - power_filter hook to make inactive widgets
* into power down
* @codec: the HDA codec
* @nid: NID to evalute
* @nid: NID to evaluate
* @power_state: target power state
*/
unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,

View file

@ -1551,6 +1551,22 @@ static void alc245_fixup_hp_mute_led_v1_coefbit(struct hda_codec *codec,
}
}
static void alc245_fixup_hp_mute_led_v2_coefbit(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->mute_led_polarity = 0;
spec->mute_led_coef.idx = 0x0b;
spec->mute_led_coef.mask = 1 << 3;
spec->mute_led_coef.on = 1 << 3;
spec->mute_led_coef.off = 0;
snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
}
}
/* turn on/off mic-mute LED per capture hook by coef bit */
static int coef_micmute_led_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
@ -1616,6 +1632,20 @@ static void alc295_fixup_hp_mute_led_coefbit11(struct hda_codec *codec,
}
}
static void alc233_fixup_lenovo_coef_micmute_led(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->mic_led_coef.idx = 0x10;
spec->mic_led_coef.mask = 1 << 13;
spec->mic_led_coef.on = 0;
spec->mic_led_coef.off = 1 << 13;
snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set);
}
}
static void alc285_fixup_hp_mute_led(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@ -1630,6 +1660,13 @@ static void alc285_fixup_hp_spectre_x360_mute_led(struct hda_codec *codec,
alc285_fixup_hp_gpio_micmute_led(codec, fix, action);
}
static void alc245_fixup_hp_envy_x360_mute_led(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
alc245_fixup_hp_mute_led_v1_coefbit(codec, fix, action);
alc245_fixup_hp_gpio_led(codec, fix, action);
}
static void alc236_fixup_hp_mute_led(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@ -1824,6 +1861,163 @@ static void alc298_samsung_v2_init_amps(struct hda_codec *codec,
spec->gen.pcm_playback_hook = alc298_samsung_v2_playback_hook;
}
/* LG Gram Style 14: program vendor coef sequence used by HDA-verb workaround */
struct alc298_lg_gram_style_seq {
unsigned short verb;
unsigned short idx;
unsigned short val;
};
static void alc298_lg_gram_style_coef_write(struct hda_codec *codec,
unsigned int verb,
unsigned int idx,
unsigned int val)
{
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x23);
snd_hda_codec_write(codec, 0x20, 0, verb, idx);
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0x00);
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, val);
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0xb011);
}
static void alc298_lg_gram_style_run_seq(struct hda_codec *codec,
const struct alc298_lg_gram_style_seq *seq,
int seq_size)
{
int i;
for (i = 0; i < seq_size; i++)
alc298_lg_gram_style_coef_write(codec, seq[i].verb,
seq[i].idx, seq[i].val);
}
/* Coef sequences derived from the HDA-verb workaround for this model. */
static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_preinit_seq[] = {
{ 0x420, 0x00, 0x01 },
};
static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_disable_seq[] = {
{ 0x423, 0xff, 0x00 },
{ 0x420, 0x3a, 0x80 },
};
static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_enable_seq[] = {
{ 0x420, 0x3a, 0x81 },
{ 0x423, 0xff, 0x01 },
};
static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_38[] = {
{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
{ 0x420, 0x1b, 0x01 }, { 0x420, 0x1d, 0x01 }, { 0x420, 0x1f, 0xfe },
{ 0x420, 0x21, 0x00 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0x99, 0x03 },
{ 0x423, 0xa4, 0xb5 }, { 0x423, 0xa5, 0x01 }, { 0x423, 0xba, 0x94 },
};
static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_39[] = {
{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
{ 0x420, 0x1b, 0x02 }, { 0x420, 0x1d, 0x02 }, { 0x420, 0x1f, 0xfd },
{ 0x420, 0x21, 0x01 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0x99, 0x03 },
{ 0x423, 0xa4, 0xb5 }, { 0x423, 0xa5, 0x01 }, { 0x423, 0xba, 0x94 },
};
static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_3c[] = {
{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
{ 0x420, 0x1b, 0x01 }, { 0x420, 0x1d, 0x01 }, { 0x420, 0x1f, 0xfe },
{ 0x420, 0x21, 0x00 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0xba, 0x8d },
};
static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_3d[] = {
{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
{ 0x420, 0x1b, 0x02 }, { 0x420, 0x1d, 0x02 }, { 0x420, 0x1f, 0xfd },
{ 0x420, 0x21, 0x01 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0xba, 0x8d },
};
struct alc298_lg_gram_style_amp_desc {
unsigned char nid;
const struct alc298_lg_gram_style_seq *init_seq;
int init_seq_size;
};
static const struct alc298_lg_gram_style_amp_desc alc298_lg_gram_style_amps[] = {
{ 0x38, alc298_lg_gram_style_init_seq_38,
ARRAY_SIZE(alc298_lg_gram_style_init_seq_38) },
{ 0x39, alc298_lg_gram_style_init_seq_39,
ARRAY_SIZE(alc298_lg_gram_style_init_seq_39) },
{ 0x3c, alc298_lg_gram_style_init_seq_3c,
ARRAY_SIZE(alc298_lg_gram_style_init_seq_3c) },
{ 0x3d, alc298_lg_gram_style_init_seq_3d,
ARRAY_SIZE(alc298_lg_gram_style_init_seq_3d) },
};
static void alc298_lg_gram_style_enable_amps(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int i;
for (i = 0; i < spec->num_speaker_amps; i++) {
alc_write_coef_idx(codec, 0x22, alc298_lg_gram_style_amps[i].nid);
alc298_lg_gram_style_run_seq(codec,
alc298_lg_gram_style_enable_seq,
ARRAY_SIZE(alc298_lg_gram_style_enable_seq));
}
}
static void alc298_lg_gram_style_disable_amps(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int i;
for (i = 0; i < spec->num_speaker_amps; i++) {
alc_write_coef_idx(codec, 0x22, alc298_lg_gram_style_amps[i].nid);
alc298_lg_gram_style_run_seq(codec,
alc298_lg_gram_style_disable_seq,
ARRAY_SIZE(alc298_lg_gram_style_disable_seq));
}
}
static void alc298_lg_gram_style_playback_hook(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream,
int action)
{
if (action == HDA_GEN_PCM_ACT_OPEN)
alc298_lg_gram_style_enable_amps(codec);
if (action == HDA_GEN_PCM_ACT_CLOSE)
alc298_lg_gram_style_disable_amps(codec);
}
static void alc298_lg_gram_style_init_amps(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int i;
spec->num_speaker_amps = ARRAY_SIZE(alc298_lg_gram_style_amps);
for (i = 0; i < spec->num_speaker_amps; i++) {
alc_write_coef_idx(codec, 0x22, alc298_lg_gram_style_amps[i].nid);
alc298_lg_gram_style_run_seq(codec,
alc298_lg_gram_style_preinit_seq,
ARRAY_SIZE(alc298_lg_gram_style_preinit_seq));
alc298_lg_gram_style_run_seq(codec,
alc298_lg_gram_style_disable_seq,
ARRAY_SIZE(alc298_lg_gram_style_disable_seq));
alc298_lg_gram_style_run_seq(codec,
alc298_lg_gram_style_amps[i].init_seq,
alc298_lg_gram_style_amps[i].init_seq_size);
alc_write_coef_idx(codec, 0x89, 0x0);
}
spec->gen.pcm_playback_hook = alc298_lg_gram_style_playback_hook;
}
static void alc298_fixup_samsung_amp_v2_2_amps(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@ -1838,6 +2032,13 @@ static void alc298_fixup_samsung_amp_v2_4_amps(struct hda_codec *codec,
alc298_samsung_v2_init_amps(codec, 4);
}
static void alc298_fixup_lg_gram_style_14(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PROBE)
alc298_lg_gram_style_init_amps(codec);
}
static void gpio2_mic_hotkey_event(struct hda_codec *codec,
struct hda_jack_callback *event)
{
@ -1918,6 +2119,39 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
}
}
/* GPIO2 = mic mute hotkey
* GPIO3 = mic mute LED
*/
static void alc233_fixup_lenovo_gpio2_mic_hotkey(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
alc233_fixup_lenovo_coef_micmute_led(codec, fix, action);
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
alc_update_coef_idx(codec, 0x10, 1<<2, 1<<2);
if (alc_register_micmute_input_device(codec) != 0)
return;
spec->gpio_mask |= 0x04;
spec->gpio_dir |= 0x0;
snd_hda_codec_write_cache(codec, codec->core.afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x04);
snd_hda_jack_detect_enable_callback(codec, codec->core.afg,
gpio2_mic_hotkey_event);
return;
}
if (!spec->kb_dev)
return;
switch (action) {
case HDA_FIXUP_ACT_FREE:
input_unregister_device(spec->kb_dev);
spec->kb_dev = NULL;
}
}
/* Line2 = mic mute hotkey
* GPIO2 = mic mute LED
*/
@ -2916,7 +3150,6 @@ static void find_cirrus_companion_amps(struct hda_codec *cdc)
{
struct device *dev = hda_codec_dev(cdc);
struct acpi_device *adev;
struct fwnode_handle *fwnode __free(fwnode_handle) = NULL;
const char *bus = NULL;
static const struct {
const char *hid;
@ -2946,7 +3179,8 @@ static void find_cirrus_companion_amps(struct hda_codec *cdc)
bus = "spi";
}
fwnode = fwnode_handle_get(acpi_fwnode_handle(adev));
struct fwnode_handle *fwnode __free(fwnode_handle) =
fwnode_handle_get(acpi_fwnode_handle(adev));
acpi_dev_put(adev);
if (!bus) {
@ -3692,6 +3926,7 @@ enum {
ALC285_FIXUP_HP_GPIO_LED,
ALC285_FIXUP_HP_MUTE_LED,
ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED,
ALC245_FIXUP_HP_ENVY_X360_MUTE_LED,
ALC285_FIXUP_HP_BEEP_MICMUTE_LED,
ALC236_FIXUP_HP_MUTE_LED_COEFBIT2,
ALC236_FIXUP_HP_GPIO_LED,
@ -3701,6 +3936,7 @@ enum {
ALC298_FIXUP_SAMSUNG_AMP,
ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS,
ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS,
ALC298_FIXUP_LG_GRAM_STYLE_14,
ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
@ -3781,6 +4017,7 @@ enum {
ALC287_FIXUP_YOGA7_14ARB7_I2C,
ALC245_FIXUP_HP_MUTE_LED_COEFBIT,
ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT,
ALC245_FIXUP_HP_MUTE_LED_V2_COEFBIT,
ALC245_FIXUP_HP_X360_MUTE_LEDS,
ALC287_FIXUP_THINKPAD_I2S_SPK,
ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD,
@ -3816,6 +4053,8 @@ enum {
ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED,
ALC288_FIXUP_SURFACE_SWAP_DACS,
ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO,
ALC233_FIXUP_LENOVO_GPIO2_MIC_HOTKEY,
ALC245_FIXUP_BASS_HP_DAC,
};
/* A special fixup for Lenovo C940 and Yoga Duet 7;
@ -5344,6 +5583,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc285_fixup_hp_spectre_x360_mute_led,
},
[ALC245_FIXUP_HP_ENVY_X360_MUTE_LED] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc245_fixup_hp_envy_x360_mute_led,
},
[ALC285_FIXUP_HP_BEEP_MICMUTE_LED] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc285_fixup_hp_beep,
@ -5394,6 +5637,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc298_fixup_samsung_amp_v2_4_amps
},
[ALC298_FIXUP_LG_GRAM_STYLE_14] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc298_fixup_lg_gram_style_14
},
[ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@ -6117,6 +6364,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc245_fixup_hp_mute_led_v1_coefbit,
},
[ALC245_FIXUP_HP_MUTE_LED_V2_COEFBIT] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc245_fixup_hp_mute_led_v2_coefbit,
},
[ALC245_FIXUP_HP_X360_MUTE_LEDS] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc245_fixup_hp_mute_led_coefbit,
@ -6306,6 +6557,15 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc288_fixup_surface_swap_dacs,
},
[ALC233_FIXUP_LENOVO_GPIO2_MIC_HOTKEY] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc233_fixup_lenovo_gpio2_mic_hotkey,
},
[ALC245_FIXUP_BASS_HP_DAC] = {
.type = HDA_FIXUP_FUNC,
/* Borrow the DAC routing selected for those Thinkpads */
.v.func = alc285_fixup_thinkpad_x1_gen7,
},
};
static const struct hda_quirk alc269_fixup_tbl[] = {
@ -6600,8 +6860,10 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8895, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x103c, 0x88b3, "HP ENVY x360 Convertible 15-es0xxx", ALC245_FIXUP_HP_ENVY_X360_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x88d0, "HP Pavilion 15-eh1xxx (mainboard 88D0)", ALC287_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x88dd, "HP Pavilion 15z-ec200", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x88eb, "HP Victus 16-e0xxx", ALC245_FIXUP_HP_MUTE_LED_V2_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x8902, "HP OMEN 16", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x890e, "HP 255 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8919, "HP Pavilion Aero Laptop 13-be0xxx", ALC287_FIXUP_HP_GPIO_LED),
@ -7211,7 +7473,12 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x31af, "ThinkCentre Station", ALC623_FIXUP_LENOVO_THINKSTATION_P340),
SND_PCI_QUIRK(0x17aa, 0x3341, "Lenovo ThinkCentre M90 Gen4", ALC233_FIXUP_LENOVO_GPIO2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x3342, "Lenovo ThinkCentre M90 Gen4", ALC233_FIXUP_LENOVO_GPIO2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x3343, "Lenovo ThinkCentre M70 Gen4", ALC233_FIXUP_LENOVO_GPIO2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x3344, "Lenovo ThinkCentre M70 Gen4", ALC233_FIXUP_LENOVO_GPIO2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x334b, "Lenovo ThinkCentre M70 Gen5", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x334f, "Lenovo ThinkCentre M90a Gen5", ALC233_FIXUP_LENOVO_GPIO2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x3384, "ThinkCentre M90a PRO", ALC233_FIXUP_LENOVO_L2MH_LOW_ENLED),
SND_PCI_QUIRK(0x17aa, 0x3386, "ThinkCentre M90a Gen6", ALC233_FIXUP_LENOVO_L2MH_LOW_ENLED),
SND_PCI_QUIRK(0x17aa, 0x3387, "ThinkCentre M70a Gen6", ALC233_FIXUP_LENOVO_L2MH_LOW_ENLED),
@ -7325,6 +7592,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1854, 0x0488, "LG gram 16 (16Z90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
SND_PCI_QUIRK(0x1854, 0x0489, "LG gram 16 (16Z90R-A)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
SND_PCI_QUIRK(0x1854, 0x048a, "LG gram 17 (17ZD90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
SND_PCI_QUIRK(0x1854, 0x0490, "LG Gram Style 14 (14Z90RS)", ALC298_FIXUP_LG_GRAM_STYLE_14),
SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x19e5, 0x3212, "Huawei KLV-WX9 ", ALC256_FIXUP_ACER_HEADSET_MIC),
@ -7358,6 +7626,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1e39, 0xca14, "MEDION NM14LNL", ALC233_FIXUP_MEDION_MTL_SPK),
SND_PCI_QUIRK(0x1ee7, 0x2078, "HONOR BRB-X M1010", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1f4c, 0xe001, "Minisforum V3 (SE)", ALC245_FIXUP_BASS_HP_DAC),
SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x2014, 0x800a, "Positivo ARN50", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x2039, 0x0001, "Inspur S14-G1", ALC295_FIXUP_CHROME_BOOK),
@ -7573,6 +7842,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC285_FIXUP_HP_GPIO_AMP_INIT, .name = "alc285-hp-amp-init"},
{.id = ALC236_FIXUP_LENOVO_INV_DMIC, .name = "alc236-fixup-lenovo-inv-mic"},
{.id = ALC2XX_FIXUP_HEADSET_MIC, .name = "alc2xx-fixup-headset-mic"},
{.id = ALC245_FIXUP_BASS_HP_DAC, .name = "alc245-fixup-bass-hp-dac"},
{}
};
#define ALC225_STANDARD_PINS \

View file

@ -215,12 +215,13 @@ void alc_update_knob_master(struct hda_codec *codec,
{
unsigned int val;
struct snd_kcontrol *kctl;
struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
if (!kctl)
return;
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
struct snd_ctl_elem_value *uctl __free(kfree) =
kzalloc(sizeof(*uctl), GFP_KERNEL);
if (!uctl)
return;
val = snd_hda_codec_read(codec, jack->nid, 0,

View file

@ -5,14 +5,13 @@
// Copyright (C) 2023 Cirrus Logic, Inc. and
// Cirrus Logic International Semiconductor Ltd.
#include <kunit/platform_device.h>
#include <kunit/resource.h>
#include <kunit/test.h>
#include <linux/device.h>
#include <linux/device/devres.h>
#include <linux/device/faux.h>
#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "cirrus_scodec.h"
@ -29,7 +28,7 @@ struct cirrus_scodec_test_gpio {
struct cirrus_scodec_test_priv {
struct faux_device *amp_dev;
struct platform_device *gpio_pdev;
struct faux_device *gpio_dev;
struct cirrus_scodec_test_gpio *gpio_priv;
};
@ -92,59 +91,57 @@ static const struct gpio_chip cirrus_scodec_test_gpio_chip = {
.ngpio = 32,
};
static int cirrus_scodec_test_gpio_probe(struct platform_device *pdev)
/* software_node referencing the gpio driver */
static const struct software_node cirrus_scodec_test_gpio_swnode = {
.name = "cirrus_scodec_test_gpio",
};
static int cirrus_scodec_test_gpio_probe(struct faux_device *fdev)
{
struct cirrus_scodec_test_gpio *gpio_priv;
int ret;
gpio_priv = devm_kzalloc(&pdev->dev, sizeof(*gpio_priv), GFP_KERNEL);
gpio_priv = devm_kzalloc(&fdev->dev, sizeof(*gpio_priv), GFP_KERNEL);
if (!gpio_priv)
return -ENOMEM;
ret = device_add_software_node(&fdev->dev, &cirrus_scodec_test_gpio_swnode);
if (ret)
return ret;
ret = devm_add_action_or_reset(&fdev->dev, device_remove_software_node_wrapper,
&fdev->dev);
if (ret)
return ret;
/* GPIO core modifies our struct gpio_chip so use a copy */
gpio_priv->chip = cirrus_scodec_test_gpio_chip;
gpio_priv->chip.parent = &pdev->dev;
ret = devm_gpiochip_add_data(&pdev->dev, &gpio_priv->chip, gpio_priv);
gpio_priv->chip.parent = &fdev->dev;
ret = devm_gpiochip_add_data(&fdev->dev, &gpio_priv->chip, gpio_priv);
if (ret)
return dev_err_probe(&pdev->dev, ret, "Failed to add gpiochip\n");
return dev_err_probe(&fdev->dev, ret, "Failed to add gpiochip\n");
dev_set_drvdata(&pdev->dev, gpio_priv);
dev_set_drvdata(&fdev->dev, gpio_priv);
return 0;
}
static struct platform_driver cirrus_scodec_test_gpio_driver = {
.driver.name = "cirrus_scodec_test_gpio_drv",
.driver.owner = THIS_MODULE,
static const struct faux_device_ops cirrus_scodec_test_gpio_driver_ops = {
.probe = cirrus_scodec_test_gpio_probe,
};
/* software_node referencing the gpio driver */
static const struct software_node cirrus_scodec_test_gpio_swnode = {
.name = "cirrus_scodec_test_gpio",
};
static void cirrus_scodec_test_create_gpio(struct kunit *test)
{
struct cirrus_scodec_test_priv *priv = test->priv;
KUNIT_ASSERT_EQ(test, 0,
kunit_platform_driver_register(test, &cirrus_scodec_test_gpio_driver));
priv->gpio_pdev = kunit_platform_device_alloc(test,
cirrus_scodec_test_gpio_driver.driver.name,
PLATFORM_DEVID_NONE);
KUNIT_ASSERT_NOT_NULL(test, priv->gpio_pdev);
KUNIT_ASSERT_EQ(test, 0, device_add_software_node(&priv->gpio_pdev->dev,
&cirrus_scodec_test_gpio_swnode));
priv->gpio_dev = faux_device_create("cirrus_scodec_test_gpio_drv", NULL,
&cirrus_scodec_test_gpio_driver_ops);
KUNIT_ASSERT_NOT_NULL(test, priv->gpio_dev);
KUNIT_ASSERT_EQ(test, 0, kunit_add_action_or_reset(test,
device_remove_software_node_wrapper,
&priv->gpio_pdev->dev));
faux_device_destroy_wrapper,
priv->gpio_dev));
KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_add(test, priv->gpio_pdev));
priv->gpio_priv = dev_get_drvdata(&priv->gpio_pdev->dev);
priv->gpio_priv = dev_get_drvdata(&priv->gpio_dev->dev);
KUNIT_ASSERT_NOT_NULL(test, priv->gpio_priv);
}

View file

@ -1255,19 +1255,16 @@ static void cs35l41_fw_load_work(struct work_struct *work)
{
struct cs35l41_hda *cs35l41 = container_of(work, struct cs35l41_hda, fw_load_work);
pm_runtime_get_sync(cs35l41->dev);
guard(pm_runtime_active_auto)(cs35l41->dev);
scoped_guard(mutex, &cs35l41->fw_mutex) {
/* Recheck if playback is ongoing, mutex will block playback during firmware loading */
if (cs35l41->playback_started)
dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback. Retrying...\n");
else
cs35l41_load_firmware(cs35l41, cs35l41->request_fw_load);
guard(mutex)(&cs35l41->fw_mutex);
/* Recheck if playback is ongoing, mutex will block playback during firmware loading */
if (cs35l41->playback_started)
dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback. Retrying...\n");
else
cs35l41_load_firmware(cs35l41, cs35l41->request_fw_load);
cs35l41->fw_request_ongoing = false;
}
pm_runtime_put_autosuspend(cs35l41->dev);
cs35l41->fw_request_ongoing = false;
}
static int cs35l41_fw_load_ctl_put(struct snd_kcontrol *kcontrol,
@ -1455,7 +1452,7 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
if (comp->dev)
return -EBUSY;
pm_runtime_get_sync(dev);
guard(pm_runtime_active_auto)(dev);
mutex_lock(&cs35l41->fw_mutex);
@ -1499,8 +1496,6 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
dev_warn(dev, "Unable to create device link\n");
unlock_system_sleep(sleep_flags);
pm_runtime_put_autosuspend(dev);
dev_info(cs35l41->dev,
"CS35L41 Bound - SSID: %s, BST: %d, VSPK: %d, CH: %c, FW EN: %d, SPKID: %d\n",
cs35l41->acpi_subsystem_id, cs35l41->hw_cfg.bst_type,

View file

@ -588,7 +588,8 @@ static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
cs35l56->base.fw_patched = false;
ret = pm_runtime_resume_and_get(cs35l56->base.dev);
PM_RUNTIME_ACQUIRE_IF_ENABLED(cs35l56->base.dev, pm);
ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
if (ret < 0) {
dev_err(cs35l56->base.dev, "Failed to resume and get %d\n", ret);
return;
@ -601,7 +602,7 @@ static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
*/
ret = cs35l56_read_prot_status(&cs35l56->base, &firmware_missing, &preloaded_fw_ver);
if (ret)
goto err_pm_put;
return;
if (firmware_missing)
preloaded_fw_ver = 0;
@ -690,8 +691,6 @@ err:
err_fw_release:
cs35l56_hda_release_firmware_files(wmfw_firmware, wmfw_filename,
coeff_firmware, coeff_filename);
err_pm_put:
pm_runtime_put(cs35l56->base.dev);
}
static void cs35l56_hda_dsp_work(struct work_struct *work)
@ -708,14 +707,12 @@ static ssize_t cs35l56_hda_debugfs_calibrate_write(struct file *file,
struct cs35l56_base *cs35l56_base = file->private_data;
ssize_t ret;
ret = pm_runtime_resume_and_get(cs35l56_base->dev);
PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(cs35l56_base->dev, pm);
ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
if (ret)
return ret;
ret = cs35l56_calibrate_debugfs_write(cs35l56_base, from, count, ppos);
pm_runtime_autosuspend(cs35l56_base->dev);
return ret;
return cs35l56_calibrate_debugfs_write(cs35l56_base, from, count, ppos);
}
static ssize_t cs35l56_hda_debugfs_cal_temperature_write(struct file *file,
@ -725,14 +722,12 @@ static ssize_t cs35l56_hda_debugfs_cal_temperature_write(struct file *file,
struct cs35l56_base *cs35l56_base = file->private_data;
ssize_t ret;
ret = pm_runtime_resume_and_get(cs35l56_base->dev);
PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(cs35l56_base->dev, pm);
ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
if (ret)
return ret;
ret = cs35l56_cal_ambient_debugfs_write(cs35l56_base, from, count, ppos);
pm_runtime_autosuspend(cs35l56_base->dev);
return ret;
return cs35l56_cal_ambient_debugfs_write(cs35l56_base, from, count, ppos);
}
static ssize_t cs35l56_hda_debugfs_cal_data_read(struct file *file,
@ -742,14 +737,12 @@ static ssize_t cs35l56_hda_debugfs_cal_data_read(struct file *file,
struct cs35l56_base *cs35l56_base = file->private_data;
ssize_t ret;
ret = pm_runtime_resume_and_get(cs35l56_base->dev);
PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(cs35l56_base->dev, pm);
ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
if (ret)
return ret;
ret = cs35l56_cal_data_debugfs_read(cs35l56_base, to, count, ppos);
pm_runtime_autosuspend(cs35l56_base->dev);
return ret;
return cs35l56_cal_data_debugfs_read(cs35l56_base, to, count, ppos);
}
static ssize_t cs35l56_hda_debugfs_cal_data_write(struct file *file,
@ -767,7 +760,8 @@ static ssize_t cs35l56_hda_debugfs_cal_data_write(struct file *file,
if (ret < 0)
return ret;
ret = pm_runtime_resume_and_get(cs35l56_base->dev);
PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(cs35l56_base->dev, pm);
ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
if (ret)
return ret;
@ -777,8 +771,6 @@ static ssize_t cs35l56_hda_debugfs_cal_data_write(struct file *file,
else
count = -EIO;
pm_runtime_autosuspend(cs35l56_base->dev);
return count;
}

View file

@ -2,7 +2,7 @@
//
// TAS2781 HDA Shared Lib for I2C&SPI driver
//
// Copyright 2025 Texas Instruments, Inc.
// Copyright 2025 - 2026 Texas Instruments, Inc.
//
// Author: Shenghao Ding <shenghao-ding@ti.com>
@ -159,7 +159,6 @@ static void tas2781_apply_calib(struct tasdevice_priv *p)
r->tlimit_reg = cali_reg[4];
}
p->is_user_space_calidata = true;
cali_data->total_sz = p->ndev * (cali_data->cali_dat_sz_per_dev + 1);
}
@ -216,6 +215,12 @@ int tas2781_save_calibration(struct tas2781_hda *hda)
status = -ENOMEM;
continue;
}
/*
* Set to an invalid value before the calibrated data
* is stored into it, for the default value is 0, which
* means the first device.
*/
data[0] = 0xff;
/* Get variable contents into buffer */
status = efi.get_variable(efi_name[i], &efi_guid,
&attr, &cali_data->total_sz, data);

View file

@ -393,19 +393,6 @@ static int tas2563_save_calibration(struct tas2781_hda *h)
r->pow_reg = TAS2563_CAL_POWER;
r->tlimit_reg = TAS2563_CAL_TLIM;
/*
* TAS2781_FMWLIB supports two solutions of calibrated data. One is
* from the driver itself: driver reads the calibrated files directly
* during probe; The other from user space: during init of audio hal,
* the audio hal will pass the calibrated data via kcontrol interface.
* Driver will store this data in "struct calidata" for use. For hda
* device, calibrated data are usunally saved into UEFI. So Hda side
* codec driver use the mixture of these two solutions, driver reads
* the data from UEFI, then store this data in "struct calidata" for
* use.
*/
p->is_user_space_calidata = true;
return 0;
}
@ -504,8 +491,8 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
struct hda_codec *codec = tas_priv->codec;
int ret;
pm_runtime_get_sync(tas_priv->dev);
mutex_lock(&tas_priv->codec_lock);
guard(pm_runtime_active_auto)(tas_priv->dev);
guard(mutex)(&tas_priv->codec_lock);
ret = tasdevice_rca_parser(tas_priv, fmw);
if (ret)
@ -541,9 +528,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
}
out:
mutex_unlock(&tas_hda->priv->codec_lock);
release_firmware(fmw);
pm_runtime_put_autosuspend(tas_hda->dev);
}
static int tas2781_hda_bind(struct device *dev, struct device *master,
@ -587,7 +572,7 @@ static int tas2781_hda_bind(struct device *dev, struct device *master,
if (codec->core.subsystem_id == 0x10431384)
hda_priv->skip_calibration = true;
pm_runtime_get_sync(dev);
guard(pm_runtime_active_auto)(dev);
comp->dev = dev;
@ -597,8 +582,6 @@ static int tas2781_hda_bind(struct device *dev, struct device *master,
if (!ret)
comp->playback_hook = tas2781_hda_playback_hook;
pm_runtime_put_autosuspend(dev);
return ret;
}

View file

@ -2,7 +2,7 @@
//
// TAS2781 HDA SPI driver
//
// Copyright 2024 - 2025 Texas Instruments, Inc.
// Copyright 2024 - 2026 Texas Instruments, Inc.
//
// Author: Baojun Xu <baojun.xu@ti.com>
@ -41,9 +41,6 @@
#define TASDEVICE_RANGE_MAX_SIZE (256 * 128)
#define TASDEVICE_WIN_LEN 128
#define TAS2781_SPI_MAX_FREQ (4 * HZ_PER_MHZ)
/* Flag of calibration registers address. */
#define TASDEVICE_CALIBRATION_REG_ADDRESS BIT(7)
#define TASDEV_UEFI_CALI_REG_ADDR_FLG BIT(7)
/* System Reset Check Register */
#define TAS2781_REG_CLK_CONFIG TASDEVICE_REG(0x0, 0x0, 0x5c)
@ -636,7 +633,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
struct hda_codec *codec = tas_priv->codec;
int ret, val;
pm_runtime_get_sync(tas_priv->dev);
guard(pm_runtime_active_auto)(tas_priv->dev);
guard(mutex)(&tas_priv->codec_lock);
ret = tasdevice_rca_parser(tas_priv, fmw);
@ -699,7 +696,6 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
tas2781_save_calibration(tas_hda);
out:
release_firmware(fmw);
pm_runtime_put_autosuspend(tas_hda->priv->dev);
}
static int tas2781_hda_bind(struct device *dev, struct device *master,
@ -720,7 +716,7 @@ static int tas2781_hda_bind(struct device *dev, struct device *master,
codec = parent->codec;
pm_runtime_get_sync(dev);
guard(pm_runtime_active_auto)(dev);
comp->dev = dev;
@ -731,7 +727,8 @@ static int tas2781_hda_bind(struct device *dev, struct device *master,
if (!ret)
comp->playback_hook = tas2781_hda_playback_hook;
pm_runtime_put_autosuspend(dev);
/* Only HP Laptop support SPI-based TAS2781 */
tas_hda->catlog_id = HP;
return ret;
}

View file

@ -1854,9 +1854,9 @@ static int check_follower_present(struct hda_codec *codec,
/* call kctl->put with the given value(s) */
static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
{
struct snd_ctl_elem_value *ucontrol __free(kfree) = NULL;
struct snd_ctl_elem_value *ucontrol __free(kfree) =
kzalloc(sizeof(*ucontrol), GFP_KERNEL);
ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL);
if (!ucontrol)
return -ENOMEM;
ucontrol->value.integer.value[0] = val;

View file

@ -82,10 +82,10 @@ snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid,
int dev_id, hda_jack_callback_fn func);
/**
* snd_hda_jack_detect_enable - enable the jack-detection
* snd_hda_jack_detect_enable_callback - enable the jack-detection
* @codec: the HDA codec
* @nid: pin NID to enable
* @func: callback function to register
* @cb: callback function to register
*
* In the case of error, the return value will be a pointer embedded with
* errno. Check and handle the return value appropriately with standard

View file

@ -424,7 +424,7 @@ int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
unsigned int val, bool cached);
/**
* _snd_hda_set_pin_ctl - Set a pin-control value safely
* snd_hda_set_pin_ctl - Set a pin-control value safely
* @codec: the codec instance
* @pin: the pin NID to set the control
* @val: the pin-control value (AC_PINCTL_* bits)

Some files were not shown because too many files have changed in this diff Show more