mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
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:
commit
d061251387
330 changed files with 14425 additions and 4703 deletions
|
|
@ -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>;
|
||||
};
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = <
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ properties:
|
|||
- fsl,imx53-asrc
|
||||
- fsl,imx8qm-asrc
|
||||
- fsl,imx8qxp-asrc
|
||||
- fsl,imx952-asrc
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx6sx-asrc
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
@ -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>;
|
||||
};
|
||||
|
||||
...
|
||||
|
|
|
|||
61
Documentation/devicetree/bindings/sound/realtek,rt5575.yaml
Normal file
61
Documentation/devicetree/bindings/sound/realtek,rt5575.yaml
Normal 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 */
|
||||
};
|
||||
};
|
||||
100
Documentation/devicetree/bindings/sound/realtek,rt5651.yaml
Normal file
100
Documentation/devicetree/bindings/sound/realtek,rt5651.yaml
Normal 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;
|
||||
};
|
||||
};
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
};
|
||||
|
|
@ -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>;
|
||||
};
|
||||
...
|
||||
|
|
@ -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>;
|
||||
};
|
||||
...
|
||||
|
|
@ -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 = <®_vbat>;
|
||||
iovdd-supply = <®_iovdd>;
|
||||
avdd-supply = <®_avdd>;
|
||||
enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
For more product information please see the link below:
|
||||
https://www.ti.com/product/TAS2552
|
||||
62
Documentation/devicetree/bindings/sound/ti,tas2552.yaml
Normal file
62
Documentation/devicetree/bindings/sound/ti,tas2552.yaml
Normal 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 = <®_vbat>;
|
||||
iovdd-supply = <®_iovdd>;
|
||||
avdd-supply = <®_avdd>;
|
||||
enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
|
@ -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: |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
32
include/sound/sdca_jack.h
Normal 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__
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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]); \
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)(®ister_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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 *),
|
||||
|
|
|
|||
|
|
@ -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 *),
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue