sound updates for 6.7

Most of changes at this time are for ASoC, spread over ASoC core and
 drivers due to the API prefix standardization.  Other than that, there
 have little change wrt API, rather lots of driver-specific updates and
 fixes.  Some highlight below:
 
 ASoC:
 - Standardization of API prefix
 - GPIO API usage improvements
 - Support for HDA patches
 - Lots of work on SOF, including crash dump support
 - Fixes for noise when stopping some Sounwire CODECs
 - Support for AMD platforms with es83xx, AMD ACP 6.3 and 7.0, Awinc
   AT87390 and AW88399, many Intel platforms, many Mediatek platforms,
   Qualcomm SM6115 and SC7180 platforms, Richtek RTQ9128 and Texas
   Instruments TAS575x
 
 HD-audio and USB-audio:
 - Deferred probe support of audio component binding
 - More fixes and enhancements for Cirrus subcodecs
 - USB Scarlett2 mixer and McIntosh DSD quirk
 
 Others:
 - More enhancement of snd-aloop driver
 - Update MAINTAINERS entry for linux-sound mailing list
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmVDqXcOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE+PbhAAsmiOxjXpCNVGbhy9tR+UB9p6gCIzFv5RQQIc
 0DzqnqssbJt86jtFMrv0VC6BNfnwcyBVzKxWinKz861xXiM9SRU5vTirUES3Cil/
 sZaQYC9ppTrZm3q2EGF4eGC349oZGzuLzk1EkEVPfNHiELwcO4R1NZbtgWKIc8LE
 bNz8RT3FyxHAv+5juW5suGs0Bq4Mwa9z+eM8xEPwxPL3gpIAb5EapIesHEgaa893
 w3jYwKRHCDq0ADtXIY9xI3ypqenfbeTge4nuBnw354sPRVdZInrRfCNkTJojb+tp
 5Pc2gpFmTUGy6T2wG6QP23VgeV14BJHrQD3Z1Wh2aQ8V+ARa92XvY1Xeg4vJ+NE0
 yhvlh028GjKrMIvhl7mmepV9mia2zA1TluqlzKEla3B5lIj0E1zvMA+vCzNAz3Ro
 lV2Q0dpJ3ENQ9ahGF/d37u3glrqXxISlG9uTGdY0UcF7U9Iyxb0jEnhQYl05b+zR
 Oaw/HApuvIUj4cdJWEYf0AnTTqeE8KSZ3wUlPPyuQAdAusCaQFMciWeO0EeLqEId
 KR/rbnSgVKS3zHLdNw5A67Sv36E9OG/E+EiJ6Tet15a69yq2Oyv4pwMMwbqsvBG5
 8kNbtBFGxOHnCrZgM6VV2/g3BP/IwyIFd5kkS2q13FXBTYRpY01dQDjHlmspasNK
 hYH69AA=
 =2/dI
 -----END PGP SIGNATURE-----

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

Pull sound updates from Takashi Iwai:
 "Most of changes at this time are for ASoC, spread over ASoC core and
  drivers due to the API prefix standardization.

  Other than that, there have little change wrt API, rather lots of
  driver-specific updates and fixes.

  Some highlight below:

  ASoC:
   - Standardization of API prefix
   - GPIO API usage improvements
   - Support for HDA patches
   - Lots of work on SOF, including crash dump support
   - Fixes for noise when stopping some Sounwire CODECs
   - Support for AMD platforms with es83xx, AMD ACP 6.3 and 7.0, Awinc
     AT87390 and AW88399, many Intel platforms, many Mediatek platforms,
     Qualcomm SM6115 and SC7180 platforms, Richtek RTQ9128 and Texas
     Instruments TAS575x

  HD-audio and USB-audio:
   - Deferred probe support of audio component binding
   - More fixes and enhancements for Cirrus subcodecs
   - USB Scarlett2 mixer and McIntosh DSD quirk

  Others:
   - More enhancement of snd-aloop driver
   - Update MAINTAINERS entry for linux-sound mailing list"

* tag 'sound-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (485 commits)
  ALSA: hda: cs35l41: Fix missing error code in cs35l41_smart_amp()
  ALSA: hda: cs35l41: mark cs35l41_verify_id() static
  ASoC: codecs: wsa883x: make use of new mute_unmute_on_trigger flag
  ASoC: soc-dai: add flag to mute and unmute stream during trigger
  ASoC: ams-delta.c: use component after check
  ASoC: amd: acp: select SND_SOC_AMD_ACP_LEGACY_COMMON for ACP63
  ASoC: codecs: aw88399: fix typo in Kconfig select
  ASoC: amd: acp: add ACPI dependency
  ASoC: Intel: avs: Add rt5514 machine board
  ASoC: Intel: avs: Add rt5514 machine board
  ALSA: scarlett2: Add missing check with firmware version control
  ALSA: virtio: use ack callback
  ALSA: scarlett2: Remap Level Meter values
  ALSA: scarlett2: Allow passing any output to line_out_remap()
  ALSA: scarlett2: Add support for reading firmware version
  ALSA: scarlett2: Rename Gen 3 config sets
  ALSA: scarlett2: Rename scarlett_gen2 to scarlett2
  ASoC: cs35l41: Detect CSPL errors when sending CSPL commands
  ALSA: hda: cs35l41: Check CSPL state after loading firmware
  ALSA: hda: cs35l41: Do not unload firmware before reset in system suspend
  ...
This commit is contained in:
Linus Torvalds 2023-11-02 14:34:14 -10:00
commit edd8e84ae9
713 changed files with 16721 additions and 5990 deletions

View File

@ -13,19 +13,17 @@ select: false
definitions:
port-base:
$ref: /schemas/graph.yaml#/$defs/port-base
allOf:
- $ref: /schemas/graph.yaml#/$defs/port-base
- $ref: /schemas/sound/dai-params.yaml#
properties:
convert-rate:
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate
convert-channels:
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels
convert-sample-format:
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format
mclk-fs:
$ref: simple-card.yaml#/definitions/mclk-fs
endpoint-base:
$ref: /schemas/graph.yaml#/$defs/endpoint-base
allOf:
- $ref: /schemas/graph.yaml#/$defs/endpoint-base
- $ref: /schemas/sound/dai-params.yaml#
properties:
mclk-fs:
$ref: simple-card.yaml#/definitions/mclk-fs
@ -68,12 +66,6 @@ definitions:
- pdm
- msb
- lsb
convert-rate:
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate
convert-channels:
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels
convert-sample-format:
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format
dai-tdm-slot-num:
description: Number of slots in use.

View File

@ -9,6 +9,9 @@ title: Audio Graph
maintainers:
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
allOf:
- $ref: /schemas/sound/dai-params.yaml#
properties:
dais:
$ref: /schemas/types.yaml#/definitions/phandle-array
@ -30,12 +33,6 @@ properties:
widget ("Microphone", "Line", "Headphone", "Speaker"), the
second being the machine specific name for the widget.
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
convert-rate:
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate
convert-channels:
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels
convert-sample-format:
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format
pa-gpios:
maxItems: 1

View File

@ -0,0 +1,58 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/awinic,aw87390.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Awinic Aw87390 Audio Amplifier
maintainers:
- Weidong Wang <wangweidong.a@awinic.com>
description:
The awinic aw87390 is specifically designed to improve
the musical output dynamic range, enhance the overall
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
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
awinic,audio-channel:
description:
It is used to distinguish multiple PA devices, so that different
configurations can be loaded to different PA devices
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 7
required:
- compatible
- reg
- "#sound-dai-cells"
- awinic,audio-channel
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@58 {
compatible = "awinic,aw87390";
reg = <0x58>;
#sound-dai-cells = <0>;
awinic,audio-channel = <0>;
};
};

View File

@ -14,14 +14,12 @@ description:
digital Smart K audio amplifier with an integrated 10.25V
smart boost convert.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
enum:
- awinic,aw88395
- awinic,aw88261
- awinic,aw88399
reg:
maxItems: 1
@ -32,11 +30,36 @@ properties:
reset-gpios:
maxItems: 1
awinic,audio-channel:
description:
It is used to distinguish multiple PA devices, so that different
configurations can be loaded to different PA devices
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 7
awinic,sync-flag:
description:
Flag bit used to keep the phase synchronized in the case of multiple PA
$ref: /schemas/types.yaml#/definitions/flag
required:
- compatible
- reg
- '#sound-dai-cells'
- reset-gpios
- awinic,audio-channel
allOf:
- $ref: dai-common.yaml#
- if:
properties:
compatible:
contains:
enum:
- awinic,aw88261
then:
properties:
reset-gpios: false
unevaluatedProperties: false
@ -51,5 +74,7 @@ examples:
reg = <0x34>;
#sound-dai-cells = <0>;
reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
awinic,audio-channel = <0>;
awinic,sync-flag;
};
};

View File

@ -83,7 +83,7 @@ properties:
Current at which the headset micbias sense clamp will engage, 0 to
disable.
enum: [ 0, 14, 24, 43, 52, 61, 71, 90, 99 ]
default: 0
default: 14
cirrus,bias-ramp-ms:
description:
@ -97,7 +97,7 @@ properties:
Time in microseconds the type detection will run for. Long values will
cause more audible effects, but give more accurate detection.
enum: [ 20, 100, 1000, 10000, 50000, 75000, 100000, 200000 ]
default: 10000
default: 1000
cirrus,button-automute:
type: boolean

View File

@ -11,15 +11,14 @@ maintainers:
select: false
$defs:
dai-channels:
properties:
convert-channels:
description: Number of audio channels used by DAI
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1
maximum: 32
dai-sample-format:
convert-sample-format:
description: Audio sample format used by DAI
$ref: /schemas/types.yaml#/definitions/string
enum:
@ -29,12 +28,10 @@ $defs:
- s24_3le
- s32_le
dai-sample-rate:
convert-rate:
description: Audio sample rate used by DAI
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 8000
maximum: 192000
properties: {}
additionalProperties: true

View File

@ -89,6 +89,7 @@ properties:
da7219_aad:
type: object
additionalProperties: false
description:
Configuration of advanced accessory detection.
properties:

View File

@ -33,6 +33,7 @@ patternProperties:
description:
A DAI managed by this controller
type: object
additionalProperties: false
properties:
reg:

View File

@ -17,6 +17,7 @@ properties:
enum:
- mediatek,mt8188-mt6359-evb
- mediatek,mt8188-nau8825
- mediatek,mt8188-rt5682s
audio-routing:
description:

View File

@ -17,6 +17,7 @@ properties:
enum:
- mediatek,mt8186-mt6366-rt1019-rt5682s-sound
- mediatek,mt8186-mt6366-rt5682s-max98360-sound
- mediatek,mt8186-mt6366-rt5650-sound
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle

View File

@ -0,0 +1,44 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nxp,tfa9879.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP TFA9879 class-D audio amplifier
maintainers:
- Peter Rosin <peda@axentia.se>
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: nxp,tfa9879
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
required:
- compatible
- reg
- '#sound-dai-cells'
unevaluatedProperties: false
examples:
- |
i2c1 {
#address-cells = <1>;
#size-cells = <0>;
amplifier@6c {
compatible = "nxp,tfa9879";
reg = <0x6c>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
#sound-dai-cells = <0>;
};
};

View File

@ -1,12 +1,12 @@
PCM512x audio CODECs
PCM512x and TAS575x audio CODECs/amplifiers
These devices support both I2C and SPI (configured with pin strapping
on the board).
on the board). The TAS575x devices only support I2C.
Required properties:
- compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141" or
"ti,pcm5142"
- compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141",
"ti,pcm5142", "ti,tas5754" or "ti,tas5756"
- reg : the I2C address of the device for I2C, the chip select
number for SPI.
@ -25,6 +25,7 @@ Optional properties:
through <6>. The device will be configured for clock input on the
given pll-in pin and PLL output on the given pll-out pin. An
external connection from the pll-out pin to the SCLK pin is assumed.
Caution: the TAS-desvices only support gpios 1,2 and 3
Examples:

View File

@ -13,6 +13,7 @@ properties:
compatible:
enum:
- qcom,sc7280-lpass-tx-macro
- qcom,sm6115-lpass-tx-macro
- qcom,sm8250-lpass-tx-macro
- qcom,sm8450-lpass-tx-macro
- qcom,sm8550-lpass-tx-macro
@ -97,6 +98,23 @@ allOf:
- const: dcodec
- const: fsgen
- if:
properties:
compatible:
enum:
- qcom,sm6115-lpass-tx-macro
then:
properties:
clocks:
minItems: 4
maxItems: 4
clock-names:
items:
- const: mclk
- const: npl
- const: dcodec
- const: fsgen
- if:
properties:
compatible:

View File

@ -25,6 +25,7 @@ properties:
- qcom,apq8016-sbc-sndcard
- qcom,msm8916-qdsp6-sndcard
- qcom,qrb5165-rb5-sndcard
- qcom,sc7180-qdsp6-sndcard
- qcom,sc8280xp-sndcard
- qcom,sdm845-sndcard
- qcom,sm8250-sndcard

View File

@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/realtek,rt5616.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Realtek rt5616 ALSA SoC audio codec driver
description: |
Pins on the device (for linking into audio routes) for RT5616:
* IN1P
* IN2P
* IN2N
* LOUTL
* LOUTR
* HPOL
* HPOR
maintainers:
- Bard Liao <bardliao@realtek.com>
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: realtek,rt5616
reg:
maxItems: 1
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@1b {
compatible = "realtek,rt5616";
reg = <0x1b>;
};
};

View File

@ -0,0 +1,61 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/richtek,rtq9128.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Richtek RTQ9128 Automative Audio Power Amplifier
maintainers:
- ChiYuan Huang <cy_huang@richtek.com>
description:
The RTQ9128 is a ultra-low output noise, high-efficiency, four-channel
class-D audio power amplifier and delivering 4x75W into 4OHm at 10%
THD+N from a 25V supply in automotive applications.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
enum:
- richtek,rtq9128
reg:
maxItems: 1
enable-gpios:
maxItems: 1
richtek,tdm-input-data2-select:
type: boolean
description:
By default, if TDM mode is used, TDM data input will select 'DATA1' pin
as the data source. This option will configure TDM data input source from
'DATA1' to 'DATA2' pin.
'#sound-dai-cells':
const: 0
required:
- compatible
- reg
- '#sound-dai-cells'
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
speaker@1a {
compatible = "richtek,rtq9128";
reg = <0x1a>;
enable-gpios = <&gpio 26 GPIO_ACTIVE_HIGH>;
#sound-dai-cells = <0>;
};
};

View File

@ -1,32 +0,0 @@
RT5616 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "realtek,rt5616".
- reg : The I2C address of the device.
Optional properties:
- clocks: The phandle of the master clock to the CODEC.
- clock-names: Should be "mclk".
Pins on the device (for linking into audio routes) for RT5616:
* IN1P
* IN2P
* IN2N
* LOUTL
* LOUTR
* HPOL
* HPOR
Example:
rt5616: codec@1b {
compatible = "realtek,rt5616";
reg = <0x1b>;
};

View File

@ -0,0 +1,76 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/starfive,jh7110-pwmdac.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: StarFive JH7110 PWM-DAC Controller
description:
The PWM-DAC Controller uses PWM square wave generators plus RC filters to
form a DAC for audio play in StarFive JH7110 SoC. This audio play controller
supports 16 bit audio format, up to 48K sampling frequency, up to left and
right dual channels.
maintainers:
- Hal Feng <hal.feng@starfivetech.com>
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: starfive,jh7110-pwmdac
reg:
maxItems: 1
clocks:
items:
- description: PWMDAC APB
- description: PWMDAC CORE
clock-names:
items:
- const: apb
- const: core
resets:
maxItems: 1
description: PWMDAC APB
dmas:
maxItems: 1
description: TX DMA Channel
dma-names:
const: tx
"#sound-dai-cells":
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- resets
- dmas
- dma-names
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
pwmdac@100b0000 {
compatible = "starfive,jh7110-pwmdac";
reg = <0x100b0000 0x1000>;
clocks = <&syscrg 157>,
<&syscrg 158>;
clock-names = "apb", "core";
resets = <&syscrg 96>;
dmas = <&dma 22>;
dma-names = "tx";
#sound-dai-cells = <0>;
};

View File

@ -37,6 +37,8 @@ properties:
generated from TI's PPC3 tool.
$ref: /schemas/types.yaml#/definitions/string
additionalProperties: false
examples:
- |
i2c {
@ -52,5 +54,4 @@ examples:
ti,dsp-config-name = "mono_pbtl_48khz";
};
};
additionalProperties: true
...

View File

@ -1,23 +0,0 @@
NXP TFA9879 class-D audio amplifier
Required properties:
- compatible : "nxp,tfa9879"
- reg : the I2C address of the device
- #sound-dai-cells : must be 0.
Example:
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
amp: amp@6c {
#sound-dai-cells = <0>;
compatible = "nxp,tfa9879";
reg = <0x6c>;
};
};

View File

@ -60,6 +60,7 @@ properties:
ports:
$ref: audio-graph-port.yaml#/definitions/port-base
unevaluatedProperties: false
properties:
port@0:
$ref: audio-graph-port.yaml#

View File

@ -8,10 +8,17 @@ Required properties:
- Vdda-supply : phandle to a regulator for the analog power supply (2.7V - 5.5V)
- Vdd-supply : phandle to a regulator for the digital power supply (2.7V - 3.6V)
Optional properties:
- wlf,fsampen:
FSAMPEN pin value, 0 for low, 1 for high, 2 for disconnected.
Defaults to 0 if left unspecified.
Example:
wm8782: stereo-adc {
compatible = "wlf,wm8782";
Vdda-supply = <&vdda_supply>;
Vdd-supply = <&vdd_supply>;
wlf,fsampen = <2>; /* 192KHz */
};

View File

@ -70,7 +70,8 @@ file:
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.ignore_suspend = 1,
.params = &dsp_codec_params,
.c2c_params = &dsp_codec_params,
.num_c2c_params = 1,
},
{
.name = "DSP-CODEC",
@ -81,12 +82,13 @@ file:
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.ignore_suspend = 1,
.params = &dsp_codec_params,
.c2c_params = &dsp_codec_params,
.num_c2c_params = 1,
},
Above code snippet is motivated from sound/soc/samsung/speyside.c.
Note the "params" callback which lets the dapm know that this
Note the "c2c_params" callback which lets the dapm know that this
dai_link is a codec to codec connection.
In dapm core a route is created between cpu_dai playback widget

View File

@ -368,7 +368,8 @@ The machine driver sets some additional parameters to the DAI link i.e.
.codec_name = "modem",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.params = &dai_params,
.c2c_params = &dai_params,
.num_c2c_params = 1,
}
< ... more DAI links here ... >

View File

@ -4959,6 +4959,7 @@ F: drivers/spi/spi-cs42l43*
F: include/dt-bindings/sound/cs*
F: include/linux/mfd/cs42l43*
F: include/sound/cs*
F: sound/pci/hda/cirrus*
F: sound/pci/hda/cs*
F: sound/pci/hda/hda_cs_dsp_ctl.*
F: sound/soc/codecs/cs*
@ -8217,7 +8218,7 @@ M: Geoffrey D. Bennett <g@b4.vu>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
F: sound/usb/mixer_scarlett_gen2.c
F: sound/usb/mixer_scarlett2.c
FORCEDETH GIGABIT ETHERNET DRIVER
M: Rain River <rain.1986.08.12@gmail.com>
@ -15522,7 +15523,7 @@ NXP TFA9879 DRIVER
M: Peter Rosin <peda@axentia.se>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/tfa9879.txt
F: Documentation/devicetree/bindings/sound/nxp,tfa9879.yaml
F: sound/soc/codecs/tfa9879*
NXP-NCI NFC DRIVER
@ -20187,7 +20188,7 @@ F: Documentation/devicetree/bindings/riscv/sophgo.yaml
SOUND
M: Jaroslav Kysela <perex@perex.cz>
M: Takashi Iwai <tiwai@suse.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
L: linux-sound@vger.kernel.org
S: Maintained
W: http://www.alsa-project.org/
Q: http://patchwork.kernel.org/project/alsa-devel/list/
@ -20200,7 +20201,7 @@ F: tools/testing/selftests/alsa
SOUND - ALSA SELFTESTS
M: Mark Brown <broonie@kernel.org>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
L: linux-sound@vger.kernel.org
L: linux-kselftest@vger.kernel.org
S: Supported
F: tools/testing/selftests/alsa
@ -20226,7 +20227,7 @@ F: sound/soc/soc-generic-dmaengine-pcm.c
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
M: Liam Girdwood <lgirdwood@gmail.com>
M: Mark Brown <broonie@kernel.org>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
L: linux-sound@vger.kernel.org
S: Supported
W: http://alsa-project.org/main/index.php/ASoC
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
@ -20234,6 +20235,10 @@ F: Documentation/devicetree/bindings/sound/
F: Documentation/sound/soc/
F: include/dt-bindings/sound/
F: include/sound/soc*
F: include/sound/sof.h
F: include/sound/sof/
F: include/trace/events/sof*.h
F: include/uapi/sound/asoc.h
F: sound/soc/
SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS
@ -20587,6 +20592,13 @@ S: Supported
F: Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml
F: drivers/clk/starfive/clk-starfive-jh7110-pll.c
STARFIVE JH7110 PWMDAC DRIVER
M: Hal Feng <hal.feng@starfivetech.com>
M: Xingyu Wu <xingyu.wu@starfivetech.com>
S: Supported
F: Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
F: sound/soc/starfive/jh7110_pwmdac.c
STARFIVE JH7110 SYSCON
M: William Qiu <william.qiu@starfivetech.com>
M: Xingyu Wu <xingyu.wu@starfivetech.com>
@ -23061,7 +23073,7 @@ F: fs/vboxsf/*
VIRTUAL PCM TEST DRIVER
M: Ivan Orlov <ivan.orlov0322@gmail.com>
L: alsa-devel@alsa-project.org
L: linux-sound@vger.kernel.org
S: Maintained
F: Documentation/sound/cards/pcmtest.rst
F: sound/drivers/pcmtest.c

View File

@ -498,6 +498,15 @@ struct menelaus_platform_data n8x0_menelaus_platform_data = {
.late_init = n8x0_menelaus_late_init,
};
static struct gpiod_lookup_table nokia810_asoc_gpio_table = {
.dev_id = "soc-audio",
.table = {
GPIO_LOOKUP("gpio-0-15", 10, "headset", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("gpio-80-111", 21, "speaker", GPIO_ACTIVE_HIGH),
{ }
},
};
static int __init n8x0_late_initcall(void)
{
if (!board_caps)
@ -505,6 +514,7 @@ static int __init n8x0_late_initcall(void)
n8x0_mmc_init();
n8x0_usb_init();
gpiod_add_lookup_table(&nokia810_asoc_gpio_table);
return 0;
}

View File

@ -275,9 +275,19 @@ static struct platform_device pandora_backlight = {
.id = -1,
};
static struct gpiod_lookup_table pandora_soc_audio_gpios = {
.dev_id = "soc-audio",
.table = {
GPIO_LOOKUP("gpio-112-127", 6, "dac", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("gpio-0-15", 14, "amp", GPIO_ACTIVE_HIGH),
{ }
},
};
static void __init omap3_pandora_legacy_init(void)
{
platform_device_register(&pandora_backlight);
gpiod_add_lookup_table(&pandora_soc_audio_gpios);
}
#endif /* CONFIG_ARCH_OMAP3 */

View File

@ -881,7 +881,7 @@ static struct platform_device fsi_device = {
.resource = fsi_resources,
};
static struct asoc_simple_card_info fsi_da7210_info = {
static struct simple_util_info fsi_da7210_info = {
.name = "DA7210",
.card = "FSIB-DA7210",
.codec = "da7210.0-001a",

View File

@ -300,7 +300,7 @@ static struct platform_device fsi_device = {
.resource = fsi_resources,
};
static struct asoc_simple_card_info fsi_ak4642_info = {
static struct simple_util_info fsi_ak4642_info = {
.name = "AK4642",
.card = "FSIA-AK4642",
.codec = "ak4642-codec.0-0012",

View File

@ -522,6 +522,10 @@ static struct gpio_desc *of_find_gpio_rename(struct device_node *np,
#if IS_ENABLED(CONFIG_SND_SOC_CS42L56)
{ "reset", "cirrus,gpio-nreset", "cirrus,cs42l56" },
#endif
#if IS_ENABLED(CONFIG_SND_SOC_MT2701_CS42448)
{ "i2s1-in-sel-gpio1", NULL, "mediatek,mt2701-cs42448-machine" },
{ "i2s1-in-sel-gpio2", NULL, "mediatek,mt2701-cs42448-machine" },
#endif
#if IS_ENABLED(CONFIG_SND_SOC_TLV320AIC3X)
{ "reset", "gpio-reset", "ti,tlv320aic3x" },
{ "reset", "gpio-reset", "ti,tlv320aic33" },

View File

@ -759,7 +759,7 @@ static int intel_prepare(struct snd_pcm_substream *substream,
}
if (dai_runtime->suspended) {
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_hw_params *hw_params;
hw_params = &rtd->dpcm[substream->stream].hw_params;

View File

@ -327,7 +327,7 @@ static int intel_prepare(struct snd_pcm_substream *substream,
}
if (dai_runtime->suspended) {
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_hw_params *hw_params;
hw_params = &rtd->dpcm[substream->stream].hw_params;

View File

@ -1819,7 +1819,7 @@ void sdw_shutdown_stream(void *sdw_substream)
struct snd_soc_dai *dai;
/* Find stream from first CPU DAI */
dai = asoc_rtd_to_cpu(rtd, 0);
dai = snd_soc_rtd_to_cpu(rtd, 0);
sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);

View File

@ -37,9 +37,6 @@ struct omap_tw4030_pdata {
bool has_digimic0;
bool has_digimic1;
u8 has_linein;
/* Jack detect GPIO or <= 0 if it is not implemented */
int jack_detect;
};
#endif /* _OMAP_TWL4030_H_ */

View File

@ -11,7 +11,6 @@
#define __CS35L41_H
#include <linux/regmap.h>
#include <linux/completion.h>
#include <linux/firmware/cirrus/cs_dsp.h>
#define CS35L41_FIRSTREG 0x00000000
@ -736,6 +735,7 @@
#define CS35L41_REVID_B2 0xB2
#define CS35L41_HALO_CORE_RESET 0x00000200
#define CS35L41_SOFTWARE_RESET 0x5A000000
#define CS35L41_FS1_WINDOW_MASK 0x000007FF
#define CS35L41_FS2_WINDOW_MASK 0x00FFF800
@ -816,6 +816,8 @@ struct cs35l41_otp_map_element_t {
};
enum cs35l41_cspl_mbox_status {
CSPL_MBOX_STS_ERROR = U32_MAX,
CSPL_MBOX_STS_ERROR2 = 0x00ffffff, // firmware not always sign-extending 24-bit value
CSPL_MBOX_STS_RUNNING = 0,
CSPL_MBOX_STS_PAUSED = 1,
CSPL_MBOX_STS_RDY_FOR_REINIT = 2,
@ -902,7 +904,8 @@ int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap);
int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
struct cs35l41_hw_cfg *hw_cfg);
bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type);
int cs35l41_mdsync_up(struct regmap *regmap);
int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l41_boost_type b_type,
int enable, struct completion *pll_lock, bool firmware_running);
int enable, bool firmware_running);
#endif /* __CS35L41_H */

View File

@ -242,9 +242,8 @@
#define CS35L56_CONTROL_PORT_READY_US 2200
#define CS35L56_HALO_STATE_POLL_US 1000
#define CS35L56_HALO_STATE_TIMEOUT_US 50000
#define CS35L56_HIBERNATE_WAKE_POLL_US 500
#define CS35L56_HIBERNATE_WAKE_TIMEOUT_US 5000
#define CS35L56_RESET_PULSE_MIN_US 1100
#define CS35L56_WAKE_HOLD_TIME_US 1000
#define CS35L56_SDW1_PLAYBACK_PORT 1
#define CS35L56_SDW1_CAPTURE_PORT 3

View File

@ -9,27 +9,27 @@
#include <sound/simple_card_utils.h>
typedef int (*GRAPH2_CUSTOM)(struct asoc_simple_priv *priv,
typedef int (*GRAPH2_CUSTOM)(struct simple_util_priv *priv,
struct device_node *lnk,
struct link_info *li);
struct graph2_custom_hooks {
int (*hook_pre)(struct asoc_simple_priv *priv);
int (*hook_post)(struct asoc_simple_priv *priv);
int (*hook_pre)(struct simple_util_priv *priv);
int (*hook_post)(struct simple_util_priv *priv);
GRAPH2_CUSTOM custom_normal;
GRAPH2_CUSTOM custom_dpcm;
GRAPH2_CUSTOM custom_c2c;
};
int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev);
int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev,
int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev);
int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev,
struct graph2_custom_hooks *hooks);
int audio_graph2_link_normal(struct asoc_simple_priv *priv,
int audio_graph2_link_normal(struct simple_util_priv *priv,
struct device_node *lnk, struct link_info *li);
int audio_graph2_link_dpcm(struct asoc_simple_priv *priv,
int audio_graph2_link_dpcm(struct simple_util_priv *priv,
struct device_node *lnk, struct link_info *li);
int audio_graph2_link_c2c(struct asoc_simple_priv *priv,
int audio_graph2_link_c2c(struct simple_util_priv *priv,
struct device_node *lnk, struct link_info *li);
#endif /* __GRAPH_CARD_H */

View File

@ -91,6 +91,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_REG_SD_BDLPL 0x18
#define AZX_REG_SD_BDLPU 0x1c
#define AZX_SD_FIFOSIZE_MASK GENMASK(15, 0)
/* GTS registers */
#define AZX_REG_LLCH 0x14

View File

@ -573,7 +573,7 @@ void snd_hdac_stream_release(struct hdac_stream *azx_dev);
struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus,
int dir, int stream_tag);
int snd_hdac_stream_setup(struct hdac_stream *azx_dev);
int snd_hdac_stream_setup(struct hdac_stream *azx_dev, bool code_loading);
void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev);
int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev);
int snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
@ -624,6 +624,9 @@ int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value);
#define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
read_poll_timeout_atomic(snd_hdac_reg_readb, val, cond, delay_us, timeout_us, \
false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readw_poll(dev, reg, val, cond, delay_us, timeout_us) \
read_poll_timeout_atomic(snd_hdac_reg_readw, val, cond, delay_us, timeout_us, \
false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
read_poll_timeout_atomic(snd_hdac_reg_readl, val, cond, delay_us, timeout_us, \
false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)

View File

@ -60,6 +60,8 @@ struct hdac_ext_stream {
bool link_locked:1;
bool link_prepared;
int (*host_setup)(struct hdac_stream *, bool);
struct snd_pcm_substream *link_substream;
};
@ -86,6 +88,7 @@ void snd_hdac_ext_stream_start(struct hdac_ext_stream *hext_stream);
void snd_hdac_ext_stream_clear(struct hdac_ext_stream *hext_stream);
void snd_hdac_ext_stream_reset(struct hdac_ext_stream *hext_stream);
int snd_hdac_ext_stream_setup(struct hdac_ext_stream *hext_stream, int fmt);
int snd_hdac_ext_host_stream_setup(struct hdac_ext_stream *hext_stream, bool code_loading);
struct hdac_ext_link {
struct hdac_bus *bus;

View File

@ -9,14 +9,10 @@
/**
* struct max9768_pdata - optional platform specific MAX9768 configuration
* @shdn_gpio: GPIO to SHDN pin. If not valid, pin must be hardwired HIGH
* @mute_gpio: GPIO to MUTE pin. If not valid, control for mute won't be added
* @flags: configuration flags, e.g. set classic PWM mode (check datasheet
* regarding "filterless modulation" which is default).
*/
struct max9768_pdata {
int shdn_gpio;
int mute_gpio;
unsigned flags;
#define MAX9768_FLAG_CLASSIC_PWM (1 << 0)
};

View File

@ -229,7 +229,7 @@ struct fm_operator {
unsigned char attack_decay;
unsigned char sustain_release;
unsigned char wave_select;
} __attribute__((packed));
} __packed;
/* Instrument data */
struct fm_instrument {

View File

@ -12,15 +12,15 @@
#include <sound/soc.h>
#include <sound/simple_card_utils.h>
struct asoc_simple_card_info {
struct simple_util_info {
const char *name;
const char *card;
const char *codec;
const char *platform;
unsigned int daifmt;
struct asoc_simple_dai cpu_dai;
struct asoc_simple_dai codec_dai;
struct simple_util_dai cpu_dai;
struct simple_util_dai codec_dai;
};
#endif /* __SIMPLE_CARD_H */

View File

@ -11,18 +11,18 @@
#include <linux/clk.h>
#include <sound/soc.h>
#define asoc_simple_init_hp(card, sjack, prefix) \
asoc_simple_init_jack(card, sjack, 1, prefix, NULL)
#define asoc_simple_init_mic(card, sjack, prefix) \
asoc_simple_init_jack(card, sjack, 0, prefix, NULL)
#define simple_util_init_hp(card, sjack, prefix) \
simple_util_init_jack(card, sjack, 1, prefix, NULL)
#define simple_util_init_mic(card, sjack, prefix) \
simple_util_init_jack(card, sjack, 0, prefix, NULL)
struct asoc_simple_tdm_width_map {
struct simple_util_tdm_width_map {
u8 sample_bits;
u8 slot_count;
u16 slot_width;
};
struct asoc_simple_dai {
struct simple_util_dai {
const char *name;
unsigned int sysclk;
int clk_direction;
@ -32,17 +32,17 @@ struct asoc_simple_dai {
unsigned int rx_slot_mask;
struct clk *clk;
bool clk_fixed;
struct asoc_simple_tdm_width_map *tdm_width_map;
struct simple_util_tdm_width_map *tdm_width_map;
int n_tdm_widths;
};
struct asoc_simple_data {
struct simple_util_data {
u32 convert_rate;
u32 convert_channels;
const char *convert_sample_format;
};
struct asoc_simple_jack {
struct simple_util_jack {
struct snd_soc_jack jack;
struct snd_soc_jack_pin pin;
struct snd_soc_jack_gpio gpio;
@ -54,21 +54,21 @@ struct prop_nums {
int platforms;
};
struct asoc_simple_priv {
struct simple_util_priv {
struct snd_soc_card snd_card;
struct simple_dai_props {
struct asoc_simple_dai *cpu_dai;
struct asoc_simple_dai *codec_dai;
struct asoc_simple_data adata;
struct simple_util_dai *cpu_dai;
struct simple_util_dai *codec_dai;
struct simple_util_data adata;
struct snd_soc_codec_conf *codec_conf;
struct prop_nums num;
unsigned int mclk_fs;
} *dai_props;
struct asoc_simple_jack hp_jack;
struct asoc_simple_jack mic_jack;
struct simple_util_jack hp_jack;
struct simple_util_jack mic_jack;
struct snd_soc_jack *aux_jacks;
struct snd_soc_dai_link *dai_link;
struct asoc_simple_dai *dais;
struct simple_util_dai *dais;
struct snd_soc_dai_link_component *dlcs;
struct snd_soc_codec_conf *codec_conf;
struct gpio_desc *pa_gpio;
@ -130,75 +130,75 @@ struct link_info {
struct prop_nums num[SNDRV_MAX_LINKS];
};
int asoc_simple_parse_daifmt(struct device *dev,
int simple_util_parse_daifmt(struct device *dev,
struct device_node *node,
struct device_node *codec,
char *prefix,
unsigned int *retfmt);
int asoc_simple_parse_tdm_width_map(struct device *dev, struct device_node *np,
struct asoc_simple_dai *dai);
int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np,
struct simple_util_dai *dai);
__printf(3, 4)
int asoc_simple_set_dailink_name(struct device *dev,
int simple_util_set_dailink_name(struct device *dev,
struct snd_soc_dai_link *dai_link,
const char *fmt, ...);
int asoc_simple_parse_card_name(struct snd_soc_card *card,
int simple_util_parse_card_name(struct snd_soc_card *card,
char *prefix);
int asoc_simple_parse_clk(struct device *dev,
int simple_util_parse_clk(struct device *dev,
struct device_node *node,
struct asoc_simple_dai *simple_dai,
struct simple_util_dai *simple_dai,
struct snd_soc_dai_link_component *dlc);
int asoc_simple_startup(struct snd_pcm_substream *substream);
void asoc_simple_shutdown(struct snd_pcm_substream *substream);
int asoc_simple_hw_params(struct snd_pcm_substream *substream,
int simple_util_startup(struct snd_pcm_substream *substream);
void simple_util_shutdown(struct snd_pcm_substream *substream);
int simple_util_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd);
int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd);
int simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
#define asoc_simple_parse_tdm(np, dai) \
#define simple_util_parse_tdm(np, dai) \
snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \
&(dai)->rx_slot_mask, \
&(dai)->slots, \
&(dai)->slot_width);
void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platforms,
void simple_util_canonicalize_platform(struct snd_soc_dai_link_component *platforms,
struct snd_soc_dai_link_component *cpus);
void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus,
void simple_util_canonicalize_cpu(struct snd_soc_dai_link_component *cpus,
int is_single_links);
void asoc_simple_clean_reference(struct snd_soc_card *card);
void simple_util_clean_reference(struct snd_soc_card *card);
void asoc_simple_parse_convert(struct device_node *np, char *prefix,
struct asoc_simple_data *data);
bool asoc_simple_is_convert_required(const struct asoc_simple_data *data);
void simple_util_parse_convert(struct device_node *np, char *prefix,
struct simple_util_data *data);
bool simple_util_is_convert_required(const struct simple_util_data *data);
int asoc_simple_parse_routing(struct snd_soc_card *card,
int simple_util_parse_routing(struct snd_soc_card *card,
char *prefix);
int asoc_simple_parse_widgets(struct snd_soc_card *card,
int simple_util_parse_widgets(struct snd_soc_card *card,
char *prefix);
int asoc_simple_parse_pin_switches(struct snd_soc_card *card,
int simple_util_parse_pin_switches(struct snd_soc_card *card,
char *prefix);
int asoc_simple_init_jack(struct snd_soc_card *card,
struct asoc_simple_jack *sjack,
int simple_util_init_jack(struct snd_soc_card *card,
struct simple_util_jack *sjack,
int is_hp, char *prefix, char *pin);
int asoc_simple_init_aux_jacks(struct asoc_simple_priv *priv,
int simple_util_init_aux_jacks(struct simple_util_priv *priv,
char *prefix);
int asoc_simple_init_priv(struct asoc_simple_priv *priv,
int simple_util_init_priv(struct simple_util_priv *priv,
struct link_info *li);
int asoc_simple_remove(struct platform_device *pdev);
void simple_util_remove(struct platform_device *pdev);
int asoc_graph_card_probe(struct snd_soc_card *card);
int asoc_graph_is_ports0(struct device_node *port);
int asoc_graph_parse_dai(struct device *dev, struct device_node *ep,
int graph_util_card_probe(struct snd_soc_card *card);
int graph_util_is_ports0(struct device_node *port);
int graph_util_parse_dai(struct device *dev, struct device_node *ep,
struct snd_soc_dai_link_component *dlc, int *is_single_link);
#ifdef DEBUG
static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
static inline void simple_util_debug_dai(struct simple_util_priv *priv,
char *name,
struct asoc_simple_dai *dai)
struct simple_util_dai *dai)
{
struct device *dev = simple_priv_to_dev(priv);
@ -228,7 +228,7 @@ static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
name, dai->clk_direction ? "OUT" : "IN");
}
static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
static inline void simple_util_debug_info(struct simple_util_priv *priv)
{
struct snd_soc_card *card = simple_priv_to_card(priv);
struct device *dev = simple_priv_to_dev(priv);
@ -241,7 +241,7 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
for (i = 0; i < card->num_links; i++) {
struct simple_dai_props *props = simple_priv_to_props(priv, i);
struct snd_soc_dai_link *link = simple_priv_to_link(priv, i);
struct asoc_simple_dai *dai;
struct simple_util_dai *dai;
struct snd_soc_codec_conf *cnf;
int j;
@ -249,10 +249,10 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
dev_dbg(dev, "cpu num = %d\n", link->num_cpus);
for_each_prop_dai_cpu(props, j, dai)
asoc_simple_debug_dai(priv, "cpu", dai);
simple_util_debug_dai(priv, "cpu", dai);
dev_dbg(dev, "codec num = %d\n", link->num_codecs);
for_each_prop_dai_codec(props, j, dai)
asoc_simple_debug_dai(priv, "codec", dai);
simple_util_debug_dai(priv, "codec", dai);
if (link->name)
dev_dbg(dev, "dai name = %s\n", link->name);
@ -270,7 +270,7 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
}
}
#else
#define asoc_simple_debug_info(priv)
#define simple_util_debug_info(priv)
#endif /* DEBUG */
#endif /* __SIMPLE_CARD_UTILS_H */

View File

@ -32,6 +32,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[];
@ -42,6 +43,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[];
/*
* generic table used for HDA codec-based platforms, possibly with

View File

@ -68,6 +68,10 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
* @i2s_link_mask: I2S/TDM links enabled on the board
* @num_dai_drivers: number of elements in @dai_drivers
* @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode
* @subsystem_vendor: optional PCI SSID vendor value
* @subsystem_device: optional PCI SSID device value
* @subsystem_id_set: true if a value has been written to
* subsystem_vendor and subsystem_device.
*/
struct snd_soc_acpi_mach_params {
u32 acpi_ipc_irq_index;
@ -80,6 +84,9 @@ struct snd_soc_acpi_mach_params {
u32 i2s_link_mask;
u32 num_dai_drivers;
struct snd_soc_dai_driver *dai_drivers;
unsigned short subsystem_vendor;
unsigned short subsystem_device;
bool subsystem_id_set;
};
/**

View File

@ -59,6 +59,43 @@ int snd_soc_card_add_dai_link(struct snd_soc_card *card,
void snd_soc_card_remove_dai_link(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link);
#ifdef CONFIG_PCI
static inline void snd_soc_card_set_pci_ssid(struct snd_soc_card *card,
unsigned short vendor,
unsigned short device)
{
card->pci_subsystem_vendor = vendor;
card->pci_subsystem_device = device;
card->pci_subsystem_set = true;
}
static inline int snd_soc_card_get_pci_ssid(struct snd_soc_card *card,
unsigned short *vendor,
unsigned short *device)
{
if (!card->pci_subsystem_set)
return -ENOENT;
*vendor = card->pci_subsystem_vendor;
*device = card->pci_subsystem_device;
return 0;
}
#else /* !CONFIG_PCI */
static inline void snd_soc_card_set_pci_ssid(struct snd_soc_card *card,
unsigned short vendor,
unsigned short device)
{
}
static inline int snd_soc_card_get_pci_ssid(struct snd_soc_card *card,
unsigned short *vendor,
unsigned short *device)
{
return -ENOENT;
}
#endif /* CONFIG_PCI */
/* device driver data */
static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
void *data)
@ -78,8 +115,8 @@ struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card,
struct snd_soc_pcm_runtime *rtd;
for_each_card_rtds(card, rtd) {
if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name))
return asoc_rtd_to_codec(rtd, 0);
if (!strcmp(snd_soc_rtd_to_codec(rtd, 0)->name, dai_name))
return snd_soc_rtd_to_codec(rtd, 0);
}
return NULL;

View File

@ -370,6 +370,7 @@ struct snd_soc_dai_ops {
/* bit field */
unsigned int no_capture_mute:1;
unsigned int mute_unmute_on_trigger:1;
};
struct snd_soc_cdai_ops {

View File

@ -718,7 +718,7 @@ struct snd_soc_dapm_context {
/* A list of widgets associated with an object, typically a snd_kcontrol */
struct snd_soc_dapm_widget_list {
int num_widgets;
struct snd_soc_dapm_widget *widgets[];
struct snd_soc_dapm_widget *widgets[] __counted_by(num_widgets);
};
#define for_each_dapm_widgets(list, i, widget) \

View File

@ -10,6 +10,7 @@
#ifndef __LINUX_SND_SOC_H
#define __LINUX_SND_SOC_H
#include <linux/args.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/types.h>
@ -775,36 +776,36 @@ struct snd_soc_dai_link {
};
static inline struct snd_soc_dai_link_component*
asoc_link_to_cpu(struct snd_soc_dai_link *link, int n) {
snd_soc_link_to_cpu(struct snd_soc_dai_link *link, int n) {
return &(link)->cpus[n];
}
static inline struct snd_soc_dai_link_component*
asoc_link_to_codec(struct snd_soc_dai_link *link, int n) {
snd_soc_link_to_codec(struct snd_soc_dai_link *link, int n) {
return &(link)->codecs[n];
}
static inline struct snd_soc_dai_link_component*
asoc_link_to_platform(struct snd_soc_dai_link *link, int n) {
snd_soc_link_to_platform(struct snd_soc_dai_link *link, int n) {
return &(link)->platforms[n];
}
#define for_each_link_codecs(link, i, codec) \
for ((i) = 0; \
((i) < link->num_codecs) && \
((codec) = asoc_link_to_codec(link, i)); \
((codec) = snd_soc_link_to_codec(link, i)); \
(i)++)
#define for_each_link_platforms(link, i, platform) \
for ((i) = 0; \
((i) < link->num_platforms) && \
((platform) = asoc_link_to_platform(link, i)); \
((platform) = snd_soc_link_to_platform(link, i)); \
(i)++)
#define for_each_link_cpus(link, i, cpu) \
for ((i) = 0; \
((i) < link->num_cpus) && \
((cpu) = asoc_link_to_cpu(link, i)); \
((cpu) = snd_soc_link_to_cpu(link, i)); \
(i)++)
/*
@ -870,12 +871,8 @@ asoc_link_to_platform(struct snd_soc_dai_link *link, int n) {
.platforms = platform, \
.num_platforms = ARRAY_SIZE(platform)
#define SND_SOC_DAILINK_REGx(_1, _2, _3, func, ...) func
#define SND_SOC_DAILINK_REG(...) \
SND_SOC_DAILINK_REGx(__VA_ARGS__, \
SND_SOC_DAILINK_REG3, \
SND_SOC_DAILINK_REG2, \
SND_SOC_DAILINK_REG1)(__VA_ARGS__)
CONCATENATE(SND_SOC_DAILINK_REG, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
#define SND_SOC_DAILINK_DEF(name, def...) \
static struct snd_soc_dai_link_component name[] = { def }
@ -895,7 +892,7 @@ asoc_link_to_platform(struct snd_soc_dai_link *link, int n) {
#define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", }
extern struct snd_soc_dai_link_component null_dailink_component[0];
extern struct snd_soc_dai_link_component asoc_dummy_dlc;
extern struct snd_soc_dai_link_component snd_soc_dummy_dlc;
struct snd_soc_codec_conf {
@ -932,6 +929,17 @@ struct snd_soc_card {
#ifdef CONFIG_DMI
char dmi_longname[80];
#endif /* CONFIG_DMI */
#ifdef CONFIG_PCI
/*
* PCI does not define 0 as invalid, so pci_subsystem_set indicates
* whether a value has been written to these fields.
*/
unsigned short pci_subsystem_vendor;
unsigned short pci_subsystem_device;
bool pci_subsystem_set;
#endif /* CONFIG_PCI */
char topology_shortname[32];
struct device *dev;
@ -1102,8 +1110,8 @@ struct snd_soc_pcm_runtime {
* dais = cpu_dai + codec_dai
* see
* soc_new_pcm_runtime()
* asoc_rtd_to_cpu()
* asoc_rtd_to_codec()
* snd_soc_rtd_to_cpu()
* snd_soc_rtd_to_codec()
*/
struct snd_soc_dai **dais;
@ -1131,10 +1139,11 @@ struct snd_soc_pcm_runtime {
int num_components;
struct snd_soc_component *components[]; /* CPU/Codec/Platform */
};
/* see soc_new_pcm_runtime() */
#define asoc_rtd_to_cpu(rtd, n) (rtd)->dais[n]
#define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus]
#define asoc_substream_to_rtd(substream) \
#define snd_soc_rtd_to_cpu(rtd, n) (rtd)->dais[n]
#define snd_soc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus]
#define snd_soc_substream_to_rtd(substream) \
(struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream)
#define for_each_rtd_components(rtd, i, component) \
@ -1143,11 +1152,11 @@ struct snd_soc_pcm_runtime {
(i)++)
#define for_each_rtd_cpu_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < rtd->dai_link->num_cpus) && ((dai) = asoc_rtd_to_cpu(rtd, i)); \
((i) < rtd->dai_link->num_cpus) && ((dai) = snd_soc_rtd_to_cpu(rtd, i)); \
(i)++)
#define for_each_rtd_codec_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < rtd->dai_link->num_codecs) && ((dai) = asoc_rtd_to_codec(rtd, i)); \
((i) < rtd->dai_link->num_codecs) && ((dai) = snd_soc_rtd_to_codec(rtd, i)); \
(i)++)
#define for_each_rtd_dais(rtd, i, dai) \
for ((i) = 0; \

View File

@ -52,8 +52,8 @@ enum sof_dsp_power_states {
/* Definitions for multiple IPCs */
enum sof_ipc_type {
SOF_IPC,
SOF_INTEL_IPC4,
SOF_IPC_TYPE_3,
SOF_IPC_TYPE_4,
SOF_IPC_TYPE_COUNT
};
@ -64,6 +64,14 @@ struct snd_sof_pdata {
const char *name;
const char *platform;
/*
* PCI SSID. As PCI does not define 0 as invalid, the subsystem_id_set
* flag indicates that a value has been written to these members.
*/
unsigned short subsystem_vendor;
unsigned short subsystem_device;
bool subsystem_id_set;
struct device *dev;
/*

View File

@ -106,12 +106,19 @@ enum sof_ipc4_global_msg {
SOF_IPC4_GLB_SAVE_PIPELINE,
SOF_IPC4_GLB_RESTORE_PIPELINE,
/* Loads library (using Code Load or HD/A Host Output DMA) */
/*
* library loading
*
* Loads library (using Code Load or HD/A Host Output DMA)
*/
SOF_IPC4_GLB_LOAD_LIBRARY,
/*
* Prepare the host DMA channel for library loading, must be followed by
* a SOF_IPC4_GLB_LOAD_LIBRARY message as the library loading step
*/
SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE,
/* 25: RESERVED - do not use */
SOF_IPC4_GLB_INTERNAL_MESSAGE = 26,
SOF_IPC4_GLB_INTERNAL_MESSAGE,
/* Notification (FW to SW driver) */
SOF_IPC4_GLB_NOTIFICATION,
@ -508,6 +515,23 @@ struct sof_ipc4_notify_resource_data {
uint32_t data[6];
} __packed __aligned(4);
#define SOF_IPC4_DEBUG_DESCRIPTOR_SIZE 12 /* 3 x u32 */
/*
* The debug memory window is divided into 16 slots, and the
* first slot is used as a recorder for the other 15 slots.
*/
#define SOF_IPC4_MAX_DEBUG_SLOTS 15
#define SOF_IPC4_DEBUG_SLOT_SIZE 0x1000
/* debug log slot types */
#define SOF_IPC4_DEBUG_SLOT_UNUSED 0x00000000
#define SOF_IPC4_DEBUG_SLOT_CRITICAL_LOG 0x54524300 /* byte 0: core ID */
#define SOF_IPC4_DEBUG_SLOT_DEBUG_LOG 0x474f4c00 /* byte 0: core ID */
#define SOF_IPC4_DEBUG_SLOT_GDB_STUB 0x42444700
#define SOF_IPC4_DEBUG_SLOT_TELEMETRY 0x4c455400
#define SOF_IPC4_DEBUG_SLOT_BROKEN 0x44414544
/** @}*/
#endif

View File

@ -77,6 +77,11 @@ struct tasdev_blk {
unsigned int nr_cmds;
unsigned int blk_size;
unsigned int nr_subblocks;
/* fixed m68k compiling issue, storing the dev_idx as a member of block
* can reduce unnecessary timeand system resource comsumption of
* dev_idx mapping every time the block data writing to the dsp.
*/
unsigned char dev_idx;
unsigned char *data;
};

View File

@ -8,34 +8,6 @@
* Copyright (c) by Paul Barton-Davis <pbd@op.net>
*/
#if (!defined(__GNUC__) && !defined(__GNUG__))
You will not be able to compile this file correctly without gcc, because
it is necessary to pack the "wavefront_alias" structure to a size
of 22 bytes, corresponding to 16-bit alignment (as would have been
the case on the original platform, MS-DOS). If this is not done,
then WavePatch-format files cannot be read/written correctly.
The method used to do this here ("__attribute__((packed)") is
completely compiler dependent.
All other wavefront_* types end up aligned to 32 bit values and
still have the same (correct) size.
#else
/* However, note that as of G++ 2.7.3.2, g++ was unable to
correctly parse *type* __attribute__ tags. It will do the
right thing if we use the "packed" attribute on each struct
member, which has the same semantics anyway.
*/
#endif /* __GNUC__ */
/***************************** WARNING ********************************
PLEASE DO NOT MODIFY THIS FILE IN ANY WAY THAT AFFECTS ITS ABILITY TO
BE USED WITH EITHER C *OR* C++.
**********************************************************************/
#ifndef NUM_MIDIKEYS
#define NUM_MIDIKEYS 128
#endif /* NUM_MIDIKEYS */
@ -44,29 +16,6 @@
#define NUM_MIDICHANNELS 16
#endif /* NUM_MIDICHANNELS */
/* These are very useful/important. the original wavefront interface
was developed on a 16 bit system, where sizeof(int) = 2
bytes. Defining things like this makes the code much more portable, and
easier to understand without having to toggle back and forth
between a 16-bit view of the world and a 32-bit one.
*/
#ifndef __KERNEL__
/* keep them for compatibility */
typedef short s16;
typedef unsigned short u16;
typedef int s32;
typedef unsigned int u32;
typedef char s8;
typedef unsigned char u8;
typedef s16 INT16;
typedef u16 UINT16;
typedef s32 INT32;
typedef u32 UINT32;
typedef s8 CHAR8;
typedef u8 UCHAR8;
#endif
/* Pseudo-commands not part of the WaveFront command set.
These are used for various driver controls and direct
hardware control.
@ -468,7 +417,7 @@ typedef struct wf_alias {
*/
u8 sixteen_bit_padding;
} __attribute__((packed)) wavefront_alias;
} __packed wavefront_alias;
typedef struct wf_drum {
u8 PatchNumber;

View File

@ -207,7 +207,7 @@ struct snd_seq_ev_raw32 {
struct snd_seq_ev_ext {
unsigned int len; /* length of data */
void *ptr; /* pointer to data (note: maybe 64-bit) */
} __attribute__((packed));
} __packed;
struct snd_seq_result {
int event; /* processed event type */
@ -251,7 +251,7 @@ struct snd_seq_ev_quote {
struct snd_seq_addr origin; /* original sender */
unsigned short value; /* optional data */
struct snd_seq_event *event; /* quoted event */
} __attribute__((packed));
} __packed;
union snd_seq_event_data { /* event data... */
struct snd_seq_ev_note note;

View File

@ -9,7 +9,6 @@
#define __AOA_GPIO_H
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <asm/prom.h>
typedef void (*notify_func_t)(void *data);

View File

@ -7,7 +7,6 @@
#ifndef __AOA_H
#define __AOA_H
#include <asm/prom.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/asound.h>

View File

@ -30,6 +30,7 @@
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/slab.h>
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
MODULE_LICENSE("GPL");

View File

@ -8,7 +8,6 @@
#define __SND_AOA_CODEC_ONYX_H
#include <linux/i2c.h>
#include <asm/pmac_low_i2c.h>
#include <asm/prom.h>
/* PCM3052 register definitions */

View File

@ -60,10 +60,10 @@
*/
#include <linux/i2c.h>
#include <asm/pmac_low_i2c.h>
#include <asm/prom.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/slab.h>
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");

View File

@ -7,9 +7,10 @@
* This fabric module looks for sound codecs based on the
* layout-id or device-id property in the device tree.
*/
#include <asm/prom.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "../aoa.h"
#include "../soundbus/soundbus.h"

View File

@ -6,6 +6,8 @@
*/
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include "soundbus.h"
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");

View File

@ -10,7 +10,6 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <asm/prom.h>
#include <asm/macio.h>
#include <asm/pmac_feature.h>
#include <asm/pmac_pfunc.h>

View File

@ -10,6 +10,7 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>

View File

@ -13,7 +13,6 @@
#include <sound/pcm.h>
#include <asm/prom.h>
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>

View File

@ -34,7 +34,7 @@ struct i2s_interface_regs {
__le32 peak_level_in1; /* 0x90 */
PAD(12);
/* total size: 0x100 bytes */
} __attribute__((__packed__));
} __packed;
/* interrupt register is just a bitfield with
* interrupt enable and pending bits */

View File

@ -7,7 +7,7 @@
#ifndef __SOUNDBUS_H
#define __SOUNDBUS_H
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <sound/pcm.h>
#include <linux/list.h>

View File

@ -38,7 +38,7 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
struct dma_slave_config config;
int ret;
dma_params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
dma_params = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream);
if (!dma_params)
return 0;
@ -47,7 +47,7 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
return ret;
snd_dmaengine_pcm_set_config_from_dai_data(substream,
snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream),
snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream),
&config);
ret = dmaengine_slave_config(chan, &config);
@ -86,7 +86,7 @@ int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
runtime->hw = pxa2xx_pcm_hardware;
dma_params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
dma_params = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream);
if (!dma_params)
return 0;
@ -111,7 +111,7 @@ int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
return ret;
return snd_dmaengine_pcm_open(
substream, dma_request_slave_channel(asoc_rtd_to_cpu(rtd, 0)->dev,
substream, dma_request_slave_channel(snd_soc_rtd_to_cpu(rtd, 0)->dev,
dma_params->chan_name));
}
EXPORT_SYMBOL(pxa2xx_pcm_open);

View File

@ -74,7 +74,7 @@ struct snd_ctl_elem_info32 {
unsigned char reserved[128];
} value;
unsigned char reserved[64];
} __attribute__((packed));
} __packed;
static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
struct snd_ctl_elem_info32 __user *data32)

View File

@ -3089,7 +3089,7 @@ struct snd_pcm_mmap_status32 {
snd_pcm_state_t suspended_state;
s32 audio_tstamp_sec;
s32 audio_tstamp_nsec;
} __attribute__((packed));
} __packed;
struct snd_pcm_mmap_control32 {
u32 appl_ptr;
@ -3106,7 +3106,7 @@ struct snd_pcm_sync_ptr32 {
struct snd_pcm_mmap_control32 control;
unsigned char reserved[64];
} c;
} __attribute__((packed));
} __packed;
/* recalcuate the boundary within 32bit */
static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)

View File

@ -15,7 +15,7 @@ struct snd_rawmidi_params32 {
unsigned int no_active_sensing; /* avoid bit-field */
unsigned int mode;
unsigned char reserved[12];
} __attribute__((packed));
} __packed;
static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
struct snd_rawmidi_params32 __user *src)
@ -51,7 +51,7 @@ struct compat_snd_rawmidi_status64 {
u32 avail;
u32 xruns;
unsigned char reserved[16];
} __attribute__((packed));
} __packed;
static int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile,
struct compat_snd_rawmidi_status64 __user *src)

View File

@ -119,11 +119,13 @@ struct loopback_setup {
unsigned int rate_shift;
snd_pcm_format_t format;
unsigned int rate;
snd_pcm_access_t access;
unsigned int channels;
struct snd_ctl_elem_id active_id;
struct snd_ctl_elem_id format_id;
struct snd_ctl_elem_id rate_id;
struct snd_ctl_elem_id channels_id;
struct snd_ctl_elem_id access_id;
};
struct loopback {
@ -158,6 +160,9 @@ struct loopback_pcm {
unsigned long last_jiffies;
/* If jiffies timer is used */
struct timer_list timer;
/* size of per channel buffer in case of non-interleaved access */
unsigned int channel_buf_n;
};
static struct platform_device *devices[SNDRV_CARDS];
@ -335,7 +340,8 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
substream->runtime;
check = runtime->format != cruntime->format ||
runtime->rate != cruntime->rate ||
runtime->channels != cruntime->channels;
runtime->channels != cruntime->channels ||
runtime->access != cruntime->access;
if (!check)
return 0;
if (stream == SNDRV_PCM_STREAM_CAPTURE) {
@ -363,6 +369,11 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
&setup->channels_id);
setup->channels = runtime->channels;
}
if (setup->access != runtime->access) {
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
&setup->access_id);
setup->access = runtime->access;
}
}
return 0;
}
@ -472,6 +483,7 @@ static int loopback_prepare(struct snd_pcm_substream *substream)
dpcm->buf_pos = 0;
dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
dpcm->channel_buf_n = dpcm->pcm_buffer_size / runtime->channels;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
/* clear capture buffer */
dpcm->silent_size = dpcm->pcm_buffer_size;
@ -522,6 +534,22 @@ static void clear_capture_buf(struct loopback_pcm *dpcm, unsigned int bytes)
}
}
static void copy_play_buf_part_n(struct loopback_pcm *play, struct loopback_pcm *capt,
unsigned int size, unsigned int src_off, unsigned int dst_off)
{
unsigned int channels = capt->substream->runtime->channels;
unsigned int size_p_ch = size / channels;
unsigned int src_off_ch = src_off / channels;
unsigned int dst_off_ch = dst_off / channels;
int i;
for (i = 0; i < channels; i++) {
memcpy(capt->substream->runtime->dma_area + capt->channel_buf_n * i + dst_off_ch,
play->substream->runtime->dma_area + play->channel_buf_n * i + src_off_ch,
size_p_ch);
}
}
static void copy_play_buf(struct loopback_pcm *play,
struct loopback_pcm *capt,
unsigned int bytes)
@ -556,7 +584,11 @@ static void copy_play_buf(struct loopback_pcm *play,
size = play->pcm_buffer_size - src_off;
if (dst_off + size > capt->pcm_buffer_size)
size = capt->pcm_buffer_size - dst_off;
memcpy(dst + dst_off, src + src_off, size);
if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ||
runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED)
copy_play_buf_part_n(play, capt, size, src_off, dst_off);
else
memcpy(dst + dst_off, src + src_off, size);
capt->silent_size = 0;
bytes -= size;
if (!bytes)
@ -878,7 +910,7 @@ static const struct snd_pcm_hardware loopback_pcm_hardware =
{
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME),
SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_NONINTERLEAVED),
.formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
@ -1495,6 +1527,30 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
return 0;
}
static int loopback_access_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
const char * const texts[] = {"Interleaved", "Non-interleaved"};
return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
}
static int loopback_access_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
snd_pcm_access_t access;
mutex_lock(&loopback->cable_lock);
access = loopback->setup[kcontrol->id.subdevice][kcontrol->id.device].access;
ucontrol->value.enumerated.item[0] = access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ||
access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED;
mutex_unlock(&loopback->cable_lock);
return 0;
}
static const struct snd_kcontrol_new loopback_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@ -1541,7 +1597,15 @@ static const struct snd_kcontrol_new loopback_controls[] = {
.name = "PCM Slave Channels",
.info = loopback_channels_info,
.get = loopback_channels_get
}
},
#define ACCESS_IDX 6
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "PCM Slave Access Mode",
.info = loopback_access_info,
.get = loopback_access_get,
},
};
static int loopback_mixer_new(struct loopback *loopback, int notify)
@ -1562,6 +1626,7 @@ static int loopback_mixer_new(struct loopback *loopback, int notify)
setup->notify = notify;
setup->rate_shift = NO_PITCH;
setup->format = SNDRV_PCM_FORMAT_S16_LE;
setup->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
setup->rate = 48000;
setup->channels = 2;
for (idx = 0; idx < ARRAY_SIZE(loopback_controls);
@ -1593,6 +1658,9 @@ static int loopback_mixer_new(struct loopback *loopback, int notify)
case CHANNELS_IDX:
setup->channels_id = kctl->id;
break;
case ACCESS_IDX:
setup->access_id = kctl->id;
break;
default:
break;
}

View File

@ -10,12 +10,47 @@
*/
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <sound/pcm.h>
#include <sound/hda_register.h>
#include <sound/hdaudio_ext.h>
#include <sound/compress_driver.h>
/**
* snd_hdac_ext_host_stream_setup - Setup a HOST stream.
* @hext_stream: HDAudio stream to set up.
* @code_loading: Whether the stream is for PCM or code-loading.
*
* Return: Zero on success or negative error code.
*/
int snd_hdac_ext_host_stream_setup(struct hdac_ext_stream *hext_stream, bool code_loading)
{
return hext_stream->host_setup(hdac_stream(hext_stream), code_loading);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_host_stream_setup);
/**
* snd_hdac_apl_host_stream_setup - Setup a HOST stream following procedure
* recommended for ApolloLake devices.
* @hstream: HDAudio stream to set up.
* @code_loading: Whether the stream is for PCM or code-loading.
*
* Return: Zero on success or negative error code.
*/
static int snd_hdac_apl_host_stream_setup(struct hdac_stream *hstream, bool code_loading)
{
struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
int ret;
snd_hdac_ext_stream_decouple(hstream->bus, hext_stream, false);
ret = snd_hdac_stream_setup(hstream, code_loading);
snd_hdac_ext_stream_decouple(hstream->bus, hext_stream, true);
return ret;
}
/**
* snd_hdac_ext_stream_init - initialize each stream (aka device)
* @bus: HD-audio core bus
@ -55,9 +90,16 @@ static void snd_hdac_ext_stream_init(struct hdac_bus *bus,
int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
int num_stream, int dir)
{
struct pci_dev *pci = to_pci_dev(bus->dev);
int (*setup_op)(struct hdac_stream *, bool);
int stream_tag = 0;
int i, tag, idx = start_idx;
if (pci->device == PCI_DEVICE_ID_INTEL_HDA_APL)
setup_op = snd_hdac_apl_host_stream_setup;
else
setup_op = snd_hdac_stream_setup;
for (i = 0; i < num_stream; i++) {
struct hdac_ext_stream *hext_stream =
kzalloc(sizeof(*hext_stream), GFP_KERNEL);
@ -66,6 +108,7 @@ int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
tag = ++stream_tag;
snd_hdac_ext_stream_init(bus, hext_stream, idx, dir, tag);
idx++;
hext_stream->host_setup = setup_op;
}
return 0;

View File

@ -10,6 +10,12 @@
#include <sound/hdaudio.h>
#include <sound/hda_i915.h>
#include <sound/hda_register.h>
#include <video/nomodeset.h>
static int gpu_bind = -1;
module_param(gpu_bind, int, 0644);
MODULE_PARM_DESC(gpu_bind, "Whether to bind sound component to GPU "
"(1=always, 0=never, -1=on nomodeset(default))");
/**
* snd_hdac_i915_set_bclk - Reprogram BCLK for HSW/BDW
@ -109,7 +115,8 @@ static int i915_component_master_match(struct device *dev, int subcomponent,
hdac_pci = to_pci_dev(bus->dev);
i915_pci = to_pci_dev(dev);
if (!strcmp(dev->driver->name, "i915") &&
if ((!strcmp(dev->driver->name, "i915") ||
!strcmp(dev->driver->name, "xe")) &&
subcomponent == I915_COMPONENT_AUDIO &&
connectivity_check(i915_pci, hdac_pci))
return 1;
@ -122,6 +129,9 @@ static int i915_gfx_present(struct pci_dev *hdac_pci)
{
struct pci_dev *display_dev = NULL;
if (!gpu_bind || (gpu_bind < 0 && video_firmware_drivers_only()))
return false;
for_each_pci_dev(display_dev) {
if (display_dev->vendor == PCI_VENDOR_ID_INTEL &&
(display_dev->class >> 16) == PCI_BASE_CLASS_DISPLAY &&
@ -163,17 +173,9 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
if (!acomp)
return -ENODEV;
if (!acomp->ops) {
if (!IS_ENABLED(CONFIG_MODULES) ||
!request_module("i915")) {
/* 60s timeout */
wait_for_completion_killable_timeout(&acomp->master_bind_complete,
msecs_to_jiffies(60 * 1000));
}
}
if (!acomp->ops) {
dev_info(bus->dev, "couldn't bind with audio component\n");
snd_hdac_acomp_exit(bus);
return -ENODEV;
return dev_err_probe(bus->dev, -EPROBE_DEFER,
"couldn't bind with audio component\n");
}
return 0;
}

View File

@ -252,12 +252,15 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_reset);
/**
* snd_hdac_stream_setup - set up the SD for streaming
* @azx_dev: HD-audio core stream to set up
* @code_loading: Whether the stream is for PCM or code-loading.
*/
int snd_hdac_stream_setup(struct hdac_stream *azx_dev)
int snd_hdac_stream_setup(struct hdac_stream *azx_dev, bool code_loading)
{
struct hdac_bus *bus = azx_dev->bus;
struct snd_pcm_runtime *runtime;
unsigned int val;
u16 reg;
int ret;
if (azx_dev->substream)
runtime = azx_dev->substream->runtime;
@ -300,7 +303,15 @@ int snd_hdac_stream_setup(struct hdac_stream *azx_dev)
/* set the interrupt enable bits in the descriptor control register */
snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK);
azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1;
if (!code_loading) {
/* Once SDxFMT is set, the controller programs SDxFIFOS to non-zero value. */
ret = snd_hdac_stream_readw_poll(azx_dev, SD_FIFOSIZE, reg,
reg & AZX_SD_FIFOSIZE_MASK, 3, 300);
if (ret)
dev_dbg(bus->dev, "polling SD_FIFOSIZE 0x%04x failed: %d\n",
AZX_REG_SD_FIFOSIZE, ret);
azx_dev->fifo_size = reg;
}
/* when LPIB delay correction gives a small negative value,
* we ignore it; currently set the threshold statically to
@ -354,8 +365,10 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
struct hdac_stream *res = NULL;
/* make a non-zero unique key for the substream */
int key = (substream->pcm->device << 16) | (substream->number << 2) |
(substream->stream + 1);
int key = (substream->number << 2) | (substream->stream + 1);
if (substream->pcm)
key |= (substream->pcm->device << 16);
spin_lock_irq(&bus->reg_lock);
list_for_each_entry(azx_dev, &bus->stream_list, list) {
@ -943,7 +956,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
if (err < 0)
goto error;
snd_hdac_stream_setup(azx_dev);
snd_hdac_stream_setup(azx_dev, true);
snd_hdac_dsp_unlock(azx_dev);
return azx_dev->stream_tag;

View File

@ -336,6 +336,12 @@ static const struct config_entry config_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
}
},
{
.ident = "Google firmware",
.matches = {
DMI_MATCH(DMI_BIOS_VERSION, "Google"),
}
},
{}
}
},

View File

@ -1383,7 +1383,7 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,
u32 dma_start_1;
u32 dma_start_2;
u32 dma_lengths;
} __attribute__((packed)) setup_io;
} __packed setup_io;
area_length = buffer_bytes/2;

View File

@ -91,6 +91,22 @@ config SND_HDA_PATCH_LOADER
start up. The "patch" file can be specified via patch module
option, such as patch=hda-init.
config SND_HDA_CIRRUS_SCODEC
tristate
config SND_HDA_CIRRUS_SCODEC_KUNIT_TEST
tristate "KUnit test for Cirrus side-codec library" if !KUNIT_ALL_TESTS
select SND_HDA_CIRRUS_SCODEC
select GPIOLIB
depends on KUNIT
default KUNIT_ALL_TESTS
help
This builds KUnit tests for the cirrus side-codec library.
For more information on KUnit and unit tests in general,
please refer to the KUnit documentation in
Documentation/dev-tools/kunit/.
If in doubt, say "N".
config SND_HDA_SCODEC_CS35L41
tristate
select SND_HDA_GENERIC
@ -144,6 +160,7 @@ config SND_HDA_SCODEC_CS35L56_I2C
select SND_HDA_GENERIC
select SND_SOC_CS35L56_SHARED
select SND_HDA_SCODEC_CS35L56
select SND_HDA_CIRRUS_SCODEC
select SND_HDA_CS_DSP_CONTROLS
help
Say Y or M here to include CS35L56 amplifier support with
@ -158,6 +175,7 @@ config SND_HDA_SCODEC_CS35L56_SPI
select SND_HDA_GENERIC
select SND_SOC_CS35L56_SHARED
select SND_HDA_SCODEC_CS35L56
select SND_HDA_CIRRUS_SCODEC
select SND_HDA_CS_DSP_CONTROLS
help
Say Y or M here to include CS35L56 amplifier support with

View File

@ -28,6 +28,8 @@ snd-hda-codec-via-objs := patch_via.o
snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
# side codecs
snd-hda-cirrus-scodec-objs := cirrus_scodec.o
snd-hda-cirrus-scodec-test-objs := cirrus_scodec_test.o
snd-hda-scodec-cs35l41-objs := cs35l41_hda.o cs35l41_hda_property.o
snd-hda-scodec-cs35l41-i2c-objs := cs35l41_hda_i2c.o
snd-hda-scodec-cs35l41-spi-objs := cs35l41_hda_spi.o
@ -56,6 +58,8 @@ obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o
obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
# side codecs
obj-$(CONFIG_SND_HDA_CIRRUS_SCODEC) += snd-hda-cirrus-scodec.o
obj-$(CONFIG_SND_HDA_CIRRUS_SCODEC_KUNIT_TEST) += snd-hda-cirrus-scodec-test.o
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) += snd-hda-scodec-cs35l41.o
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.o
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o

View File

@ -0,0 +1,73 @@
// SPDX-License-Identifier: GPL-2.0-only
//
// Common code for Cirrus side-codecs.
//
// Copyright (C) 2021, 2023 Cirrus Logic, Inc. and
// Cirrus Logic International Semiconductor Ltd.
#include <linux/dev_printk.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include "cirrus_scodec.h"
int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
int num_amps, int fixed_gpio_id)
{
struct gpio_desc *speaker_id_desc;
int speaker_id = -ENOENT;
if (fixed_gpio_id >= 0) {
dev_dbg(dev, "Found Fixed Speaker ID GPIO (index = %d)\n", fixed_gpio_id);
speaker_id_desc = gpiod_get_index(dev, NULL, fixed_gpio_id, GPIOD_IN);
if (IS_ERR(speaker_id_desc)) {
speaker_id = PTR_ERR(speaker_id_desc);
return speaker_id;
}
speaker_id = gpiod_get_value_cansleep(speaker_id_desc);
gpiod_put(speaker_id_desc);
} else {
int base_index;
int gpios_per_amp;
int count;
int tmp;
int i;
count = gpiod_count(dev, "spk-id");
if (count > 0) {
speaker_id = 0;
gpios_per_amp = count / num_amps;
base_index = gpios_per_amp * amp_index;
if (count % num_amps)
return -EINVAL;
dev_dbg(dev, "Found %d Speaker ID GPIOs per Amp\n", gpios_per_amp);
for (i = 0; i < gpios_per_amp; i++) {
speaker_id_desc = gpiod_get_index(dev, "spk-id", i + base_index,
GPIOD_IN);
if (IS_ERR(speaker_id_desc)) {
speaker_id = PTR_ERR(speaker_id_desc);
break;
}
tmp = gpiod_get_value_cansleep(speaker_id_desc);
gpiod_put(speaker_id_desc);
if (tmp < 0) {
speaker_id = tmp;
break;
}
speaker_id |= tmp << i;
}
}
}
dev_dbg(dev, "Speaker ID = %d\n", speaker_id);
return speaker_id;
}
EXPORT_SYMBOL_NS_GPL(cirrus_scodec_get_speaker_id, SND_HDA_CIRRUS_SCODEC);
MODULE_DESCRIPTION("HDA Cirrus side-codec library");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0
*
* Copyright (C) 2023 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*/
#ifndef CIRRUS_SCODEC_H
#define CIRRUS_SCODEC_H
int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
int num_amps, int fixed_gpio_id);
#endif /* CIRRUS_SCODEC_H */

View File

@ -0,0 +1,370 @@
// SPDX-License-Identifier: GPL-2.0-only
//
// KUnit test for the Cirrus side-codec library.
//
// Copyright (C) 2023 Cirrus Logic, Inc. and
// Cirrus Logic International Semiconductor Ltd.
#include <kunit/test.h>
#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "cirrus_scodec.h"
struct cirrus_scodec_test_gpio {
unsigned int pin_state;
struct gpio_chip chip;
};
struct cirrus_scodec_test_priv {
struct platform_device amp_pdev;
struct platform_device *gpio_pdev;
struct cirrus_scodec_test_gpio *gpio_priv;
};
static int cirrus_scodec_test_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
return GPIO_LINE_DIRECTION_IN;
}
static int cirrus_scodec_test_gpio_direction_in(struct gpio_chip *chip,
unsigned int offset)
{
return 0;
}
static int cirrus_scodec_test_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct cirrus_scodec_test_gpio *gpio_priv = gpiochip_get_data(chip);
return !!(gpio_priv->pin_state & BIT(offset));
}
static int cirrus_scodec_test_gpio_direction_out(struct gpio_chip *chip,
unsigned int offset, int value)
{
return -EOPNOTSUPP;
}
static void cirrus_scodec_test_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
}
static int cirrus_scodec_test_gpio_set_config(struct gpio_chip *gc,
unsigned int offset,
unsigned long config)
{
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_OUTPUT:
case PIN_CONFIG_OUTPUT_ENABLE:
return -EOPNOTSUPP;
default:
return 0;
}
}
static const struct gpio_chip cirrus_scodec_test_gpio_chip = {
.label = "cirrus_scodec_test_gpio",
.owner = THIS_MODULE,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.get_direction = cirrus_scodec_test_gpio_get_direction,
.direction_input = cirrus_scodec_test_gpio_direction_in,
.get = cirrus_scodec_test_gpio_get,
.direction_output = cirrus_scodec_test_gpio_direction_out,
.set = cirrus_scodec_test_gpio_set,
.set_config = cirrus_scodec_test_gpio_set_config,
.base = -1,
.ngpio = 32,
};
static int cirrus_scodec_test_gpio_probe(struct platform_device *pdev)
{
struct cirrus_scodec_test_gpio *gpio_priv;
int ret;
gpio_priv = devm_kzalloc(&pdev->dev, sizeof(*gpio_priv), GFP_KERNEL);
if (!gpio_priv)
return -ENOMEM;
/* GPIO core modifies our struct gpio_chip so use a copy */
gpio_priv->chip = cirrus_scodec_test_gpio_chip;
ret = devm_gpiochip_add_data(&pdev->dev, &gpio_priv->chip, gpio_priv);
if (ret)
return dev_err_probe(&pdev->dev, ret, "Failed to add gpiochip\n");
dev_set_drvdata(&pdev->dev, gpio_priv);
return 0;
}
static struct platform_driver cirrus_scodec_test_gpio_driver = {
.driver.name = "cirrus_scodec_test_gpio_drv",
.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 int cirrus_scodec_test_create_gpio(struct kunit *test)
{
struct cirrus_scodec_test_priv *priv = test->priv;
int ret;
priv->gpio_pdev = platform_device_alloc(cirrus_scodec_test_gpio_driver.driver.name, -1);
if (!priv->gpio_pdev)
return -ENOMEM;
ret = device_add_software_node(&priv->gpio_pdev->dev, &cirrus_scodec_test_gpio_swnode);
if (ret) {
platform_device_put(priv->gpio_pdev);
KUNIT_FAIL(test, "Failed to add swnode to gpio: %d\n", ret);
return ret;
}
ret = platform_device_add(priv->gpio_pdev);
if (ret) {
platform_device_put(priv->gpio_pdev);
KUNIT_FAIL(test, "Failed to add gpio platform device: %d\n", ret);
return ret;
}
priv->gpio_priv = dev_get_drvdata(&priv->gpio_pdev->dev);
if (!priv->gpio_priv) {
platform_device_put(priv->gpio_pdev);
KUNIT_FAIL(test, "Failed to get gpio private data\n");
return -EINVAL;
}
return 0;
}
static void cirrus_scodec_test_set_gpio_ref_arg(struct software_node_ref_args *arg,
int gpio_num)
{
struct software_node_ref_args template =
SOFTWARE_NODE_REFERENCE(&cirrus_scodec_test_gpio_swnode, gpio_num, 0);
*arg = template;
}
static int cirrus_scodec_test_set_spkid_swnode(struct kunit *test,
struct device *dev,
struct software_node_ref_args *args,
int num_args)
{
const struct property_entry props_template[] = {
PROPERTY_ENTRY_REF_ARRAY_LEN("spk-id-gpios", args, num_args),
{ }
};
struct property_entry *props;
struct software_node *node;
node = kunit_kzalloc(test, sizeof(*node), GFP_KERNEL);
if (!node)
return -ENOMEM;
props = kunit_kzalloc(test, sizeof(props_template), GFP_KERNEL);
if (!props)
return -ENOMEM;
memcpy(props, props_template, sizeof(props_template));
node->properties = props;
return device_add_software_node(dev, node);
}
struct cirrus_scodec_test_spkid_param {
int num_amps;
int gpios_per_amp;
int num_amps_sharing;
};
static void cirrus_scodec_test_spkid_parse(struct kunit *test)
{
struct cirrus_scodec_test_priv *priv = test->priv;
const struct cirrus_scodec_test_spkid_param *param = test->param_value;
int num_spk_id_refs = param->num_amps * param->gpios_per_amp;
struct software_node_ref_args *refs;
struct device *dev = &priv->amp_pdev.dev;
unsigned int v;
int i, ret;
refs = kunit_kcalloc(test, num_spk_id_refs, sizeof(*refs), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, refs);
for (i = 0, v = 0; i < num_spk_id_refs; ) {
cirrus_scodec_test_set_gpio_ref_arg(&refs[i++], v++);
/*
* If amps are sharing GPIOs repeat the last set of
* GPIOs until we've done that number of amps.
* We have done all GPIOs for an amp when i is a multiple
* of gpios_per_amp.
* We have done all amps sharing the same GPIOs when i is
* a multiple of (gpios_per_amp * num_amps_sharing).
*/
if (!(i % param->gpios_per_amp) &&
(i % (param->gpios_per_amp * param->num_amps_sharing)))
v -= param->gpios_per_amp;
}
ret = cirrus_scodec_test_set_spkid_swnode(test, dev, refs, num_spk_id_refs);
KUNIT_EXPECT_EQ_MSG(test, ret, 0, "Failed to add swnode\n");
for (i = 0; i < param->num_amps; ++i) {
for (v = 0; v < (1 << param->gpios_per_amp); ++v) {
/* Set only the GPIO bits used by this amp */
priv->gpio_priv->pin_state =
v << (param->gpios_per_amp * (i / param->num_amps_sharing));
ret = cirrus_scodec_get_speaker_id(dev, i, param->num_amps, -1);
KUNIT_EXPECT_EQ_MSG(test, ret, v,
"get_speaker_id failed amp:%d pin_state:%#x\n",
i, priv->gpio_priv->pin_state);
}
}
}
static void cirrus_scodec_test_no_spkid(struct kunit *test)
{
struct cirrus_scodec_test_priv *priv = test->priv;
struct device *dev = &priv->amp_pdev.dev;
int ret;
ret = cirrus_scodec_get_speaker_id(dev, 0, 4, -1);
KUNIT_EXPECT_EQ(test, ret, -ENOENT);
}
static void cirrus_scodec_test_dev_release(struct device *dev)
{
}
static int cirrus_scodec_test_case_init(struct kunit *test)
{
struct cirrus_scodec_test_priv *priv;
int ret;
priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
test->priv = priv;
/* Create dummy GPIO */
ret = cirrus_scodec_test_create_gpio(test);
if (ret < 0)
return ret;
/* Create dummy amp driver dev */
priv->amp_pdev.name = "cirrus_scodec_test_amp_drv";
priv->amp_pdev.id = -1;
priv->amp_pdev.dev.release = cirrus_scodec_test_dev_release;
ret = platform_device_register(&priv->amp_pdev);
KUNIT_ASSERT_GE_MSG(test, ret, 0, "Failed to register amp platform device\n");
return 0;
}
static void cirrus_scodec_test_case_exit(struct kunit *test)
{
struct cirrus_scodec_test_priv *priv = test->priv;
if (priv->amp_pdev.name)
platform_device_unregister(&priv->amp_pdev);
if (priv->gpio_pdev) {
device_remove_software_node(&priv->gpio_pdev->dev);
platform_device_unregister(priv->gpio_pdev);
}
}
static int cirrus_scodec_test_suite_init(struct kunit_suite *suite)
{
int ret;
/* Register mock GPIO driver */
ret = platform_driver_register(&cirrus_scodec_test_gpio_driver);
if (ret < 0) {
kunit_err(suite, "Failed to register gpio platform driver, %d\n", ret);
return ret;
}
return 0;
}
static void cirrus_scodec_test_suite_exit(struct kunit_suite *suite)
{
platform_driver_unregister(&cirrus_scodec_test_gpio_driver);
}
static const struct cirrus_scodec_test_spkid_param cirrus_scodec_test_spkid_param_cases[] = {
{ .num_amps = 2, .gpios_per_amp = 1, .num_amps_sharing = 1 },
{ .num_amps = 2, .gpios_per_amp = 2, .num_amps_sharing = 1 },
{ .num_amps = 2, .gpios_per_amp = 3, .num_amps_sharing = 1 },
{ .num_amps = 2, .gpios_per_amp = 4, .num_amps_sharing = 1 },
{ .num_amps = 3, .gpios_per_amp = 1, .num_amps_sharing = 1 },
{ .num_amps = 3, .gpios_per_amp = 2, .num_amps_sharing = 1 },
{ .num_amps = 3, .gpios_per_amp = 3, .num_amps_sharing = 1 },
{ .num_amps = 3, .gpios_per_amp = 4, .num_amps_sharing = 1 },
{ .num_amps = 4, .gpios_per_amp = 1, .num_amps_sharing = 1 },
{ .num_amps = 4, .gpios_per_amp = 2, .num_amps_sharing = 1 },
{ .num_amps = 4, .gpios_per_amp = 3, .num_amps_sharing = 1 },
{ .num_amps = 4, .gpios_per_amp = 4, .num_amps_sharing = 1 },
/* Same GPIO shared by all amps */
{ .num_amps = 2, .gpios_per_amp = 1, .num_amps_sharing = 2 },
{ .num_amps = 2, .gpios_per_amp = 2, .num_amps_sharing = 2 },
{ .num_amps = 2, .gpios_per_amp = 3, .num_amps_sharing = 2 },
{ .num_amps = 2, .gpios_per_amp = 4, .num_amps_sharing = 2 },
{ .num_amps = 3, .gpios_per_amp = 1, .num_amps_sharing = 3 },
{ .num_amps = 3, .gpios_per_amp = 2, .num_amps_sharing = 3 },
{ .num_amps = 3, .gpios_per_amp = 3, .num_amps_sharing = 3 },
{ .num_amps = 3, .gpios_per_amp = 4, .num_amps_sharing = 3 },
{ .num_amps = 4, .gpios_per_amp = 1, .num_amps_sharing = 4 },
{ .num_amps = 4, .gpios_per_amp = 2, .num_amps_sharing = 4 },
{ .num_amps = 4, .gpios_per_amp = 3, .num_amps_sharing = 4 },
{ .num_amps = 4, .gpios_per_amp = 4, .num_amps_sharing = 4 },
/* Two sets of shared GPIOs */
{ .num_amps = 4, .gpios_per_amp = 1, .num_amps_sharing = 2 },
{ .num_amps = 4, .gpios_per_amp = 2, .num_amps_sharing = 2 },
{ .num_amps = 4, .gpios_per_amp = 3, .num_amps_sharing = 2 },
{ .num_amps = 4, .gpios_per_amp = 4, .num_amps_sharing = 2 },
};
static void cirrus_scodec_test_spkid_param_desc(const struct cirrus_scodec_test_spkid_param *param,
char *desc)
{
snprintf(desc, KUNIT_PARAM_DESC_SIZE, "amps:%d gpios_per_amp:%d num_amps_sharing:%d",
param->num_amps, param->gpios_per_amp, param->num_amps_sharing);
}
KUNIT_ARRAY_PARAM(cirrus_scodec_test_spkid, cirrus_scodec_test_spkid_param_cases,
cirrus_scodec_test_spkid_param_desc);
static struct kunit_case cirrus_scodec_test_cases[] = {
KUNIT_CASE_PARAM(cirrus_scodec_test_spkid_parse, cirrus_scodec_test_spkid_gen_params),
KUNIT_CASE(cirrus_scodec_test_no_spkid),
{ } /* terminator */
};
static struct kunit_suite cirrus_scodec_test_suite = {
.name = "snd-hda-scodec-cs35l56-test",
.suite_init = cirrus_scodec_test_suite_init,
.suite_exit = cirrus_scodec_test_suite_exit,
.init = cirrus_scodec_test_case_init,
.exit = cirrus_scodec_test_case_exit,
.test_cases = cirrus_scodec_test_cases,
};
kunit_test_suite(cirrus_scodec_test_suite);
MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL");

View File

@ -33,6 +33,9 @@
#define CAL_AMBIENT_DSP_CTL_NAME "CAL_AMBIENT"
#define CAL_DSP_CTL_TYPE 5
#define CAL_DSP_CTL_ALG 205
#define CS35L41_UUID "50d90cdc-3de4-4f18-b528-c7fe3b71f40d"
#define CS35L41_DSM_GET_MUTE 5
#define CS35L41_NOTIFY_EVENT 0x91
static bool firmware_autostart = 1;
module_param(firmware_autostart, bool, 0444);
@ -563,6 +566,31 @@ static void cs35l41_hda_play_start(struct device *dev)
}
static void cs35l41_mute(struct device *dev, bool mute)
{
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
struct regmap *reg = cs35l41->regmap;
dev_dbg(dev, "Mute(%d:%d) Playback Started: %d\n", mute, cs35l41->mute_override,
cs35l41->playback_started);
if (cs35l41->playback_started) {
if (mute || cs35l41->mute_override) {
dev_dbg(dev, "Muting\n");
regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));
} else {
dev_dbg(dev, "Unmuting\n");
if (cs35l41->firmware_running) {
regmap_multi_reg_write(reg, cs35l41_hda_unmute_dsp,
ARRAY_SIZE(cs35l41_hda_unmute_dsp));
} else {
regmap_multi_reg_write(reg, cs35l41_hda_unmute,
ARRAY_SIZE(cs35l41_hda_unmute));
}
}
}
}
static void cs35l41_hda_play_done(struct device *dev)
{
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
@ -570,15 +598,9 @@ static void cs35l41_hda_play_done(struct device *dev)
dev_dbg(dev, "Play (Complete)\n");
cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 1, NULL,
cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 1,
cs35l41->firmware_running);
if (cs35l41->firmware_running) {
regmap_multi_reg_write(reg, cs35l41_hda_unmute_dsp,
ARRAY_SIZE(cs35l41_hda_unmute_dsp));
} else {
regmap_multi_reg_write(reg, cs35l41_hda_unmute,
ARRAY_SIZE(cs35l41_hda_unmute));
}
cs35l41_mute(dev, false);
}
static void cs35l41_hda_pause_start(struct device *dev)
@ -588,8 +610,8 @@ static void cs35l41_hda_pause_start(struct device *dev)
dev_dbg(dev, "Pause (Start)\n");
regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));
cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0, NULL,
cs35l41_mute(dev, true);
cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0,
cs35l41->firmware_running);
}
@ -708,43 +730,46 @@ static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsi
rx_slot);
}
static int cs35l41_verify_id(struct cs35l41_hda *cs35l41, unsigned int *regid, unsigned int *reg_revid)
{
unsigned int mtl_revid, chipid;
int ret;
ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, regid);
if (ret) {
dev_err_probe(cs35l41->dev, ret, "Get Device ID failed\n");
return ret;
}
ret = regmap_read(cs35l41->regmap, CS35L41_REVID, reg_revid);
if (ret) {
dev_err_probe(cs35l41->dev, ret, "Get Revision ID failed\n");
return ret;
}
mtl_revid = *reg_revid & CS35L41_MTLREVID_MASK;
chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
if (*regid != chipid) {
dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", *regid, chipid);
return -ENODEV;
}
return 0;
}
static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)
{
int ret = 0;
mutex_lock(&cs35l41->fw_mutex);
if (cs35l41->firmware_running) {
regcache_cache_only(cs35l41->regmap, false);
ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap);
if (ret) {
dev_warn(cs35l41->dev, "Unable to exit Hibernate.");
goto err;
}
/* Test key needs to be unlocked to allow the OTP settings to re-apply */
cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
ret = regcache_sync(cs35l41->regmap);
cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);
if (ret) {
dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret);
goto err;
}
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
cs35l41_shutdown_dsp(cs35l41);
cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
cs35l41->cs_dsp.running = false;
cs35l41->cs_dsp.booted = false;
cs35l41->firmware_running = false;
}
err:
regcache_cache_only(cs35l41->regmap, true);
regcache_mark_dirty(cs35l41->regmap);
mutex_unlock(&cs35l41->fw_mutex);
return ret;
return 0;
}
static int cs35l41_system_suspend_prep(struct device *dev)
@ -791,17 +816,44 @@ static int cs35l41_system_suspend(struct device *dev)
/* Shutdown DSP before system suspend */
ret = cs35l41_ready_for_reset(cs35l41);
if (ret)
dev_err(dev, "System Suspend Failed, not ready for Reset: %d\n", ret);
/*
* Reset GPIO may be shared, so cannot reset here.
* However beyond this point, amps may be powered down.
*/
if (cs35l41->reset_gpio) {
dev_info(cs35l41->dev, "Asserting Reset\n");
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
usleep_range(2000, 2100);
}
dev_dbg(cs35l41->dev, "System Suspended\n");
return ret;
}
static int cs35l41_wait_boot_done(struct cs35l41_hda *cs35l41)
{
unsigned int int_status;
int ret;
ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,
int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);
if (ret) {
dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE\n");
return ret;
}
ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_status);
if (ret || (int_status & CS35L41_OTP_BOOT_ERR)) {
dev_err(cs35l41->dev, "OTP Boot status %x error\n",
int_status & CS35L41_OTP_BOOT_ERR);
if (!ret)
ret = -EIO;
return ret;
}
return 0;
}
static int cs35l41_system_resume(struct device *dev)
{
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
@ -815,12 +867,24 @@ static int cs35l41_system_resume(struct device *dev)
}
if (cs35l41->reset_gpio) {
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
usleep_range(2000, 2100);
gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
}
usleep_range(2000, 2100);
regcache_cache_only(cs35l41->regmap, false);
regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);
usleep_range(2000, 2100);
ret = cs35l41_wait_boot_done(cs35l41);
if (ret)
return ret;
regcache_cache_only(cs35l41->regmap, true);
ret = pm_runtime_force_resume(dev);
if (ret) {
dev_err(dev, "System Resume Failed: Unable to runtime resume: %d\n", ret);
@ -882,6 +946,7 @@ err:
static int cs35l41_runtime_resume(struct device *dev)
{
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
unsigned int regid, reg_revid;
int ret = 0;
dev_dbg(cs35l41->dev, "Runtime Resume\n");
@ -903,6 +968,10 @@ static int cs35l41_runtime_resume(struct device *dev)
}
}
ret = cs35l41_verify_id(cs35l41, &regid, &reg_revid);
if (ret)
goto err;
/* Test key needs to be unlocked to allow the OTP settings to re-apply */
cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
ret = regcache_sync(cs35l41->regmap);
@ -915,6 +984,8 @@ static int cs35l41_runtime_resume(struct device *dev)
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
dev_dbg(cs35l41->dev, "CS35L41 Resumed (%x), Revision: %02X\n", regid, reg_revid);
err:
mutex_unlock(&cs35l41->fw_mutex);
@ -923,6 +994,7 @@ err:
static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
{
unsigned int fw_status;
__be32 halo_sts;
int ret;
@ -956,6 +1028,24 @@ static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
goto clean_dsp;
}
ret = regmap_read(cs35l41->regmap, CS35L41_DSP_MBOX_2, &fw_status);
if (ret < 0) {
dev_err(cs35l41->dev,
"Failed to read firmware status: %d\n", ret);
goto clean_dsp;
}
switch (fw_status) {
case CSPL_MBOX_STS_RUNNING:
case CSPL_MBOX_STS_PAUSED:
break;
default:
dev_err(cs35l41->dev, "Firmware status is invalid: %u\n",
fw_status);
ret = -EINVAL;
goto clean_dsp;
}
ret = cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, CSPL_MBOX_CMD_PAUSE);
if (ret) {
dev_err(cs35l41->dev, "Error waiting for DSP to pause: %u\n", ret);
@ -993,6 +1083,15 @@ static int cs35l41_fw_load_ctl_get(struct snd_kcontrol *kcontrol,
return 0;
}
static int cs35l41_mute_override_ctl_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = cs35l41->mute_override;
return 0;
}
static void cs35l41_fw_load_work(struct work_struct *work)
{
struct cs35l41_hda *cs35l41 = container_of(work, struct cs35l41_hda, fw_load_work);
@ -1076,6 +1175,7 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
{
char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
char fw_load_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
char mute_override_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
struct snd_kcontrol_new fw_type_ctl = {
.name = fw_type_ctl_name,
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
@ -1090,12 +1190,21 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
.get = cs35l41_fw_load_ctl_get,
.put = cs35l41_fw_load_ctl_put,
};
struct snd_kcontrol_new mute_override_ctl = {
.name = mute_override_ctl_name,
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.info = snd_ctl_boolean_mono_info,
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.get = cs35l41_mute_override_ctl_get,
};
int ret;
scnprintf(fw_type_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Type",
cs35l41->amp_name);
scnprintf(fw_load_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Load",
cs35l41->amp_name);
scnprintf(mute_override_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s Forced Mute Status",
cs35l41->amp_name);
ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41));
if (ret) {
@ -1113,9 +1222,65 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name);
ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&mute_override_ctl, cs35l41));
if (ret) {
dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", mute_override_ctl.name,
ret);
return ret;
}
dev_dbg(cs35l41->dev, "Added Control %s\n", mute_override_ctl.name);
return 0;
}
static bool cs35l41_dsm_supported(acpi_handle handle, unsigned int commands)
{
guid_t guid;
guid_parse(CS35L41_UUID, &guid);
return acpi_check_dsm(handle, &guid, 0, BIT(commands));
}
static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle handle)
{
guid_t guid;
union acpi_object *ret;
int mute = -ENODEV;
guid_parse(CS35L41_UUID, &guid);
if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) {
ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL);
mute = *ret->buffer.pointer;
dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute);
}
dev_dbg(cs35l41->dev, "%s: %d\n", __func__, mute);
return mute;
}
static void cs35l41_acpi_device_notify(acpi_handle handle, u32 event, struct device *dev)
{
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
int mute;
if (event != CS35L41_NOTIFY_EVENT)
return;
mute = cs35l41_get_acpi_mute_state(cs35l41, handle);
if (mute < 0) {
dev_warn(cs35l41->dev, "Unable to retrieve mute state: %d\n", mute);
return;
}
dev_dbg(cs35l41->dev, "Requesting mute value: %d\n", mute);
cs35l41->mute_override = (mute > 0);
cs35l41_mute(cs35l41->dev, cs35l41->mute_override);
}
static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data)
{
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
@ -1157,6 +1322,14 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
comps->playback_hook = cs35l41_hda_playback_hook;
comps->pre_playback_hook = cs35l41_hda_pre_playback_hook;
comps->post_playback_hook = cs35l41_hda_post_playback_hook;
comps->acpi_notify = cs35l41_acpi_device_notify;
comps->adev = cs35l41->dacpi;
comps->acpi_notifications_supported = cs35l41_dsm_supported(acpi_device_handle(comps->adev),
CS35L41_DSM_GET_MUTE);
cs35l41->mute_override = cs35l41_get_acpi_mute_state(cs35l41,
acpi_device_handle(cs35l41->dacpi)) > 0;
mutex_unlock(&cs35l41->fw_mutex);
@ -1430,8 +1603,8 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
return -ENODEV;
}
cs35l41->dacpi = adev;
physdev = get_device(acpi_get_first_physical_node(adev));
acpi_dev_put(adev);
sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
if (IS_ERR(sub))
@ -1541,6 +1714,7 @@ err:
hw_cfg->valid = false;
hw_cfg->gpio1.valid = false;
hw_cfg->gpio2.valid = false;
acpi_dev_put(cs35l41->dacpi);
put_physdev:
put_device(physdev);
@ -1550,7 +1724,7 @@ put_physdev:
int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
struct regmap *regmap)
{
unsigned int int_sts, regid, reg_revid, mtl_revid, chipid, int_status;
unsigned int regid, reg_revid;
struct cs35l41_hda *cs35l41;
int ret;
@ -1584,47 +1758,22 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
}
}
if (cs35l41->reset_gpio) {
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
usleep_range(2000, 2100);
gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
}
usleep_range(2000, 2100);
regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);
usleep_range(2000, 2100);
ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,
int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);
if (ret) {
dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE: %d\n", ret);
ret = cs35l41_wait_boot_done(cs35l41);
if (ret)
goto err;
}
ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
dev_err(cs35l41->dev, "OTP Boot status %x error: %d\n",
int_sts & CS35L41_OTP_BOOT_ERR, ret);
ret = -EIO;
ret = cs35l41_verify_id(cs35l41, &regid, &reg_revid);
if (ret)
goto err;
}
ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, &regid);
if (ret) {
dev_err(cs35l41->dev, "Get Device ID failed: %d\n", ret);
goto err;
}
ret = regmap_read(cs35l41->regmap, CS35L41_REVID, &reg_revid);
if (ret) {
dev_err(cs35l41->dev, "Get Revision ID failed: %d\n", ret);
goto err;
}
mtl_revid = reg_revid & CS35L41_MTLREVID_MASK;
chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
if (regid != chipid) {
dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", regid, chipid);
ret = -ENODEV;
goto err;
}
ret = cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
if (ret)
@ -1636,7 +1785,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
if (ret) {
dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
dev_err_probe(cs35l41->dev, ret, "OTP Unpack failed\n");
goto err;
}
@ -1644,10 +1793,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
if (ret)
goto err;
ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute,
ARRAY_SIZE(cs35l41_hda_mute));
if (ret)
goto err;
cs35l41_mute(cs35l41->dev, true);
INIT_WORK(&cs35l41->fw_load_work, cs35l41_fw_load_work);
mutex_init(&cs35l41->fw_mutex);
@ -1667,9 +1813,8 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);
if (ret) {
dev_err(cs35l41->dev, "Register component failed: %d\n", ret);
pm_runtime_disable(cs35l41->dev);
goto err;
dev_err_probe(cs35l41->dev, ret, "Register component failed\n");
goto err_pm;
}
dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid);
@ -1677,6 +1822,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
return 0;
err_pm:
pm_runtime_dont_use_autosuspend(cs35l41->dev);
pm_runtime_disable(cs35l41->dev);
pm_runtime_put_noidle(cs35l41->dev);
@ -1684,6 +1830,7 @@ err:
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio);
acpi_dev_put(cs35l41->dacpi);
kfree(cs35l41->acpi_subsystem_id);
return ret;
@ -1695,6 +1842,7 @@ void cs35l41_hda_remove(struct device *dev)
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
pm_runtime_get_sync(cs35l41->dev);
pm_runtime_dont_use_autosuspend(cs35l41->dev);
pm_runtime_disable(cs35l41->dev);
if (cs35l41->halo_initialized)
@ -1702,6 +1850,8 @@ void cs35l41_hda_remove(struct device *dev)
component_del(cs35l41->dev, &cs35l41_hda_comp_ops);
acpi_dev_put(cs35l41->dacpi);
pm_runtime_put_noidle(cs35l41->dev);
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))

View File

@ -10,6 +10,7 @@
#ifndef __CS35L41_HDA_H__
#define __CS35L41_HDA_H__
#include <linux/acpi.h>
#include <linux/efi.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h>
@ -70,6 +71,8 @@ struct cs35l41_hda {
bool halo_initialized;
bool playback_started;
struct cs_dsp cs_dsp;
struct acpi_device *dacpi;
bool mute_override;
};
enum halo_state {

View File

@ -58,9 +58,16 @@ static int hp_vision_acpi_fix(struct cs35l41_hda *cs35l41, struct device *physde
cs35l41->index = id;
cs35l41->channel_index = 0;
cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 1, GPIOD_OUT_HIGH);
/*
* This system has _DSD, it just contains an error, so we can still get the reset using
* the "reset" label.
*/
cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset",
cs35l41->index, GPIOD_OUT_LOW,
"cs35l41-reset");
cs35l41->speaker_id = -ENOENT;
hw_cfg->spk_pos = cs35l41->index ? 1 : 0; // right:left
hw_cfg->spk_pos = cs35l41->index ? 0 : 1; // right:left
hw_cfg->gpio1.func = CS35L41_NOT_USED;
hw_cfg->gpio1.valid = true;
hw_cfg->gpio2.func = CS35L41_INTERRUPT;

View File

@ -16,6 +16,7 @@
#include <sound/core.h>
#include <sound/hda_codec.h>
#include <sound/tlv.h>
#include "cirrus_scodec.h"
#include "cs35l56_hda.h"
#include "hda_component.h"
#include "hda_cs_dsp_ctl.h"
@ -869,7 +870,17 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int id)
"Read ACPI _SUB failed(%ld): fallback to generic firmware\n",
PTR_ERR(sub));
} else {
cs35l56->system_name = sub;
ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index, nval, -1);
if (ret == -ENOENT) {
cs35l56->system_name = sub;
} else if (ret >= 0) {
cs35l56->system_name = kasprintf(GFP_KERNEL, "%s-spkid%d", sub, ret);
kfree(sub);
if (!cs35l56->system_name)
return -ENOMEM;
} else {
return ret;
}
}
cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev,
@ -1024,7 +1035,18 @@ const struct dev_pm_ops cs35l56_hda_pm_ops = {
};
EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56);
#if IS_ENABLED(CONFIG_SND_HDA_SCODEC_CS35L56_KUNIT_TEST)
/* Hooks to export static function to KUnit test */
int cs35l56_hda_test_hook_get_speaker_id(struct device *dev, int amp_index, int num_amps)
{
return cs35l56_hda_get_speaker_id(dev, amp_index, num_amps);
}
EXPORT_SYMBOL_NS_GPL(cs35l56_hda_test_hook_get_speaker_id, SND_HDA_SCODEC_CS35L56);
#endif
MODULE_DESCRIPTION("CS35L56 HDA Driver");
MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);
MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS);
MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");

View File

@ -88,7 +88,7 @@ struct hda_conn_list {
struct list_head list;
int len;
hda_nid_t nid;
hda_nid_t conns[];
hda_nid_t conns[] __counted_by(len);
};
/* look up the cached results */

View File

@ -6,6 +6,7 @@
* Cirrus Logic International Semiconductor Ltd.
*/
#include <linux/acpi.h>
#include <linux/component.h>
#define HDA_MAX_COMPONENTS 4
@ -15,6 +16,9 @@ struct hda_component {
struct device *dev;
char name[HDA_MAX_NAME_SIZE];
struct hda_codec *codec;
struct acpi_device *adev;
bool acpi_notifications_supported;
void (*acpi_notify)(acpi_handle handle, u32 event, struct device *dev);
void (*pre_playback_hook)(struct device *dev, int action);
void (*playback_hook)(struct device *dev, int action);
void (*post_playback_hook)(struct device *dev, int action);

View File

@ -182,7 +182,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
if (err < 0)
goto unlock;
snd_hdac_stream_setup(azx_stream(azx_dev));
snd_hdac_stream_setup(azx_stream(azx_dev), false);
stream_tag = azx_dev->core.stream_tag;
/* CA-IBG chips need the playback stream starting from 1 */

View File

@ -806,7 +806,7 @@ static unsigned int azx_via_get_position(struct azx *chip,
mod_dma_pos = le32_to_cpu(*azx_dev->core.posbuf);
mod_dma_pos %= azx_dev->core.period_bytes;
fifo_size = azx_stream(azx_dev)->fifo_size - 1;
fifo_size = azx_stream(azx_dev)->fifo_size;
if (azx_dev->insufficient) {
/* Link position never gather than FIFO size */
@ -2129,6 +2129,36 @@ static int azx_probe(struct pci_dev *pci,
pci_set_drvdata(pci, card);
#ifdef CONFIG_SND_HDA_I915
/* bind with i915 if needed */
if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) {
err = snd_hdac_i915_init(azx_bus(chip));
if (err < 0) {
/* if the controller is bound only with HDMI/DP
* (for HSW and BDW), we need to abort the probe;
* for other chips, still continue probing as other
* codecs can be on the same link.
*/
if (HDA_CONTROLLER_IN_GPU(pci)) {
dev_err_probe(card->dev, err,
"HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n");
goto out_free;
} else {
/* don't bother any longer */
chip->driver_caps &= ~AZX_DCAPS_I915_COMPONENT;
}
}
/* HSW/BDW controllers need this power */
if (HDA_CONTROLLER_IN_GPU(pci))
hda->need_i915_power = true;
}
#else
if (HDA_CONTROLLER_IN_GPU(pci))
dev_err(card->dev, "Haswell/Broadwell HDMI/DP must build in CONFIG_SND_HDA_I915\n");
#endif
err = register_vga_switcheroo(chip);
if (err < 0) {
dev_err(card->dev, "Error registering vga_switcheroo client\n");
@ -2156,11 +2186,6 @@ static int azx_probe(struct pci_dev *pci,
}
#endif /* CONFIG_SND_HDA_PATCH_LOADER */
#ifndef CONFIG_SND_HDA_I915
if (HDA_CONTROLLER_IN_GPU(pci))
dev_err(card->dev, "Haswell/Broadwell HDMI/DP must build in CONFIG_SND_HDA_I915\n");
#endif
if (schedule_probe)
schedule_delayed_work(&hda->probe_work, 0);
@ -2170,6 +2195,7 @@ static int azx_probe(struct pci_dev *pci,
return 0;
out_free:
pci_set_drvdata(pci, NULL);
snd_card_free(card);
return err;
}
@ -2257,30 +2283,6 @@ static int azx_probe_continue(struct azx *chip)
to_hda_bus(bus)->bus_probing = 1;
hda->probe_continued = 1;
/* bind with i915 if needed */
if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) {
err = snd_hdac_i915_init(bus);
if (err < 0) {
/* if the controller is bound only with HDMI/DP
* (for HSW and BDW), we need to abort the probe;
* for other chips, still continue probing as other
* codecs can be on the same link.
*/
if (HDA_CONTROLLER_IN_GPU(pci)) {
dev_err(chip->card->dev,
"HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n");
goto out_free;
} else {
/* don't bother any longer */
chip->driver_caps &= ~AZX_DCAPS_I915_COMPONENT;
}
}
/* HSW/BDW controllers need this power */
if (HDA_CONTROLLER_IN_GPU(pci))
hda->need_i915_power = true;
}
/* Request display power well for the HDA controller or codec. For
* Haswell/Broadwell, both the display HDA controller and codec need
* this power. For other platforms, like Baytrail/Braswell, only the

View File

@ -10,6 +10,7 @@
* Jonathan Woithe <jwoithe@just42.net>
*/
#include <linux/acpi.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
@ -6704,12 +6705,91 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
}
}
#ifdef CONFIG_ACPI
static void comp_acpi_device_notify(acpi_handle handle, u32 event, void *data)
{
struct hda_codec *cdc = data;
struct alc_spec *spec = cdc->spec;
int i;
codec_info(cdc, "ACPI Notification %d\n", event);
for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
if (spec->comps[i].dev && spec->comps[i].acpi_notify)
spec->comps[i].acpi_notify(acpi_device_handle(spec->comps[i].adev), event,
spec->comps[i].dev);
}
}
static int comp_bind_acpi(struct device *dev)
{
struct hda_codec *cdc = dev_to_hda_codec(dev);
struct alc_spec *spec = cdc->spec;
bool support_notifications = false;
struct acpi_device *adev;
int ret;
int i;
adev = spec->comps[0].adev;
if (!acpi_device_handle(adev))
return 0;
for (i = 0; i < HDA_MAX_COMPONENTS; i++)
support_notifications = support_notifications ||
spec->comps[i].acpi_notifications_supported;
if (support_notifications) {
ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
comp_acpi_device_notify, cdc);
if (ret < 0) {
codec_warn(cdc, "Failed to install notify handler: %d\n", ret);
return 0;
}
codec_dbg(cdc, "Notify handler installed\n");
}
return 0;
}
static void comp_unbind_acpi(struct device *dev)
{
struct hda_codec *cdc = dev_to_hda_codec(dev);
struct alc_spec *spec = cdc->spec;
struct acpi_device *adev;
int ret;
adev = spec->comps[0].adev;
if (!acpi_device_handle(adev))
return;
ret = acpi_remove_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
comp_acpi_device_notify);
if (ret < 0)
codec_warn(cdc, "Failed to uninstall notify handler: %d\n", ret);
}
#else
static int comp_bind_acpi(struct device *dev)
{
return 0;
}
static void comp_unbind_acpi(struct device *dev)
{
}
#endif
static int comp_bind(struct device *dev)
{
struct hda_codec *cdc = dev_to_hda_codec(dev);
struct alc_spec *spec = cdc->spec;
int ret;
return component_bind_all(dev, spec->comps);
ret = component_bind_all(dev, spec->comps);
if (ret)
return ret;
return comp_bind_acpi(dev);
}
static void comp_unbind(struct device *dev)
@ -6717,6 +6797,7 @@ static void comp_unbind(struct device *dev)
struct hda_codec *cdc = dev_to_hda_codec(dev);
struct alc_spec *spec = cdc->spec;
comp_unbind_acpi(dev);
component_unbind_all(dev, spec->comps);
}

View File

@ -918,7 +918,7 @@ static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing)
}
if (chip->device_type == DEVICE_SIS) {
/* unmute the output on SIS7012 */
/* unmute the output on SIS7013 */
iputword(chip, 0x4c, igetword(chip, 0x4c) | 1);
}

View File

@ -68,7 +68,7 @@ struct mixart_enum_connector_resp
u32 uid_count;
u32 current_uid_index;
struct mixart_uid uid[MIXART_MAX_PHYS_CONNECTORS];
} __attribute__((packed));
} __packed;
/* used for following struct */
@ -81,7 +81,7 @@ struct mixart_audio_info_req
u32 line_max_level; /* float */
u32 micro_max_level; /* float */
u32 cd_max_level; /* float */
} __attribute__((packed));
} __packed;
struct mixart_analog_hw_info
{
@ -93,7 +93,7 @@ struct mixart_analog_hw_info
u32 step_var_level; /* float */
u32 fix_gain; /* float */
u32 zero_var; /* float */
} __attribute__((packed));
} __packed;
struct mixart_digital_hw_info
{
@ -101,7 +101,7 @@ struct mixart_digital_hw_info
u32 presence;
u32 clock;
u32 reserved;
} __attribute__((packed));
} __packed;
struct mixart_analog_info
{
@ -110,27 +110,27 @@ struct mixart_analog_info
struct mixart_analog_hw_info line_info;
struct mixart_analog_hw_info cd_info;
u32 analog_level_present;
} __attribute__((packed));
} __packed;
struct mixart_digital_info
{
u32 type_mask;
struct mixart_digital_hw_info aes_info;
struct mixart_digital_hw_info adat_info;
} __attribute__((packed));
} __packed;
struct mixart_audio_info
{
u32 clock_type_mask;
struct mixart_analog_info analog_info;
struct mixart_digital_info digital_info;
} __attribute__((packed));
} __packed;
struct mixart_audio_info_resp
{
u32 txx_status;
struct mixart_audio_info info;
} __attribute__((packed));
} __packed;
/* used for nb_bytes_max_per_sample */
@ -142,7 +142,7 @@ struct mixart_stream_info
u32 size_max_byte_frame;
u32 size_max_sample_frame;
u32 nb_bytes_max_per_sample; /* float */
} __attribute__((packed));
} __packed;
/* MSG_STREAM_ADD_INPUT_GROUP */
/* MSG_STREAM_ADD_OUTPUT_GROUP */
@ -157,13 +157,13 @@ struct mixart_streaming_group_req
struct mixart_stream_info stream_info[32];
struct mixart_uid connector;
u32 flow_entry[32];
} __attribute__((packed));
} __packed;
struct mixart_stream_desc
{
struct mixart_uid stream_uid;
u32 stream_desc;
} __attribute__((packed));
} __packed;
struct mixart_streaming_group
{
@ -172,7 +172,7 @@ struct mixart_streaming_group
u32 pipe_desc;
u32 stream_count;
struct mixart_stream_desc stream[32];
} __attribute__((packed));
} __packed;
/* MSG_STREAM_DELETE_GROUP */
@ -182,7 +182,7 @@ struct mixart_delete_group_resp
{
u32 status;
u32 unused[2];
} __attribute__((packed));
} __packed;
/* MSG_STREAM_START_INPUT_STAGE_PACKET = 0x130000 + 7,
@ -195,7 +195,7 @@ struct mixart_fx_couple_uid
{
struct mixart_uid uid_fx_code;
struct mixart_uid uid_fx_data;
} __attribute__((packed));
} __packed;
struct mixart_txx_stream_desc
{
@ -203,14 +203,14 @@ struct mixart_txx_stream_desc
u32 stream_idx;
u32 fx_number;
struct mixart_fx_couple_uid uid_fx[4];
} __attribute__((packed));
} __packed;
struct mixart_flow_info
{
struct mixart_txx_stream_desc stream_desc;
u32 flow_entry;
u32 flow_phy_addr;
} __attribute__((packed));
} __packed;
struct mixart_stream_state_req
{
@ -219,7 +219,7 @@ struct mixart_stream_state_req
u32 reserved4np[3];
u32 stream_count; /* set to 1 for instance */
struct mixart_flow_info stream_info; /* could be an array[stream_count] */
} __attribute__((packed));
} __packed;
/* MSG_STREAM_START_STREAM_GRP_PACKET = 0x130000 + 6
MSG_STREAM_STOP_STREAM_GRP_PACKET = 0x130000 + 9
@ -232,13 +232,13 @@ struct mixart_group_state_req
u32 reserved4np[2];
u32 pipe_count; /* set to 1 for instance */
struct mixart_uid pipe_uid; /* could be an array[pipe_count], in theory */
} __attribute__((packed));
} __packed;
struct mixart_group_state_resp
{
u32 txx_status;
u64 scheduler;
} __attribute__((packed));
} __packed;
@ -250,7 +250,7 @@ struct mixart_sample_pos
u32 validity;
u32 sample_pos_high_part;
u32 sample_pos_low_part;
} __attribute__((packed));
} __packed;
/*
* This structure is limited by the size of MSG_DEFAULT_SIZE. Instead of
@ -263,7 +263,7 @@ struct mixart_timer_notify
{
u32 stream_count;
struct mixart_sample_pos streams[MIXART_MAX_TIMER_NOTIFY_STREAMS];
} __attribute__((packed));
} __packed;
/* MSG_CONSOLE_GET_CLOCK_UID = 0x070003,
@ -275,7 +275,7 @@ struct mixart_return_uid
{
u32 error_code;
struct mixart_uid uid;
} __attribute__((packed));
} __packed;
/* MSG_CLOCK_CHECK_PROPERTIES = 0x200001,
MSG_CLOCK_SET_PROPERTIES = 0x200002,
@ -315,13 +315,13 @@ struct mixart_clock_properties
u32 board_mask;
u32 nb_callers; /* set to 1 (see below) */
struct mixart_uid uid_caller;
} __attribute__((packed));
} __packed;
struct mixart_clock_properties_resp
{
u32 status;
u32 clock_mode;
} __attribute__((packed));
} __packed;
/* MSG_STREAM_SET_INPUT_STAGE_PARAM = 0x13000F */
@ -402,7 +402,7 @@ struct mixart_stream_param_desc
u32 pipe_count; /* set to 1 (array size !) */
u32 stream_count; /* set to 1 (array size !) */
struct mixart_txx_stream_desc stream_desc; /* only one stream per command, but this could be an array, in theory */
} __attribute__((packed));
} __packed;
/* MSG_CONNECTOR_GET_OUT_AUDIO_LEVEL = 0x050009,
@ -418,7 +418,7 @@ struct mixart_get_out_audio_level
u32 mute;
u32 monitor_mute1;
u32 monitor_mute2;
} __attribute__((packed));
} __packed;
/* MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL = 0x05000A,
@ -445,7 +445,7 @@ struct mixart_set_out_audio_level
u32 monitor_mute1;
u32 monitor_mute2;
u32 reserved4np;
} __attribute__((packed));
} __packed;
/* MSG_SYSTEM_ENUM_PHYSICAL_IO = 0x16000E,
@ -460,7 +460,7 @@ struct mixart_uid_enumeration
u32 nb_uid;
u32 current_uid_index;
struct mixart_uid uid[MIXART_MAX_PHYS_IO];
} __attribute__((packed));
} __packed;
/* MSG_PHYSICALIO_SET_LEVEL = 0x0F0008,
@ -471,13 +471,13 @@ struct mixart_io_channel_level
{
u32 analog_level; /* float */
u32 unused[2];
} __attribute__((packed));
} __packed;
struct mixart_io_level
{
s32 channel; /* 0=left, 1=right, -1=both, -2=both same */
struct mixart_io_channel_level level[2];
} __attribute__((packed));
} __packed;
/* MSG_STREAM_SET_IN_AUDIO_LEVEL = 0x130015,
@ -490,7 +490,7 @@ struct mixart_in_audio_level_info
u32 valid_mask2;
u32 digital_level;
u32 analog_level;
} __attribute__((packed));
} __packed;
struct mixart_set_in_audio_level_req
{
@ -499,7 +499,7 @@ struct mixart_set_in_audio_level_req
u32 audio_count; /* set to <= 2 */
u32 reserved4np;
struct mixart_in_audio_level_info level[2];
} __attribute__((packed));
} __packed;
/* response is a 32 bit status */
@ -529,13 +529,13 @@ struct mixart_out_stream_level_info
u32 digital_level2;
u32 mute1;
u32 mute2;
} __attribute__((packed));
} __packed;
struct mixart_set_out_stream_level
{
struct mixart_txx_stream_desc desc;
struct mixart_out_stream_level_info out_level;
} __attribute__((packed));
} __packed;
struct mixart_set_out_stream_level_req
{
@ -544,7 +544,7 @@ struct mixart_set_out_stream_level_req
u32 reserved4np[2];
u32 nb_of_stream; /* set to 1 */
struct mixart_set_out_stream_level stream_level; /* could be an array */
} __attribute__((packed));
} __packed;
/* response to this request is a u32 status value */

View File

@ -61,6 +61,76 @@ static const struct config_entry config_table[] = {
{}
},
},
{
.flags = FLAG_AMD_LEGACY,
.device = ACP_PCI_DEV_ID,
.dmi_table = (const struct dmi_system_id []) {
{
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXXW"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
},
},
{}
},
},
{
.flags = FLAG_AMD_LEGACY,
.device = ACP_PCI_DEV_ID,
.dmi_table = (const struct dmi_system_id []) {
{
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXX9"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
},
},
{}
},
},
{
.flags = FLAG_AMD_LEGACY,
.device = ACP_PCI_DEV_ID,
.dmi_table = (const struct dmi_system_id []) {
{
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BOM-WXX9"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
},
},
{}
},
},
{
.flags = FLAG_AMD_LEGACY,
.device = ACP_PCI_DEV_ID,
.dmi_table = (const struct dmi_system_id []) {
{
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1020"),
},
},
{}
},
},
{
.flags = FLAG_AMD_LEGACY,
.device = ACP_PCI_DEV_ID,
.dmi_table = (const struct dmi_system_id []) {
{
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1040"),
},
},
{}
},
},
};
int snd_amd_acp_find_config(struct pci_dev *pci)
@ -193,4 +263,16 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[] = {
};
EXPORT_SYMBOL(snd_soc_acpi_amd_rmb_sof_machines);
struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[] = {
{
.id = "AMDI1019",
.drv_name = "acp63-dsp",
.pdata = &acp_quirk_data,
.fw_filename = "sof-acp_6_3.ri",
.sof_tplg_filename = "sof-acp_6_3.tplg",
},
{},
};
EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_machines);
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -54,7 +54,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
{
int ret;
struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
struct snd_soc_component *component = codec_dai->component;
dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
@ -106,7 +106,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
static int da7219_clk_enable(struct snd_pcm_substream *substream)
{
int ret = 0;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
/*
* Set wclk to 48000 because the rate constraint of this driver is
@ -134,7 +134,7 @@ static int cz_rt5682_init(struct snd_soc_pcm_runtime *rtd)
{
int ret;
struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
struct snd_soc_component *component = codec_dai->component;
dev_info(codec_dai->dev, "codec dai name = %s\n", codec_dai->name);
@ -191,7 +191,7 @@ static int cz_rt5682_init(struct snd_soc_pcm_runtime *rtd)
static int rt5682_clk_enable(struct snd_pcm_substream *substream)
{
int ret;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
/*
* Set wclk to 48000 because the rate constraint of this driver is
@ -245,7 +245,7 @@ static const struct snd_pcm_hw_constraint_list constraints_channels = {
static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
@ -266,7 +266,7 @@ static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
@ -288,7 +288,7 @@ static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
static int cz_max_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
@ -309,7 +309,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream)
static int cz_dmic0_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
@ -330,7 +330,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream *substream)
static int cz_dmic1_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
@ -357,7 +357,7 @@ static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
static int cz_rt5682_play_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
@ -378,7 +378,7 @@ static int cz_rt5682_play_startup(struct snd_pcm_substream *substream)
static int cz_rt5682_cap_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
@ -400,7 +400,7 @@ static int cz_rt5682_cap_startup(struct snd_pcm_substream *substream)
static int cz_rt5682_max_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
@ -421,7 +421,7 @@ static int cz_rt5682_max_startup(struct snd_pcm_substream *substream)
static int cz_rt5682_dmic0_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
@ -442,7 +442,7 @@ static int cz_rt5682_dmic0_startup(struct snd_pcm_substream *substream)
static int cz_rt5682_dmic1_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);

View File

@ -62,7 +62,7 @@ static int st_es8336_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_card *card;
struct snd_soc_component *codec;
codec = asoc_rtd_to_codec(rtd, 0)->component;
codec = snd_soc_rtd_to_codec(rtd, 0)->component;
card = rtd->card;
ret = snd_soc_card_jack_new_pins(card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0,
@ -111,10 +111,10 @@ static int st_es8336_codec_startup(struct snd_pcm_substream *substream)
int ret;
runtime = substream->runtime;
rtd = asoc_substream_to_rtd(substream);
rtd = snd_soc_substream_to_rtd(substream);
card = rtd->card;
machine = snd_soc_card_get_drvdata(card);
codec_dai = asoc_rtd_to_codec(rtd, 0);
codec_dai = snd_soc_rtd_to_codec(rtd, 0);
ret = snd_soc_dai_set_sysclk(codec_dai, 0, ES8336_PLL_FREQ, SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);

View File

@ -849,7 +849,7 @@ static int acp_dma_hw_params(struct snd_soc_component *component,
u32 val = 0;
struct snd_pcm_runtime *runtime;
struct audio_substream_data *rtd;
struct snd_soc_pcm_runtime *prtd = asoc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *prtd = snd_soc_substream_to_rtd(substream);
struct audio_drv_data *adata = dev_get_drvdata(component->dev);
struct snd_soc_card *card = prtd->card;
struct acp_platform_info *pinfo = snd_soc_card_get_drvdata(card);

View File

@ -57,8 +57,8 @@ static int cz_aif1_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
int ret = 0;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK,
CZ_PLAT_CLK, params_rate(params) * 512);
@ -83,7 +83,7 @@ static int cz_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_card *card;
struct snd_soc_component *codec;
codec = asoc_rtd_to_codec(rtd, 0)->component;
codec = snd_soc_rtd_to_codec(rtd, 0)->component;
card = rtd->card;
ret = snd_soc_card_jack_new_pins(card, "Headset Jack",

View File

@ -30,13 +30,15 @@ config SND_SOC_AMD_ACP_PCM
config SND_SOC_AMD_ACP_PCI
tristate "AMD ACP PCI Driver Support"
select SND_SOC_AMD_ACP_LEGACY_COMMON
depends on X86 && PCI
depends on ACPI
select SND_SOC_AMD_ACP_LEGACY_COMMON
help
This options enables generic PCI driver for ACP device.
config SND_AMD_ASOC_RENOIR
tristate "AMD ACP ASOC Renoir Support"
depends on ACPI
select SND_SOC_AMD_ACP_PCM
select SND_SOC_AMD_ACP_I2S
select SND_SOC_AMD_ACP_PDM
@ -47,6 +49,7 @@ config SND_AMD_ASOC_RENOIR
config SND_AMD_ASOC_REMBRANDT
tristate "AMD ACP ASOC Rembrandt Support"
depends on ACPI
select SND_SOC_AMD_ACP_PCM
select SND_SOC_AMD_ACP_I2S
select SND_SOC_AMD_ACP_PDM
@ -57,6 +60,19 @@ config SND_AMD_ASOC_REMBRANDT
Say Y if you want to enable AUDIO on Rembrandt
If unsure select "N".
config SND_AMD_ASOC_ACP63
tristate "AMD ACP ASOC ACP6.3 Support"
depends on X86 && PCI
depends on ACPI
select SND_SOC_AMD_ACP_PCM
select SND_SOC_AMD_ACP_I2S
select SND_SOC_AMD_ACP_PDM
select SND_SOC_AMD_ACP_LEGACY_COMMON
help
This option enables Acp6.3 I2S support on AMD platform.
Say Y if you want to enable AUDIO on ACP6.3
If unsure select "N".
config SND_SOC_AMD_MACH_COMMON
tristate
depends on X86 && PCI && I2C

View File

@ -14,10 +14,11 @@ snd-acp-pci-objs := acp-pci.o
#platform specific driver
snd-acp-renoir-objs := acp-renoir.o
snd-acp-rembrandt-objs := acp-rembrandt.o
snd-acp63-objs := acp63.o
#machine specific driver
snd-acp-mach-objs := acp-mach-common.o
snd-acp-legacy-mach-objs := acp-legacy-mach.o
snd-acp-legacy-mach-objs := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o
snd-acp-sof-mach-objs := acp-sof-mach.o
obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
@ -28,6 +29,7 @@ obj-$(CONFIG_SND_SOC_AMD_ACP_PCI) += snd-acp-pci.o
obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
obj-$(CONFIG_SND_AMD_ASOC_REMBRANDT) += snd-acp-rembrandt.o
obj-$(CONFIG_SND_AMD_ASOC_ACP63) += snd-acp63.o
obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o

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