Merge branch 'for-next' into for-linus

Pull 6.7 materials

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2023-10-31 08:58:36 +01:00
commit c468b5dd75
656 changed files with 12214 additions and 5721 deletions
Documentation
MAINTAINERS
arch
arm/mach-omap2
sh/boards
mach-ecovec24
mach-se/7724
drivers
include
sound

View File

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

View File

@ -9,6 +9,9 @@ title: Audio Graph
maintainers: maintainers:
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> - Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
allOf:
- $ref: /schemas/sound/dai-params.yaml#
properties: properties:
dais: dais:
$ref: /schemas/types.yaml#/definitions/phandle-array $ref: /schemas/types.yaml#/definitions/phandle-array
@ -30,12 +33,6 @@ properties:
widget ("Microphone", "Line", "Headphone", "Speaker"), the widget ("Microphone", "Line", "Headphone", "Speaker"), the
second being the machine specific name for the widget. second being the machine specific name for the widget.
$ref: /schemas/types.yaml#/definitions/non-unique-string-array $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: pa-gpios:
maxItems: 1 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,9 +14,6 @@ description:
digital Smart K audio amplifier with an integrated 10.25V digital Smart K audio amplifier with an integrated 10.25V
smart boost convert. smart boost convert.
allOf:
- $ref: dai-common.yaml#
properties: properties:
compatible: compatible:
enum: enum:
@ -32,11 +29,36 @@ properties:
reset-gpios: reset-gpios:
maxItems: 1 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: required:
- compatible - compatible
- reg - reg
- '#sound-dai-cells' - '#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 unevaluatedProperties: false
@ -51,5 +73,7 @@ examples:
reg = <0x34>; reg = <0x34>;
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>; 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 Current at which the headset micbias sense clamp will engage, 0 to
disable. disable.
enum: [ 0, 14, 24, 43, 52, 61, 71, 90, 99 ] enum: [ 0, 14, 24, 43, 52, 61, 71, 90, 99 ]
default: 0 default: 14
cirrus,bias-ramp-ms: cirrus,bias-ramp-ms:
description: description:
@ -97,7 +97,7 @@ properties:
Time in microseconds the type detection will run for. Long values will Time in microseconds the type detection will run for. Long values will
cause more audible effects, but give more accurate detection. cause more audible effects, but give more accurate detection.
enum: [ 20, 100, 1000, 10000, 50000, 75000, 100000, 200000 ] enum: [ 20, 100, 1000, 10000, 50000, 75000, 100000, 200000 ]
default: 10000 default: 1000
cirrus,button-automute: cirrus,button-automute:
type: boolean type: boolean

View File

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

View File

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

View File

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

View File

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

View File

@ -17,6 +17,7 @@ properties:
enum: enum:
- mediatek,mt8186-mt6366-rt1019-rt5682s-sound - mediatek,mt8186-mt6366-rt1019-rt5682s-sound
- mediatek,mt8186-mt6366-rt5682s-max98360-sound - mediatek,mt8186-mt6366-rt5682s-max98360-sound
- mediatek,mt8186-mt6366-rt5650-sound
mediatek,platform: mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle $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 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: Required properties:
- compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141" or - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141",
"ti,pcm5142" "ti,pcm5142", "ti,tas5754" or "ti,tas5756"
- reg : the I2C address of the device for I2C, the chip select - reg : the I2C address of the device for I2C, the chip select
number for SPI. number for SPI.
@ -25,6 +25,7 @@ Optional properties:
through <6>. The device will be configured for clock input on the 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 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. 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: Examples:

View File

@ -13,6 +13,7 @@ properties:
compatible: compatible:
enum: enum:
- qcom,sc7280-lpass-tx-macro - qcom,sc7280-lpass-tx-macro
- qcom,sm6115-lpass-tx-macro
- qcom,sm8250-lpass-tx-macro - qcom,sm8250-lpass-tx-macro
- qcom,sm8450-lpass-tx-macro - qcom,sm8450-lpass-tx-macro
- qcom,sm8550-lpass-tx-macro - qcom,sm8550-lpass-tx-macro
@ -97,6 +98,23 @@ allOf:
- const: dcodec - const: dcodec
- const: fsgen - 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: - if:
properties: properties:
compatible: compatible:

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. generated from TI's PPC3 tool.
$ref: /schemas/types.yaml#/definitions/string $ref: /schemas/types.yaml#/definitions/string
additionalProperties: false
examples: examples:
- | - |
i2c { i2c {
@ -52,5 +54,4 @@ examples:
ti,dsp-config-name = "mono_pbtl_48khz"; 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: ports:
$ref: audio-graph-port.yaml#/definitions/port-base $ref: audio-graph-port.yaml#/definitions/port-base
unevaluatedProperties: false
properties: properties:
port@0: port@0:
$ref: audio-graph-port.yaml# $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) - 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) - 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: Example:
wm8782: stereo-adc { wm8782: stereo-adc {
compatible = "wlf,wm8782"; compatible = "wlf,wm8782";
Vdda-supply = <&vdda_supply>; Vdda-supply = <&vdda_supply>;
Vdd-supply = <&vdd_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 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM, | SND_SOC_DAIFMT_CBM_CFM,
.ignore_suspend = 1, .ignore_suspend = 1,
.params = &dsp_codec_params, .c2c_params = &dsp_codec_params,
.num_c2c_params = 1,
}, },
{ {
.name = "DSP-CODEC", .name = "DSP-CODEC",
@ -81,12 +82,13 @@ file:
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM, | SND_SOC_DAIFMT_CBM_CFM,
.ignore_suspend = 1, .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. 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. dai_link is a codec to codec connection.
In dapm core a route is created between cpu_dai playback widget 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", .codec_name = "modem",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM, | SND_SOC_DAIFMT_CBM_CFM,
.params = &dai_params, .c2c_params = &dai_params,
.num_c2c_params = 1,
} }
< ... more DAI links here ... > < ... more DAI links here ... >

View File

@ -4912,6 +4912,7 @@ F: drivers/spi/spi-cs42l43*
F: include/dt-bindings/sound/cs* F: include/dt-bindings/sound/cs*
F: include/linux/mfd/cs42l43* F: include/linux/mfd/cs42l43*
F: include/sound/cs* F: include/sound/cs*
F: sound/pci/hda/cirrus*
F: sound/pci/hda/cs* F: sound/pci/hda/cs*
F: sound/pci/hda/hda_cs_dsp_ctl.* F: sound/pci/hda/hda_cs_dsp_ctl.*
F: sound/soc/codecs/cs* F: sound/soc/codecs/cs*
@ -8125,7 +8126,7 @@ M: Geoffrey D. Bennett <g@b4.vu>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git 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 FORCEDETH GIGABIT ETHERNET DRIVER
M: Rain River <rain.1986.08.12@gmail.com> M: Rain River <rain.1986.08.12@gmail.com>
@ -15423,7 +15424,7 @@ NXP TFA9879 DRIVER
M: Peter Rosin <peda@axentia.se> M: Peter Rosin <peda@axentia.se>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/sound/tfa9879.txt F: Documentation/devicetree/bindings/sound/nxp,tfa9879.yaml
F: sound/soc/codecs/tfa9879* F: sound/soc/codecs/tfa9879*
NXP-NCI NFC DRIVER NXP-NCI NFC DRIVER
@ -20066,7 +20067,7 @@ F: include/linux/sony-laptop.h
SOUND SOUND
M: Jaroslav Kysela <perex@perex.cz> M: Jaroslav Kysela <perex@perex.cz>
M: Takashi Iwai <tiwai@suse.com> M: Takashi Iwai <tiwai@suse.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: linux-sound@vger.kernel.org
S: Maintained S: Maintained
W: http://www.alsa-project.org/ W: http://www.alsa-project.org/
Q: http://patchwork.kernel.org/project/alsa-devel/list/ Q: http://patchwork.kernel.org/project/alsa-devel/list/
@ -20079,7 +20080,7 @@ F: tools/testing/selftests/alsa
SOUND - ALSA SELFTESTS SOUND - ALSA SELFTESTS
M: Mark Brown <broonie@kernel.org> 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 L: linux-kselftest@vger.kernel.org
S: Supported S: Supported
F: tools/testing/selftests/alsa F: tools/testing/selftests/alsa
@ -20105,7 +20106,7 @@ F: sound/soc/soc-generic-dmaengine-pcm.c
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
M: Liam Girdwood <lgirdwood@gmail.com> M: Liam Girdwood <lgirdwood@gmail.com>
M: Mark Brown <broonie@kernel.org> M: Mark Brown <broonie@kernel.org>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: linux-sound@vger.kernel.org
S: Supported S: Supported
W: http://alsa-project.org/main/index.php/ASoC W: http://alsa-project.org/main/index.php/ASoC
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
@ -20113,6 +20114,10 @@ F: Documentation/devicetree/bindings/sound/
F: Documentation/sound/soc/ F: Documentation/sound/soc/
F: include/dt-bindings/sound/ F: include/dt-bindings/sound/
F: include/sound/soc* 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/ F: sound/soc/
SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS
@ -20466,6 +20471,13 @@ S: Supported
F: Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml F: Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml
F: drivers/clk/starfive/clk-starfive-jh7110-pll.c 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 STARFIVE JH7110 SYSCON
M: William Qiu <william.qiu@starfivetech.com> M: William Qiu <william.qiu@starfivetech.com>
M: Xingyu Wu <xingyu.wu@starfivetech.com> M: Xingyu Wu <xingyu.wu@starfivetech.com>
@ -22936,7 +22948,7 @@ F: fs/vboxsf/*
VIRTUAL PCM TEST DRIVER VIRTUAL PCM TEST DRIVER
M: Ivan Orlov <ivan.orlov0322@gmail.com> M: Ivan Orlov <ivan.orlov0322@gmail.com>
L: alsa-devel@alsa-project.org L: linux-sound@vger.kernel.org
S: Maintained S: Maintained
F: Documentation/sound/cards/pcmtest.rst F: Documentation/sound/cards/pcmtest.rst
F: sound/drivers/pcmtest.c 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, .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) static int __init n8x0_late_initcall(void)
{ {
if (!board_caps) if (!board_caps)
@ -505,6 +514,7 @@ static int __init n8x0_late_initcall(void)
n8x0_mmc_init(); n8x0_mmc_init();
n8x0_usb_init(); n8x0_usb_init();
gpiod_add_lookup_table(&nokia810_asoc_gpio_table);
return 0; return 0;
} }

View File

@ -275,9 +275,19 @@ static struct platform_device pandora_backlight = {
.id = -1, .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) static void __init omap3_pandora_legacy_init(void)
{ {
platform_device_register(&pandora_backlight); platform_device_register(&pandora_backlight);
gpiod_add_lookup_table(&pandora_soc_audio_gpios);
} }
#endif /* CONFIG_ARCH_OMAP3 */ #endif /* CONFIG_ARCH_OMAP3 */

View File

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

View File

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

View File

@ -512,6 +512,10 @@ static struct gpio_desc *of_find_gpio_rename(struct device_node *np,
#if IS_ENABLED(CONFIG_SND_SOC_CS42L56) #if IS_ENABLED(CONFIG_SND_SOC_CS42L56)
{ "reset", "cirrus,gpio-nreset", "cirrus,cs42l56" }, { "reset", "cirrus,gpio-nreset", "cirrus,cs42l56" },
#endif #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) #if IS_ENABLED(CONFIG_SND_SOC_TLV320AIC3X)
{ "reset", "gpio-reset", "ti,tlv320aic3x" }, { "reset", "gpio-reset", "ti,tlv320aic3x" },
{ "reset", "gpio-reset", "ti,tlv320aic33" }, { "reset", "gpio-reset", "ti,tlv320aic33" },

View File

@ -759,7 +759,7 @@ static int intel_prepare(struct snd_pcm_substream *substream,
} }
if (dai_runtime->suspended) { 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; struct snd_pcm_hw_params *hw_params;
hw_params = &rtd->dpcm[substream->stream].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) { 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; struct snd_pcm_hw_params *hw_params;
hw_params = &rtd->dpcm[substream->stream].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; struct snd_soc_dai *dai;
/* Find stream from first CPU 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); 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_digimic0;
bool has_digimic1; bool has_digimic1;
u8 has_linein; u8 has_linein;
/* Jack detect GPIO or <= 0 if it is not implemented */
int jack_detect;
}; };
#endif /* _OMAP_TWL4030_H_ */ #endif /* _OMAP_TWL4030_H_ */

View File

@ -11,7 +11,6 @@
#define __CS35L41_H #define __CS35L41_H
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/completion.h>
#include <linux/firmware/cirrus/cs_dsp.h> #include <linux/firmware/cirrus/cs_dsp.h>
#define CS35L41_FIRSTREG 0x00000000 #define CS35L41_FIRSTREG 0x00000000
@ -736,6 +735,7 @@
#define CS35L41_REVID_B2 0xB2 #define CS35L41_REVID_B2 0xB2
#define CS35L41_HALO_CORE_RESET 0x00000200 #define CS35L41_HALO_CORE_RESET 0x00000200
#define CS35L41_SOFTWARE_RESET 0x5A000000
#define CS35L41_FS1_WINDOW_MASK 0x000007FF #define CS35L41_FS1_WINDOW_MASK 0x000007FF
#define CS35L41_FS2_WINDOW_MASK 0x00FFF800 #define CS35L41_FS2_WINDOW_MASK 0x00FFF800
@ -816,6 +816,8 @@ struct cs35l41_otp_map_element_t {
}; };
enum cs35l41_cspl_mbox_status { 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_RUNNING = 0,
CSPL_MBOX_STS_PAUSED = 1, CSPL_MBOX_STS_PAUSED = 1,
CSPL_MBOX_STS_RDY_FOR_REINIT = 2, 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, int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
struct cs35l41_hw_cfg *hw_cfg); struct cs35l41_hw_cfg *hw_cfg);
bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type); 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 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 */ #endif /* __CS35L41_H */

View File

@ -242,9 +242,8 @@
#define CS35L56_CONTROL_PORT_READY_US 2200 #define CS35L56_CONTROL_PORT_READY_US 2200
#define CS35L56_HALO_STATE_POLL_US 1000 #define CS35L56_HALO_STATE_POLL_US 1000
#define CS35L56_HALO_STATE_TIMEOUT_US 50000 #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_RESET_PULSE_MIN_US 1100
#define CS35L56_WAKE_HOLD_TIME_US 1000
#define CS35L56_SDW1_PLAYBACK_PORT 1 #define CS35L56_SDW1_PLAYBACK_PORT 1
#define CS35L56_SDW1_CAPTURE_PORT 3 #define CS35L56_SDW1_CAPTURE_PORT 3

View File

@ -9,27 +9,27 @@
#include <sound/simple_card_utils.h> #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 device_node *lnk,
struct link_info *li); struct link_info *li);
struct graph2_custom_hooks { struct graph2_custom_hooks {
int (*hook_pre)(struct asoc_simple_priv *priv); int (*hook_pre)(struct simple_util_priv *priv);
int (*hook_post)(struct asoc_simple_priv *priv); int (*hook_post)(struct simple_util_priv *priv);
GRAPH2_CUSTOM custom_normal; GRAPH2_CUSTOM custom_normal;
GRAPH2_CUSTOM custom_dpcm; GRAPH2_CUSTOM custom_dpcm;
GRAPH2_CUSTOM custom_c2c; GRAPH2_CUSTOM custom_c2c;
}; };
int audio_graph_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 asoc_simple_priv *priv, struct device *dev, int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev,
struct graph2_custom_hooks *hooks); 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); 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); 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); struct device_node *lnk, struct link_info *li);
#endif /* __GRAPH_CARD_H */ #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_BDLPL 0x18
#define AZX_REG_SD_BDLPU 0x1c #define AZX_REG_SD_BDLPU 0x1c
#define AZX_SD_FIFOSIZE_MASK GENMASK(15, 0)
/* GTS registers */ /* GTS registers */
#define AZX_REG_LLCH 0x14 #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, struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus,
int dir, int stream_tag); 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); 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_setup_periods(struct hdac_stream *azx_dev);
int snd_hdac_stream_set_params(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) \ #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, \ read_poll_timeout_atomic(snd_hdac_reg_readb, val, cond, delay_us, timeout_us, \
false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) 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) \ #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, \ read_poll_timeout_atomic(snd_hdac_reg_readl, val, cond, delay_us, timeout_us, \
false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) 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_locked:1;
bool link_prepared; bool link_prepared;
int (*host_setup)(struct hdac_stream *, bool);
struct snd_pcm_substream *link_substream; 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_clear(struct hdac_ext_stream *hext_stream);
void snd_hdac_ext_stream_reset(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_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_ext_link {
struct hdac_bus *bus; struct hdac_bus *bus;

View File

@ -9,14 +9,10 @@
/** /**
* struct max9768_pdata - optional platform specific MAX9768 configuration * 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 * @flags: configuration flags, e.g. set classic PWM mode (check datasheet
* regarding "filterless modulation" which is default). * regarding "filterless modulation" which is default).
*/ */
struct max9768_pdata { struct max9768_pdata {
int shdn_gpio;
int mute_gpio;
unsigned flags; unsigned flags;
#define MAX9768_FLAG_CLASSIC_PWM (1 << 0) #define MAX9768_FLAG_CLASSIC_PWM (1 << 0)
}; };

View File

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

View File

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

View File

@ -11,18 +11,18 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <sound/soc.h> #include <sound/soc.h>
#define asoc_simple_init_hp(card, sjack, prefix) \ #define simple_util_init_hp(card, sjack, prefix) \
asoc_simple_init_jack(card, sjack, 1, prefix, NULL) simple_util_init_jack(card, sjack, 1, prefix, NULL)
#define asoc_simple_init_mic(card, sjack, prefix) \ #define simple_util_init_mic(card, sjack, prefix) \
asoc_simple_init_jack(card, sjack, 0, prefix, NULL) 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 sample_bits;
u8 slot_count; u8 slot_count;
u16 slot_width; u16 slot_width;
}; };
struct asoc_simple_dai { struct simple_util_dai {
const char *name; const char *name;
unsigned int sysclk; unsigned int sysclk;
int clk_direction; int clk_direction;
@ -32,17 +32,17 @@ struct asoc_simple_dai {
unsigned int rx_slot_mask; unsigned int rx_slot_mask;
struct clk *clk; struct clk *clk;
bool clk_fixed; 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; int n_tdm_widths;
}; };
struct asoc_simple_data { struct simple_util_data {
u32 convert_rate; u32 convert_rate;
u32 convert_channels; u32 convert_channels;
const char *convert_sample_format; const char *convert_sample_format;
}; };
struct asoc_simple_jack { struct simple_util_jack {
struct snd_soc_jack jack; struct snd_soc_jack jack;
struct snd_soc_jack_pin pin; struct snd_soc_jack_pin pin;
struct snd_soc_jack_gpio gpio; struct snd_soc_jack_gpio gpio;
@ -54,21 +54,21 @@ struct prop_nums {
int platforms; int platforms;
}; };
struct asoc_simple_priv { struct simple_util_priv {
struct snd_soc_card snd_card; struct snd_soc_card snd_card;
struct simple_dai_props { struct simple_dai_props {
struct asoc_simple_dai *cpu_dai; struct simple_util_dai *cpu_dai;
struct asoc_simple_dai *codec_dai; struct simple_util_dai *codec_dai;
struct asoc_simple_data adata; struct simple_util_data adata;
struct snd_soc_codec_conf *codec_conf; struct snd_soc_codec_conf *codec_conf;
struct prop_nums num; struct prop_nums num;
unsigned int mclk_fs; unsigned int mclk_fs;
} *dai_props; } *dai_props;
struct asoc_simple_jack hp_jack; struct simple_util_jack hp_jack;
struct asoc_simple_jack mic_jack; struct simple_util_jack mic_jack;
struct snd_soc_jack *aux_jacks; struct snd_soc_jack *aux_jacks;
struct snd_soc_dai_link *dai_link; 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_dai_link_component *dlcs;
struct snd_soc_codec_conf *codec_conf; struct snd_soc_codec_conf *codec_conf;
struct gpio_desc *pa_gpio; struct gpio_desc *pa_gpio;
@ -130,75 +130,75 @@ struct link_info {
struct prop_nums num[SNDRV_MAX_LINKS]; 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 *node,
struct device_node *codec, struct device_node *codec,
char *prefix, char *prefix,
unsigned int *retfmt); unsigned int *retfmt);
int asoc_simple_parse_tdm_width_map(struct device *dev, struct device_node *np, int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np,
struct asoc_simple_dai *dai); struct simple_util_dai *dai);
__printf(3, 4) __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, struct snd_soc_dai_link *dai_link,
const char *fmt, ...); 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); char *prefix);
int asoc_simple_parse_clk(struct device *dev, int simple_util_parse_clk(struct device *dev,
struct device_node *node, struct device_node *node,
struct asoc_simple_dai *simple_dai, struct simple_util_dai *simple_dai,
struct snd_soc_dai_link_component *dlc); struct snd_soc_dai_link_component *dlc);
int asoc_simple_startup(struct snd_pcm_substream *substream); int simple_util_startup(struct snd_pcm_substream *substream);
void asoc_simple_shutdown(struct snd_pcm_substream *substream); void simple_util_shutdown(struct snd_pcm_substream *substream);
int asoc_simple_hw_params(struct snd_pcm_substream *substream, int simple_util_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params); struct snd_pcm_hw_params *params);
int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd); int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd);
int asoc_simple_be_hw_params_fixup(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); 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, \ snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \
&(dai)->rx_slot_mask, \ &(dai)->rx_slot_mask, \
&(dai)->slots, \ &(dai)->slots, \
&(dai)->slot_width); &(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); 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); 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, void simple_util_parse_convert(struct device_node *np, char *prefix,
struct asoc_simple_data *data); struct simple_util_data *data);
bool asoc_simple_is_convert_required(const struct asoc_simple_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); char *prefix);
int asoc_simple_parse_widgets(struct snd_soc_card *card, int simple_util_parse_widgets(struct snd_soc_card *card,
char *prefix); 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); char *prefix);
int asoc_simple_init_jack(struct snd_soc_card *card, int simple_util_init_jack(struct snd_soc_card *card,
struct asoc_simple_jack *sjack, struct simple_util_jack *sjack,
int is_hp, char *prefix, char *pin); 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); 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); struct link_info *li);
int asoc_simple_remove(struct platform_device *pdev); int simple_util_remove(struct platform_device *pdev);
int asoc_graph_card_probe(struct snd_soc_card *card); int graph_util_card_probe(struct snd_soc_card *card);
int asoc_graph_is_ports0(struct device_node *port); int graph_util_is_ports0(struct device_node *port);
int asoc_graph_parse_dai(struct device *dev, struct device_node *ep, int graph_util_parse_dai(struct device *dev, struct device_node *ep,
struct snd_soc_dai_link_component *dlc, int *is_single_link); struct snd_soc_dai_link_component *dlc, int *is_single_link);
#ifdef DEBUG #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, char *name,
struct asoc_simple_dai *dai) struct simple_util_dai *dai)
{ {
struct device *dev = simple_priv_to_dev(priv); 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"); 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 snd_soc_card *card = simple_priv_to_card(priv);
struct device *dev = simple_priv_to_dev(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++) { for (i = 0; i < card->num_links; i++) {
struct simple_dai_props *props = simple_priv_to_props(priv, 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 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; struct snd_soc_codec_conf *cnf;
int j; 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); dev_dbg(dev, "cpu num = %d\n", link->num_cpus);
for_each_prop_dai_cpu(props, j, dai) 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); dev_dbg(dev, "codec num = %d\n", link->num_codecs);
for_each_prop_dai_codec(props, j, dai) 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) if (link->name)
dev_dbg(dev, "dai name = %s\n", 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 #else
#define asoc_simple_debug_info(priv) #define simple_util_debug_info(priv)
#endif /* DEBUG */ #endif /* DEBUG */
#endif /* __SIMPLE_CARD_UTILS_H */ #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_rpl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_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_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_cnl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_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_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_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_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 * 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 * @i2s_link_mask: I2S/TDM links enabled on the board
* @num_dai_drivers: number of elements in @dai_drivers * @num_dai_drivers: number of elements in @dai_drivers
* @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode * @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 { struct snd_soc_acpi_mach_params {
u32 acpi_ipc_irq_index; u32 acpi_ipc_irq_index;
@ -80,6 +84,9 @@ struct snd_soc_acpi_mach_params {
u32 i2s_link_mask; u32 i2s_link_mask;
u32 num_dai_drivers; u32 num_dai_drivers;
struct snd_soc_dai_driver *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, void snd_soc_card_remove_dai_link(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link); 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 */ /* device driver data */
static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
void *data) 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; struct snd_soc_pcm_runtime *rtd;
for_each_card_rtds(card, rtd) { for_each_card_rtds(card, rtd) {
if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name)) if (!strcmp(snd_soc_rtd_to_codec(rtd, 0)->name, dai_name))
return asoc_rtd_to_codec(rtd, 0); return snd_soc_rtd_to_codec(rtd, 0);
} }
return NULL; return NULL;

View File

@ -718,7 +718,7 @@ struct snd_soc_dapm_context {
/* A list of widgets associated with an object, typically a snd_kcontrol */ /* A list of widgets associated with an object, typically a snd_kcontrol */
struct snd_soc_dapm_widget_list { struct snd_soc_dapm_widget_list {
int num_widgets; 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) \ #define for_each_dapm_widgets(list, i, widget) \

View File

@ -10,6 +10,7 @@
#ifndef __LINUX_SND_SOC_H #ifndef __LINUX_SND_SOC_H
#define __LINUX_SND_SOC_H #define __LINUX_SND_SOC_H
#include <linux/args.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
@ -775,36 +776,36 @@ struct snd_soc_dai_link {
}; };
static inline struct snd_soc_dai_link_component* 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]; return &(link)->cpus[n];
} }
static inline struct snd_soc_dai_link_component* 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]; return &(link)->codecs[n];
} }
static inline struct snd_soc_dai_link_component* 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]; return &(link)->platforms[n];
} }
#define for_each_link_codecs(link, i, codec) \ #define for_each_link_codecs(link, i, codec) \
for ((i) = 0; \ for ((i) = 0; \
((i) < link->num_codecs) && \ ((i) < link->num_codecs) && \
((codec) = asoc_link_to_codec(link, i)); \ ((codec) = snd_soc_link_to_codec(link, i)); \
(i)++) (i)++)
#define for_each_link_platforms(link, i, platform) \ #define for_each_link_platforms(link, i, platform) \
for ((i) = 0; \ for ((i) = 0; \
((i) < link->num_platforms) && \ ((i) < link->num_platforms) && \
((platform) = asoc_link_to_platform(link, i)); \ ((platform) = snd_soc_link_to_platform(link, i)); \
(i)++) (i)++)
#define for_each_link_cpus(link, i, cpu) \ #define for_each_link_cpus(link, i, cpu) \
for ((i) = 0; \ for ((i) = 0; \
((i) < link->num_cpus) && \ ((i) < link->num_cpus) && \
((cpu) = asoc_link_to_cpu(link, i)); \ ((cpu) = snd_soc_link_to_cpu(link, i)); \
(i)++) (i)++)
/* /*
@ -870,12 +871,8 @@ asoc_link_to_platform(struct snd_soc_dai_link *link, int n) {
.platforms = platform, \ .platforms = platform, \
.num_platforms = ARRAY_SIZE(platform) .num_platforms = ARRAY_SIZE(platform)
#define SND_SOC_DAILINK_REGx(_1, _2, _3, func, ...) func
#define SND_SOC_DAILINK_REG(...) \ #define SND_SOC_DAILINK_REG(...) \
SND_SOC_DAILINK_REGx(__VA_ARGS__, \ CONCATENATE(SND_SOC_DAILINK_REG, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
SND_SOC_DAILINK_REG3, \
SND_SOC_DAILINK_REG2, \
SND_SOC_DAILINK_REG1)(__VA_ARGS__)
#define SND_SOC_DAILINK_DEF(name, def...) \ #define SND_SOC_DAILINK_DEF(name, def...) \
static struct snd_soc_dai_link_component 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", } #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 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 { struct snd_soc_codec_conf {
@ -932,6 +929,17 @@ struct snd_soc_card {
#ifdef CONFIG_DMI #ifdef CONFIG_DMI
char dmi_longname[80]; char dmi_longname[80];
#endif /* CONFIG_DMI */ #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]; char topology_shortname[32];
struct device *dev; struct device *dev;
@ -1102,8 +1110,8 @@ struct snd_soc_pcm_runtime {
* dais = cpu_dai + codec_dai * dais = cpu_dai + codec_dai
* see * see
* soc_new_pcm_runtime() * soc_new_pcm_runtime()
* asoc_rtd_to_cpu() * snd_soc_rtd_to_cpu()
* asoc_rtd_to_codec() * snd_soc_rtd_to_codec()
*/ */
struct snd_soc_dai **dais; struct snd_soc_dai **dais;
@ -1131,10 +1139,11 @@ struct snd_soc_pcm_runtime {
int num_components; int num_components;
struct snd_soc_component *components[]; /* CPU/Codec/Platform */ struct snd_soc_component *components[]; /* CPU/Codec/Platform */
}; };
/* see soc_new_pcm_runtime() */ /* see soc_new_pcm_runtime() */
#define asoc_rtd_to_cpu(rtd, n) (rtd)->dais[n] #define snd_soc_rtd_to_cpu(rtd, n) (rtd)->dais[n]
#define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus] #define snd_soc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus]
#define asoc_substream_to_rtd(substream) \ #define snd_soc_substream_to_rtd(substream) \
(struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream) (struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream)
#define for_each_rtd_components(rtd, i, component) \ #define for_each_rtd_components(rtd, i, component) \
@ -1143,11 +1152,11 @@ struct snd_soc_pcm_runtime {
(i)++) (i)++)
#define for_each_rtd_cpu_dais(rtd, i, dai) \ #define for_each_rtd_cpu_dais(rtd, i, dai) \
for ((i) = 0; \ 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)++) (i)++)
#define for_each_rtd_codec_dais(rtd, i, dai) \ #define for_each_rtd_codec_dais(rtd, i, dai) \
for ((i) = 0; \ 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)++) (i)++)
#define for_each_rtd_dais(rtd, i, dai) \ #define for_each_rtd_dais(rtd, i, dai) \
for ((i) = 0; \ for ((i) = 0; \

View File

@ -52,8 +52,8 @@ enum sof_dsp_power_states {
/* Definitions for multiple IPCs */ /* Definitions for multiple IPCs */
enum sof_ipc_type { enum sof_ipc_type {
SOF_IPC, SOF_IPC_TYPE_3,
SOF_INTEL_IPC4, SOF_IPC_TYPE_4,
SOF_IPC_TYPE_COUNT SOF_IPC_TYPE_COUNT
}; };
@ -64,6 +64,14 @@ struct snd_sof_pdata {
const char *name; const char *name;
const char *platform; 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; struct device *dev;
/* /*

View File

@ -106,12 +106,19 @@ enum sof_ipc4_global_msg {
SOF_IPC4_GLB_SAVE_PIPELINE, SOF_IPC4_GLB_SAVE_PIPELINE,
SOF_IPC4_GLB_RESTORE_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, 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,
SOF_IPC4_GLB_INTERNAL_MESSAGE = 26,
/* Notification (FW to SW driver) */ /* Notification (FW to SW driver) */
SOF_IPC4_GLB_NOTIFICATION, SOF_IPC4_GLB_NOTIFICATION,
@ -508,6 +515,23 @@ struct sof_ipc4_notify_resource_data {
uint32_t data[6]; uint32_t data[6];
} __packed __aligned(4); } __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 #endif

View File

@ -77,6 +77,11 @@ struct tasdev_blk {
unsigned int nr_cmds; unsigned int nr_cmds;
unsigned int blk_size; unsigned int blk_size;
unsigned int nr_subblocks; 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; unsigned char *data;
}; };

View File

@ -8,34 +8,6 @@
* Copyright (c) by Paul Barton-Davis <pbd@op.net> * 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 #ifndef NUM_MIDIKEYS
#define NUM_MIDIKEYS 128 #define NUM_MIDIKEYS 128
#endif /* NUM_MIDIKEYS */ #endif /* NUM_MIDIKEYS */
@ -44,29 +16,6 @@
#define NUM_MIDICHANNELS 16 #define NUM_MIDICHANNELS 16
#endif /* NUM_MIDICHANNELS */ #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. /* Pseudo-commands not part of the WaveFront command set.
These are used for various driver controls and direct These are used for various driver controls and direct
hardware control. hardware control.
@ -468,7 +417,7 @@ typedef struct wf_alias {
*/ */
u8 sixteen_bit_padding; u8 sixteen_bit_padding;
} __attribute__((packed)) wavefront_alias; } __packed wavefront_alias;
typedef struct wf_drum { typedef struct wf_drum {
u8 PatchNumber; u8 PatchNumber;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
#ifndef __SOUNDBUS_H #ifndef __SOUNDBUS_H
#define __SOUNDBUS_H #define __SOUNDBUS_H
#include <linux/of_device.h> #include <linux/platform_device.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <linux/list.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; struct dma_slave_config config;
int ret; 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) if (!dma_params)
return 0; return 0;
@ -47,7 +47,7 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
return ret; return ret;
snd_dmaengine_pcm_set_config_from_dai_data(substream, 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); &config);
ret = dmaengine_slave_config(chan, &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; 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) if (!dma_params)
return 0; return 0;
@ -111,7 +111,7 @@ int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
return ret; return ret;
return snd_dmaengine_pcm_open( 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)); dma_params->chan_name));
} }
EXPORT_SYMBOL(pxa2xx_pcm_open); EXPORT_SYMBOL(pxa2xx_pcm_open);

View File

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

View File

@ -3089,7 +3089,7 @@ struct snd_pcm_mmap_status32 {
snd_pcm_state_t suspended_state; snd_pcm_state_t suspended_state;
s32 audio_tstamp_sec; s32 audio_tstamp_sec;
s32 audio_tstamp_nsec; s32 audio_tstamp_nsec;
} __attribute__((packed)); } __packed;
struct snd_pcm_mmap_control32 { struct snd_pcm_mmap_control32 {
u32 appl_ptr; u32 appl_ptr;
@ -3106,7 +3106,7 @@ struct snd_pcm_sync_ptr32 {
struct snd_pcm_mmap_control32 control; struct snd_pcm_mmap_control32 control;
unsigned char reserved[64]; unsigned char reserved[64];
} c; } c;
} __attribute__((packed)); } __packed;
/* recalcuate the boundary within 32bit */ /* recalcuate the boundary within 32bit */
static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime) 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 no_active_sensing; /* avoid bit-field */
unsigned int mode; unsigned int mode;
unsigned char reserved[12]; unsigned char reserved[12];
} __attribute__((packed)); } __packed;
static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile, static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
struct snd_rawmidi_params32 __user *src) struct snd_rawmidi_params32 __user *src)
@ -51,7 +51,7 @@ struct compat_snd_rawmidi_status64 {
u32 avail; u32 avail;
u32 xruns; u32 xruns;
unsigned char reserved[16]; unsigned char reserved[16];
} __attribute__((packed)); } __packed;
static int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile, static int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile,
struct compat_snd_rawmidi_status64 __user *src) struct compat_snd_rawmidi_status64 __user *src)

View File

@ -119,11 +119,13 @@ struct loopback_setup {
unsigned int rate_shift; unsigned int rate_shift;
snd_pcm_format_t format; snd_pcm_format_t format;
unsigned int rate; unsigned int rate;
snd_pcm_access_t access;
unsigned int channels; unsigned int channels;
struct snd_ctl_elem_id active_id; struct snd_ctl_elem_id active_id;
struct snd_ctl_elem_id format_id; struct snd_ctl_elem_id format_id;
struct snd_ctl_elem_id rate_id; struct snd_ctl_elem_id rate_id;
struct snd_ctl_elem_id channels_id; struct snd_ctl_elem_id channels_id;
struct snd_ctl_elem_id access_id;
}; };
struct loopback { struct loopback {
@ -158,6 +160,9 @@ struct loopback_pcm {
unsigned long last_jiffies; unsigned long last_jiffies;
/* If jiffies timer is used */ /* If jiffies timer is used */
struct timer_list timer; 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]; static struct platform_device *devices[SNDRV_CARDS];
@ -335,7 +340,8 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
substream->runtime; substream->runtime;
check = runtime->format != cruntime->format || check = runtime->format != cruntime->format ||
runtime->rate != cruntime->rate || runtime->rate != cruntime->rate ||
runtime->channels != cruntime->channels; runtime->channels != cruntime->channels ||
runtime->access != cruntime->access;
if (!check) if (!check)
return 0; return 0;
if (stream == SNDRV_PCM_STREAM_CAPTURE) { 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_id);
setup->channels = runtime->channels; 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; return 0;
} }
@ -472,6 +483,7 @@ static int loopback_prepare(struct snd_pcm_substream *substream)
dpcm->buf_pos = 0; dpcm->buf_pos = 0;
dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size); 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) { if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
/* clear capture buffer */ /* clear capture buffer */
dpcm->silent_size = dpcm->pcm_buffer_size; 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, static void copy_play_buf(struct loopback_pcm *play,
struct loopback_pcm *capt, struct loopback_pcm *capt,
unsigned int bytes) unsigned int bytes)
@ -556,7 +584,11 @@ static void copy_play_buf(struct loopback_pcm *play,
size = play->pcm_buffer_size - src_off; size = play->pcm_buffer_size - src_off;
if (dst_off + size > capt->pcm_buffer_size) if (dst_off + size > capt->pcm_buffer_size)
size = capt->pcm_buffer_size - dst_off; 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; capt->silent_size = 0;
bytes -= size; bytes -= size;
if (!bytes) if (!bytes)
@ -878,7 +910,7 @@ static const struct snd_pcm_hardware loopback_pcm_hardware =
{ {
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | 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 | .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_LE | SNDRV_PCM_FMTBIT_S24_BE |
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | 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; 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[] = { static const struct snd_kcontrol_new loopback_controls[] = {
{ {
.iface = SNDRV_CTL_ELEM_IFACE_PCM, .iface = SNDRV_CTL_ELEM_IFACE_PCM,
@ -1541,7 +1597,15 @@ static const struct snd_kcontrol_new loopback_controls[] = {
.name = "PCM Slave Channels", .name = "PCM Slave Channels",
.info = loopback_channels_info, .info = loopback_channels_info,
.get = loopback_channels_get .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) 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->notify = notify;
setup->rate_shift = NO_PITCH; setup->rate_shift = NO_PITCH;
setup->format = SNDRV_PCM_FORMAT_S16_LE; setup->format = SNDRV_PCM_FORMAT_S16_LE;
setup->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
setup->rate = 48000; setup->rate = 48000;
setup->channels = 2; setup->channels = 2;
for (idx = 0; idx < ARRAY_SIZE(loopback_controls); 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: case CHANNELS_IDX:
setup->channels_id = kctl->id; setup->channels_id = kctl->id;
break; break;
case ACCESS_IDX:
setup->access_id = kctl->id;
break;
default: default:
break; break;
} }

View File

@ -10,12 +10,47 @@
*/ */
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/hda_register.h> #include <sound/hda_register.h>
#include <sound/hdaudio_ext.h> #include <sound/hdaudio_ext.h>
#include <sound/compress_driver.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) * snd_hdac_ext_stream_init - initialize each stream (aka device)
* @bus: HD-audio core bus * @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 snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
int num_stream, int dir) 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 stream_tag = 0;
int i, tag, idx = start_idx; 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++) { for (i = 0; i < num_stream; i++) {
struct hdac_ext_stream *hext_stream = struct hdac_ext_stream *hext_stream =
kzalloc(sizeof(*hext_stream), GFP_KERNEL); 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; tag = ++stream_tag;
snd_hdac_ext_stream_init(bus, hext_stream, idx, dir, tag); snd_hdac_ext_stream_init(bus, hext_stream, idx, dir, tag);
idx++; idx++;
hext_stream->host_setup = setup_op;
} }
return 0; return 0;

View File

@ -10,6 +10,12 @@
#include <sound/hdaudio.h> #include <sound/hdaudio.h>
#include <sound/hda_i915.h> #include <sound/hda_i915.h>
#include <sound/hda_register.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 * 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); hdac_pci = to_pci_dev(bus->dev);
i915_pci = to_pci_dev(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 && subcomponent == I915_COMPONENT_AUDIO &&
connectivity_check(i915_pci, hdac_pci)) connectivity_check(i915_pci, hdac_pci))
return 1; return 1;
@ -122,6 +129,9 @@ static int i915_gfx_present(struct pci_dev *hdac_pci)
{ {
struct pci_dev *display_dev = NULL; struct pci_dev *display_dev = NULL;
if (!gpu_bind || (gpu_bind < 0 && video_firmware_drivers_only()))
return false;
for_each_pci_dev(display_dev) { for_each_pci_dev(display_dev) {
if (display_dev->vendor == PCI_VENDOR_ID_INTEL && if (display_dev->vendor == PCI_VENDOR_ID_INTEL &&
(display_dev->class >> 16) == PCI_BASE_CLASS_DISPLAY && (display_dev->class >> 16) == PCI_BASE_CLASS_DISPLAY &&
@ -163,17 +173,9 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
if (!acomp) if (!acomp)
return -ENODEV; return -ENODEV;
if (!acomp->ops) { 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); snd_hdac_acomp_exit(bus);
return -ENODEV; return dev_err_probe(bus->dev, -EPROBE_DEFER,
"couldn't bind with audio component\n");
} }
return 0; 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 * snd_hdac_stream_setup - set up the SD for streaming
* @azx_dev: HD-audio core stream to set up * @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 hdac_bus *bus = azx_dev->bus;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
unsigned int val; unsigned int val;
u16 reg;
int ret;
if (azx_dev->substream) if (azx_dev->substream)
runtime = azx_dev->substream->runtime; 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 */ /* set the interrupt enable bits in the descriptor control register */
snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK); 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, /* when LPIB delay correction gives a small negative value,
* we ignore it; currently set the threshold statically to * 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; struct hdac_stream *res = NULL;
/* make a non-zero unique key for the substream */ /* make a non-zero unique key for the substream */
int key = (substream->pcm->device << 16) | (substream->number << 2) | int key = (substream->number << 2) | (substream->stream + 1);
(substream->stream + 1);
if (substream->pcm)
key |= (substream->pcm->device << 16);
spin_lock_irq(&bus->reg_lock); spin_lock_irq(&bus->reg_lock);
list_for_each_entry(azx_dev, &bus->stream_list, list) { 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) if (err < 0)
goto error; goto error;
snd_hdac_stream_setup(azx_dev); snd_hdac_stream_setup(azx_dev, true);
snd_hdac_dsp_unlock(azx_dev); snd_hdac_dsp_unlock(azx_dev);
return azx_dev->stream_tag; return azx_dev->stream_tag;

View File

@ -1383,7 +1383,7 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,
u32 dma_start_1; u32 dma_start_1;
u32 dma_start_2; u32 dma_start_2;
u32 dma_lengths; u32 dma_lengths;
} __attribute__((packed)) setup_io; } __packed setup_io;
area_length = buffer_bytes/2; 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 start up. The "patch" file can be specified via patch module
option, such as patch=hda-init. 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 config SND_HDA_SCODEC_CS35L41
tristate tristate
select SND_HDA_GENERIC select SND_HDA_GENERIC
@ -144,6 +160,7 @@ config SND_HDA_SCODEC_CS35L56_I2C
select SND_HDA_GENERIC select SND_HDA_GENERIC
select SND_SOC_CS35L56_SHARED select SND_SOC_CS35L56_SHARED
select SND_HDA_SCODEC_CS35L56 select SND_HDA_SCODEC_CS35L56
select SND_HDA_CIRRUS_SCODEC
select SND_HDA_CS_DSP_CONTROLS select SND_HDA_CS_DSP_CONTROLS
help help
Say Y or M here to include CS35L56 amplifier support with 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_HDA_GENERIC
select SND_SOC_CS35L56_SHARED select SND_SOC_CS35L56_SHARED
select SND_HDA_SCODEC_CS35L56 select SND_HDA_SCODEC_CS35L56
select SND_HDA_CIRRUS_SCODEC
select SND_HDA_CS_DSP_CONTROLS select SND_HDA_CS_DSP_CONTROLS
help help
Say Y or M here to include CS35L56 amplifier support with 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 snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
# side codecs # 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-objs := cs35l41_hda.o cs35l41_hda_property.o
snd-hda-scodec-cs35l41-i2c-objs := cs35l41_hda_i2c.o snd-hda-scodec-cs35l41-i2c-objs := cs35l41_hda_i2c.o
snd-hda-scodec-cs35l41-spi-objs := cs35l41_hda_spi.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 obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
# side codecs # 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) += snd-hda-scodec-cs35l41.o
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.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 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_AMBIENT_DSP_CTL_NAME "CAL_AMBIENT"
#define CAL_DSP_CTL_TYPE 5 #define CAL_DSP_CTL_TYPE 5
#define CAL_DSP_CTL_ALG 205 #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; static bool firmware_autostart = 1;
module_param(firmware_autostart, bool, 0444); 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) static void cs35l41_hda_play_done(struct device *dev)
{ {
struct cs35l41_hda *cs35l41 = dev_get_drvdata(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"); 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); cs35l41->firmware_running);
if (cs35l41->firmware_running) { cs35l41_mute(dev, false);
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_pause_start(struct device *dev) 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"); dev_dbg(dev, "Pause (Start)\n");
regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); cs35l41_mute(dev, true);
cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0, NULL, cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0,
cs35l41->firmware_running); cs35l41->firmware_running);
} }
@ -708,43 +730,46 @@ static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsi
rx_slot); 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) static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)
{ {
int ret = 0;
mutex_lock(&cs35l41->fw_mutex); mutex_lock(&cs35l41->fw_mutex);
if (cs35l41->firmware_running) { if (cs35l41->firmware_running) {
cs35l41->cs_dsp.running = false;
regcache_cache_only(cs35l41->regmap, false); cs35l41->cs_dsp.booted = false;
cs35l41->firmware_running = 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);
} }
err:
regcache_cache_only(cs35l41->regmap, true);
regcache_mark_dirty(cs35l41->regmap); regcache_mark_dirty(cs35l41->regmap);
mutex_unlock(&cs35l41->fw_mutex); mutex_unlock(&cs35l41->fw_mutex);
return ret; return 0;
} }
static int cs35l41_system_suspend_prep(struct device *dev) 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 */ /* Shutdown DSP before system suspend */
ret = cs35l41_ready_for_reset(cs35l41); ret = cs35l41_ready_for_reset(cs35l41);
if (ret) if (ret)
dev_err(dev, "System Suspend Failed, not ready for Reset: %d\n", ret); dev_err(dev, "System Suspend Failed, not ready for Reset: %d\n", ret);
/* if (cs35l41->reset_gpio) {
* Reset GPIO may be shared, so cannot reset here. dev_info(cs35l41->dev, "Asserting Reset\n");
* However beyond this point, amps may be powered down. gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
*/ usleep_range(2000, 2100);
}
dev_dbg(cs35l41->dev, "System Suspended\n");
return ret; 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) static int cs35l41_system_resume(struct device *dev)
{ {
struct cs35l41_hda *cs35l41 = dev_get_drvdata(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) { if (cs35l41->reset_gpio) {
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
usleep_range(2000, 2100); usleep_range(2000, 2100);
gpiod_set_value_cansleep(cs35l41->reset_gpio, 1); gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
} }
usleep_range(2000, 2100); 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); ret = pm_runtime_force_resume(dev);
if (ret) { if (ret) {
dev_err(dev, "System Resume Failed: Unable to runtime resume: %d\n", 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) static int cs35l41_runtime_resume(struct device *dev)
{ {
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
unsigned int regid, reg_revid;
int ret = 0; int ret = 0;
dev_dbg(cs35l41->dev, "Runtime Resume\n"); 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 */ /* Test key needs to be unlocked to allow the OTP settings to re-apply */
cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap); cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
ret = regcache_sync(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) if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg); cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
dev_dbg(cs35l41->dev, "CS35L41 Resumed (%x), Revision: %02X\n", regid, reg_revid);
err: err:
mutex_unlock(&cs35l41->fw_mutex); mutex_unlock(&cs35l41->fw_mutex);
@ -923,6 +994,7 @@ err:
static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41) static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
{ {
unsigned int fw_status;
__be32 halo_sts; __be32 halo_sts;
int ret; int ret;
@ -956,6 +1028,23 @@ static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
goto clean_dsp; 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);
goto clean_dsp;
}
ret = cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, CSPL_MBOX_CMD_PAUSE); ret = cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, CSPL_MBOX_CMD_PAUSE);
if (ret) { if (ret) {
dev_err(cs35l41->dev, "Error waiting for DSP to pause: %u\n", ret); dev_err(cs35l41->dev, "Error waiting for DSP to pause: %u\n", ret);
@ -993,6 +1082,15 @@ static int cs35l41_fw_load_ctl_get(struct snd_kcontrol *kcontrol,
return 0; 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) static void cs35l41_fw_load_work(struct work_struct *work)
{ {
struct cs35l41_hda *cs35l41 = container_of(work, struct cs35l41_hda, fw_load_work); struct cs35l41_hda *cs35l41 = container_of(work, struct cs35l41_hda, fw_load_work);
@ -1076,6 +1174,7 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
{ {
char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
char fw_load_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 = { struct snd_kcontrol_new fw_type_ctl = {
.name = fw_type_ctl_name, .name = fw_type_ctl_name,
.iface = SNDRV_CTL_ELEM_IFACE_CARD, .iface = SNDRV_CTL_ELEM_IFACE_CARD,
@ -1090,12 +1189,21 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
.get = cs35l41_fw_load_ctl_get, .get = cs35l41_fw_load_ctl_get,
.put = cs35l41_fw_load_ctl_put, .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; int ret;
scnprintf(fw_type_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Type", scnprintf(fw_type_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Type",
cs35l41->amp_name); cs35l41->amp_name);
scnprintf(fw_load_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Load", scnprintf(fw_load_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Load",
cs35l41->amp_name); 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)); ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41));
if (ret) { if (ret) {
@ -1113,9 +1221,65 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name); 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; 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) static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data)
{ {
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
@ -1157,6 +1321,14 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
comps->playback_hook = cs35l41_hda_playback_hook; comps->playback_hook = cs35l41_hda_playback_hook;
comps->pre_playback_hook = cs35l41_hda_pre_playback_hook; comps->pre_playback_hook = cs35l41_hda_pre_playback_hook;
comps->post_playback_hook = cs35l41_hda_post_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); mutex_unlock(&cs35l41->fw_mutex);
@ -1430,8 +1602,8 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
return -ENODEV; return -ENODEV;
} }
cs35l41->dacpi = adev;
physdev = get_device(acpi_get_first_physical_node(adev)); physdev = get_device(acpi_get_first_physical_node(adev));
acpi_dev_put(adev);
sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
if (IS_ERR(sub)) if (IS_ERR(sub))
@ -1541,6 +1713,7 @@ err:
hw_cfg->valid = false; hw_cfg->valid = false;
hw_cfg->gpio1.valid = false; hw_cfg->gpio1.valid = false;
hw_cfg->gpio2.valid = false; hw_cfg->gpio2.valid = false;
acpi_dev_put(cs35l41->dacpi);
put_physdev: put_physdev:
put_device(physdev); put_device(physdev);
@ -1550,7 +1723,7 @@ put_physdev:
int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq, int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
struct regmap *regmap) struct regmap *regmap)
{ {
unsigned int int_sts, regid, reg_revid, mtl_revid, chipid, int_status; unsigned int regid, reg_revid;
struct cs35l41_hda *cs35l41; struct cs35l41_hda *cs35l41;
int ret; int ret;
@ -1584,47 +1757,22 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
} }
} }
if (cs35l41->reset_gpio) { if (cs35l41->reset_gpio) {
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
usleep_range(2000, 2100); usleep_range(2000, 2100);
gpiod_set_value_cansleep(cs35l41->reset_gpio, 1); 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); usleep_range(2000, 2100);
ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status, ret = cs35l41_wait_boot_done(cs35l41);
int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000); if (ret)
if (ret) {
dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE: %d\n", ret);
goto err; goto err;
}
ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts); ret = cs35l41_verify_id(cs35l41, &regid, &reg_revid);
if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) { if (ret)
dev_err(cs35l41->dev, "OTP Boot status %x error: %d\n",
int_sts & CS35L41_OTP_BOOT_ERR, ret);
ret = -EIO;
goto err; 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); ret = cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
if (ret) if (ret)
@ -1636,7 +1784,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap); ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
if (ret) { if (ret) {
dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret); dev_err_probe(cs35l41->dev, ret, "OTP Unpack failed\n");
goto err; goto err;
} }
@ -1644,10 +1792,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
if (ret) if (ret)
goto err; goto err;
ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, cs35l41_mute(cs35l41->dev, true);
ARRAY_SIZE(cs35l41_hda_mute));
if (ret)
goto err;
INIT_WORK(&cs35l41->fw_load_work, cs35l41_fw_load_work); INIT_WORK(&cs35l41->fw_load_work, cs35l41_fw_load_work);
mutex_init(&cs35l41->fw_mutex); mutex_init(&cs35l41->fw_mutex);
@ -1667,9 +1812,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); ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);
if (ret) { if (ret) {
dev_err(cs35l41->dev, "Register component failed: %d\n", ret); dev_err_probe(cs35l41->dev, ret, "Register component failed\n");
pm_runtime_disable(cs35l41->dev); goto err_pm;
goto err;
} }
dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid); dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid);
@ -1677,6 +1821,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
return 0; return 0;
err_pm: err_pm:
pm_runtime_dont_use_autosuspend(cs35l41->dev);
pm_runtime_disable(cs35l41->dev); pm_runtime_disable(cs35l41->dev);
pm_runtime_put_noidle(cs35l41->dev); pm_runtime_put_noidle(cs35l41->dev);
@ -1684,6 +1829,7 @@ err:
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio); gpiod_put(cs35l41->reset_gpio);
acpi_dev_put(cs35l41->dacpi);
kfree(cs35l41->acpi_subsystem_id); kfree(cs35l41->acpi_subsystem_id);
return ret; return ret;
@ -1695,6 +1841,7 @@ void cs35l41_hda_remove(struct device *dev)
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
pm_runtime_get_sync(cs35l41->dev); pm_runtime_get_sync(cs35l41->dev);
pm_runtime_dont_use_autosuspend(cs35l41->dev);
pm_runtime_disable(cs35l41->dev); pm_runtime_disable(cs35l41->dev);
if (cs35l41->halo_initialized) if (cs35l41->halo_initialized)
@ -1702,6 +1849,8 @@ void cs35l41_hda_remove(struct device *dev)
component_del(cs35l41->dev, &cs35l41_hda_comp_ops); component_del(cs35l41->dev, &cs35l41_hda_comp_ops);
acpi_dev_put(cs35l41->dacpi);
pm_runtime_put_noidle(cs35l41->dev); pm_runtime_put_noidle(cs35l41->dev);
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))

View File

@ -10,6 +10,7 @@
#ifndef __CS35L41_HDA_H__ #ifndef __CS35L41_HDA_H__
#define __CS35L41_HDA_H__ #define __CS35L41_HDA_H__
#include <linux/acpi.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
@ -70,6 +71,8 @@ struct cs35l41_hda {
bool halo_initialized; bool halo_initialized;
bool playback_started; bool playback_started;
struct cs_dsp cs_dsp; struct cs_dsp cs_dsp;
struct acpi_device *dacpi;
bool mute_override;
}; };
enum halo_state { 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->index = id;
cs35l41->channel_index = 0; 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; 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.func = CS35L41_NOT_USED;
hw_cfg->gpio1.valid = true; hw_cfg->gpio1.valid = true;
hw_cfg->gpio2.func = CS35L41_INTERRUPT; hw_cfg->gpio2.func = CS35L41_INTERRUPT;

View File

@ -16,6 +16,7 @@
#include <sound/core.h> #include <sound/core.h>
#include <sound/hda_codec.h> #include <sound/hda_codec.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include "cirrus_scodec.h"
#include "cs35l56_hda.h" #include "cs35l56_hda.h"
#include "hda_component.h" #include "hda_component.h"
#include "hda_cs_dsp_ctl.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", "Read ACPI _SUB failed(%ld): fallback to generic firmware\n",
PTR_ERR(sub)); PTR_ERR(sub));
} else { } 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, 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); 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_DESCRIPTION("CS35L56 HDA Driver");
MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);
MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS); MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS);
MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");

View File

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

View File

@ -6,6 +6,7 @@
* Cirrus Logic International Semiconductor Ltd. * Cirrus Logic International Semiconductor Ltd.
*/ */
#include <linux/acpi.h>
#include <linux/component.h> #include <linux/component.h>
#define HDA_MAX_COMPONENTS 4 #define HDA_MAX_COMPONENTS 4
@ -15,6 +16,9 @@ struct hda_component {
struct device *dev; struct device *dev;
char name[HDA_MAX_NAME_SIZE]; char name[HDA_MAX_NAME_SIZE];
struct hda_codec *codec; 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 (*pre_playback_hook)(struct device *dev, int action);
void (*playback_hook)(struct device *dev, int action); void (*playback_hook)(struct device *dev, int action);
void (*post_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) if (err < 0)
goto unlock; 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; stream_tag = azx_dev->core.stream_tag;
/* CA-IBG chips need the playback stream starting from 1 */ /* 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 = le32_to_cpu(*azx_dev->core.posbuf);
mod_dma_pos %= azx_dev->core.period_bytes; 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) { if (azx_dev->insufficient) {
/* Link position never gather than FIFO size */ /* Link position never gather than FIFO size */
@ -2135,6 +2135,36 @@ static int azx_probe(struct pci_dev *pci,
pci_set_drvdata(pci, card); 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); err = register_vga_switcheroo(chip);
if (err < 0) { if (err < 0) {
dev_err(card->dev, "Error registering vga_switcheroo client\n"); dev_err(card->dev, "Error registering vga_switcheroo client\n");
@ -2162,11 +2192,6 @@ static int azx_probe(struct pci_dev *pci,
} }
#endif /* CONFIG_SND_HDA_PATCH_LOADER */ #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) if (schedule_probe)
schedule_delayed_work(&hda->probe_work, 0); schedule_delayed_work(&hda->probe_work, 0);
@ -2176,6 +2201,7 @@ static int azx_probe(struct pci_dev *pci,
return 0; return 0;
out_free: out_free:
pci_set_drvdata(pci, NULL);
snd_card_free(card); snd_card_free(card);
return err; return err;
} }
@ -2263,30 +2289,6 @@ static int azx_probe_continue(struct azx *chip)
to_hda_bus(bus)->bus_probing = 1; to_hda_bus(bus)->bus_probing = 1;
hda->probe_continued = 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 /* Request display power well for the HDA controller or codec. For
* Haswell/Broadwell, both the display HDA controller and codec need * Haswell/Broadwell, both the display HDA controller and codec need
* this power. For other platforms, like Baytrail/Braswell, only the * this power. For other platforms, like Baytrail/Braswell, only the

View File

@ -10,6 +10,7 @@
* Jonathan Woithe <jwoithe@just42.net> * Jonathan Woithe <jwoithe@just42.net>
*/ */
#include <linux/acpi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.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) static int comp_bind(struct device *dev)
{ {
struct hda_codec *cdc = dev_to_hda_codec(dev); struct hda_codec *cdc = dev_to_hda_codec(dev);
struct alc_spec *spec = cdc->spec; 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) 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 hda_codec *cdc = dev_to_hda_codec(dev);
struct alc_spec *spec = cdc->spec; struct alc_spec *spec = cdc->spec;
comp_unbind_acpi(dev);
component_unbind_all(dev, spec->comps); 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) { if (chip->device_type == DEVICE_SIS) {
/* unmute the output on SIS7012 */ /* unmute the output on SIS7013 */
iputword(chip, 0x4c, igetword(chip, 0x4c) | 1); iputword(chip, 0x4c, igetword(chip, 0x4c) | 1);
} }

View File

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

View File

@ -54,7 +54,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
{ {
int ret; int ret;
struct snd_soc_card *card = rtd->card; 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; struct snd_soc_component *component = codec_dai->component;
dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); 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) static int da7219_clk_enable(struct snd_pcm_substream *substream)
{ {
int ret = 0; 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 * 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; int ret;
struct snd_soc_card *card = rtd->card; 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; struct snd_soc_component *component = codec_dai->component;
dev_info(codec_dai->dev, "codec dai name = %s\n", codec_dai->name); 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) static int rt5682_clk_enable(struct snd_pcm_substream *substream)
{ {
int ret; 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 * 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) static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(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) static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(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) static int cz_max_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(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) static int cz_dmic0_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(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) static int cz_dmic1_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(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) static int cz_rt5682_play_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(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) static int cz_rt5682_cap_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(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) static int cz_rt5682_max_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(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) static int cz_rt5682_dmic0_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(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) static int cz_rt5682_dmic1_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(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_card *card;
struct snd_soc_component *codec; 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; card = rtd->card;
ret = snd_soc_card_jack_new_pins(card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0, 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; int ret;
runtime = substream->runtime; runtime = substream->runtime;
rtd = asoc_substream_to_rtd(substream); rtd = snd_soc_substream_to_rtd(substream);
card = rtd->card; card = rtd->card;
machine = snd_soc_card_get_drvdata(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); ret = snd_soc_dai_set_sysclk(codec_dai, 0, ES8336_PLL_FREQ, SND_SOC_CLOCK_IN);
if (ret < 0) { if (ret < 0) {
dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret); 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; u32 val = 0;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
struct audio_substream_data *rtd; 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 audio_drv_data *adata = dev_get_drvdata(component->dev);
struct snd_soc_card *card = prtd->card; struct snd_soc_card *card = prtd->card;
struct acp_platform_info *pinfo = snd_soc_card_get_drvdata(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) struct snd_pcm_hw_params *params)
{ {
int ret = 0; 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);
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);
ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK, ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK,
CZ_PLAT_CLK, params_rate(params) * 512); 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_card *card;
struct snd_soc_component *codec; 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; card = rtd->card;
ret = snd_soc_card_jack_new_pins(card, "Headset Jack", ret = snd_soc_card_jack_new_pins(card, "Headset Jack",

View File

@ -17,7 +17,7 @@ snd-acp-rembrandt-objs := acp-rembrandt.o
#machine specific driver #machine specific driver
snd-acp-mach-objs := acp-mach-common.o 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 snd-acp-sof-mach-objs := acp-sof-mach.o
obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o

View File

@ -80,8 +80,8 @@ void restore_acp_pdm_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *soc_runtime; struct snd_soc_pcm_runtime *soc_runtime;
u32 ext_int_ctrl; u32 ext_int_ctrl;
soc_runtime = asoc_substream_to_rtd(substream); soc_runtime = snd_soc_substream_to_rtd(substream);
dai = asoc_rtd_to_cpu(soc_runtime, 0); dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
/* Programming channel mask and sampling rate */ /* Programming channel mask and sampling rate */
writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS); writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR); writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
@ -192,8 +192,8 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *soc_runtime; struct snd_soc_pcm_runtime *soc_runtime;
u32 tdm_fmt, reg_val, fmt_reg, val; u32 tdm_fmt, reg_val, fmt_reg, val;
soc_runtime = asoc_substream_to_rtd(substream); soc_runtime = snd_soc_substream_to_rtd(substream);
dai = asoc_rtd_to_cpu(soc_runtime, 0); dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
tdm_fmt = adata->tdm_tx_fmt[stream->dai_id - 1]; tdm_fmt = adata->tdm_tx_fmt[stream->dai_id - 1];
switch (stream->dai_id) { switch (stream->dai_id) {

View File

@ -20,6 +20,7 @@
#include <linux/module.h> #include <linux/module.h>
#include "acp-mach.h" #include "acp-mach.h"
#include "acp3x-es83xx/acp3x-es83xx.h"
static struct acp_card_drvdata rt5682_rt1019_data = { static struct acp_card_drvdata rt5682_rt1019_data = {
.hs_cpu_id = I2S_SP, .hs_cpu_id = I2S_SP,
@ -51,6 +52,14 @@ static struct acp_card_drvdata rt5682s_rt1019_data = {
.tdm_mode = false, .tdm_mode = false,
}; };
static struct acp_card_drvdata es83xx_rn_data = {
.hs_cpu_id = I2S_SP,
.dmic_cpu_id = DMIC,
.hs_codec_id = ES83XX,
.dmic_codec_id = DMIC,
.platform = RENOIR,
};
static struct acp_card_drvdata max_nau8825_data = { static struct acp_card_drvdata max_nau8825_data = {
.hs_cpu_id = I2S_HS, .hs_cpu_id = I2S_HS,
.amp_cpu_id = I2S_HS, .amp_cpu_id = I2S_HS,
@ -75,6 +84,39 @@ static struct acp_card_drvdata rt5682s_rt1019_rmb_data = {
.tdm_mode = false, .tdm_mode = false,
}; };
static bool acp_asoc_init_ops(struct acp_card_drvdata *priv)
{
bool has_ops = false;
if (priv->hs_codec_id == ES83XX) {
has_ops = true;
acp3x_es83xx_init_ops(&priv->ops);
}
return has_ops;
}
static int acp_asoc_suspend_pre(struct snd_soc_card *card)
{
int ret;
ret = acp_ops_suspend_pre(card);
if (ret == 1)
return 0;
else
return ret;
}
static int acp_asoc_resume_post(struct snd_soc_card *card)
{
int ret;
ret = acp_ops_resume_post(card);
if (ret == 1)
return 0;
else
return ret;
}
static int acp_asoc_probe(struct platform_device *pdev) static int acp_asoc_probe(struct platform_device *pdev)
{ {
struct snd_soc_card *card = NULL; struct snd_soc_card *card = NULL;
@ -83,35 +125,68 @@ static int acp_asoc_probe(struct platform_device *pdev)
struct acp_card_drvdata *acp_card_drvdata; struct acp_card_drvdata *acp_card_drvdata;
int ret; int ret;
if (!pdev->id_entry) if (!pdev->id_entry) {
return -EINVAL; ret = -EINVAL;
goto out;
}
card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
if (!card) if (!card) {
return -ENOMEM; ret = -ENOMEM;
goto out;
}
card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
acp_card_drvdata = card->drvdata;
acp_card_drvdata->acpi_mach = (struct snd_soc_acpi_mach *)pdev->dev.platform_data;
card->dev = dev; card->dev = dev;
card->owner = THIS_MODULE; card->owner = THIS_MODULE;
card->name = pdev->id_entry->name; card->name = pdev->id_entry->name;
card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
/* Widgets and controls added per-codec in acp-mach-common.c */
acp_card_drvdata = card->drvdata; acp_asoc_init_ops(card->drvdata);
/* If widgets and controls are not set in specific callback,
* they will be added per-codec in acp-mach-common.c
*/
ret = acp_ops_configure_widgets(card);
if (ret < 0) {
dev_err(&pdev->dev,
"Cannot configure widgets for card (%s): %d\n",
card->name, ret);
goto out;
}
card->suspend_pre = acp_asoc_suspend_pre;
card->resume_post = acp_asoc_resume_post;
ret = acp_ops_probe(card);
if (ret < 0) {
dev_err(&pdev->dev,
"Cannot probe card (%s): %d\n",
card->name, ret);
goto out;
}
dmi_id = dmi_first_match(acp_quirk_table); dmi_id = dmi_first_match(acp_quirk_table);
if (dmi_id && dmi_id->driver_data) if (dmi_id && dmi_id->driver_data)
acp_card_drvdata->tdm_mode = dmi_id->driver_data; acp_card_drvdata->tdm_mode = dmi_id->driver_data;
acp_legacy_dai_links_create(card); ret = acp_legacy_dai_links_create(card);
if (ret) {
dev_err(&pdev->dev,
"Cannot create dai links for card (%s): %d\n",
card->name, ret);
goto out;
}
ret = devm_snd_soc_register_card(&pdev->dev, card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"devm_snd_soc_register_card(%s) failed: %d\n", "devm_snd_soc_register_card(%s) failed: %d\n",
card->name, ret); card->name, ret);
return ret; goto out;
} }
out:
return 0; return ret;
} }
static const struct platform_device_id board_ids[] = { static const struct platform_device_id board_ids[] = {
@ -127,6 +202,10 @@ static const struct platform_device_id board_ids[] = {
.name = "acp3xalc5682s1019", .name = "acp3xalc5682s1019",
.driver_data = (kernel_ulong_t)&rt5682s_rt1019_data, .driver_data = (kernel_ulong_t)&rt5682s_rt1019_data,
}, },
{
.name = "acp3x-es83xx",
.driver_data = (kernel_ulong_t)&es83xx_rn_data,
},
{ {
.name = "rmb-nau8825-max", .name = "rmb-nau8825-max",
.driver_data = (kernel_ulong_t)&max_nau8825_data, .driver_data = (kernel_ulong_t)&max_nau8825_data,
@ -153,6 +232,7 @@ MODULE_DESCRIPTION("ACP chrome audio support");
MODULE_ALIAS("platform:acp3xalc56821019"); MODULE_ALIAS("platform:acp3xalc56821019");
MODULE_ALIAS("platform:acp3xalc5682sm98360"); MODULE_ALIAS("platform:acp3xalc5682sm98360");
MODULE_ALIAS("platform:acp3xalc5682s1019"); MODULE_ALIAS("platform:acp3xalc5682s1019");
MODULE_ALIAS("platform:acp3x-es83xx");
MODULE_ALIAS("platform:rmb-nau8825-max"); MODULE_ALIAS("platform:rmb-nau8825-max");
MODULE_ALIAS("platform:rmb-rt5682s-rt1019"); MODULE_ALIAS("platform:rmb-rt5682s-rt1019");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View File

@ -117,7 +117,7 @@ static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
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; struct snd_soc_component *component = codec_dai->component;
int ret; int ret;
@ -172,10 +172,10 @@ static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
static int acp_card_hs_startup(struct snd_pcm_substream *substream) static int acp_card_hs_startup(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; 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 snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
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);
int ret; int ret;
unsigned int fmt; unsigned int fmt;
@ -206,7 +206,7 @@ static int acp_card_hs_startup(struct snd_pcm_substream *substream)
static void acp_card_shutdown(struct snd_pcm_substream *substream) static void acp_card_shutdown(struct snd_pcm_substream *substream)
{ {
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 snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
@ -220,8 +220,8 @@ static int acp_card_rt5682_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
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_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
int ret; int ret;
unsigned int fmt, srate, ch, format; unsigned int fmt, srate, ch, format;
@ -342,7 +342,7 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
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; struct snd_soc_component *component = codec_dai->component;
int ret; int ret;
@ -402,8 +402,8 @@ static int acp_card_rt5682s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
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_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
int ret; int ret;
unsigned int fmt, srate, ch, format; unsigned int fmt, srate, ch, format;
@ -573,7 +573,7 @@ static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
struct snd_soc_dai *codec_dai; struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
int i, ret = 0; int i, ret = 0;
unsigned int fmt, srate, ch, format; unsigned int fmt, srate, ch, format;
@ -737,7 +737,7 @@ static int acp_card_maxim_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
unsigned int fmt, srate, ch, format; unsigned int fmt, srate, ch, format;
int ret; int ret;
@ -928,7 +928,7 @@ static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
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; struct snd_soc_component *component = codec_dai->component;
int ret; int ret;
@ -980,11 +980,11 @@ static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)
static int acp_nau8825_hw_params(struct snd_pcm_substream *substream, static int acp_nau8825_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
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 snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
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_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
int ret; int ret;
unsigned int fmt; unsigned int fmt;
@ -1142,7 +1142,7 @@ static struct snd_pcm_hw_constraint_list constraints_sample_bits = {
static int acp_8821_init(struct snd_soc_pcm_runtime *rtd) static int acp_8821_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_card *card = rtd->card; 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; struct snd_soc_component *component = codec_dai->component;
int ret; int ret;
@ -1204,10 +1204,10 @@ static int acp_8821_startup(struct snd_pcm_substream *substream)
static int acp_nau8821_hw_params(struct snd_pcm_substream *substream, static int acp_nau8821_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
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 snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata; struct acp_card_drvdata *drvdata = card->drvdata;
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);
int ret; int ret;
unsigned int fmt; unsigned int fmt;
@ -1358,7 +1358,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].no_pcm = 1; links[i].no_pcm = 1;
if (!drv_data->hs_codec_id) { if (!drv_data->hs_codec_id) {
/* Use dummy codec if codec id not specified */ /* Use dummy codec if codec id not specified */
links[i].codecs = &asoc_dummy_dlc; links[i].codecs = &snd_soc_dummy_dlc;
links[i].num_codecs = 1; links[i].num_codecs = 1;
} }
if (drv_data->hs_codec_id == RT5682) { if (drv_data->hs_codec_id == RT5682) {
@ -1395,7 +1395,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].no_pcm = 1; links[i].no_pcm = 1;
if (!drv_data->hs_codec_id) { if (!drv_data->hs_codec_id) {
/* Use dummy codec if codec id not specified */ /* Use dummy codec if codec id not specified */
links[i].codecs = &asoc_dummy_dlc; links[i].codecs = &snd_soc_dummy_dlc;
links[i].num_codecs = 1; links[i].num_codecs = 1;
} }
if (drv_data->hs_codec_id == NAU8825) { if (drv_data->hs_codec_id == NAU8825) {
@ -1425,7 +1425,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].no_pcm = 1; links[i].no_pcm = 1;
if (!drv_data->amp_codec_id) { if (!drv_data->amp_codec_id) {
/* Use dummy codec if codec id not specified */ /* Use dummy codec if codec id not specified */
links[i].codecs = &asoc_dummy_dlc; links[i].codecs = &snd_soc_dummy_dlc;
links[i].num_codecs = 1; links[i].num_codecs = 1;
} }
if (drv_data->amp_codec_id == RT1019) { if (drv_data->amp_codec_id == RT1019) {
@ -1457,7 +1457,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].no_pcm = 1; links[i].no_pcm = 1;
if (!drv_data->amp_codec_id) { if (!drv_data->amp_codec_id) {
/* Use dummy codec if codec id not specified */ /* Use dummy codec if codec id not specified */
links[i].codecs = &asoc_dummy_dlc; links[i].codecs = &snd_soc_dummy_dlc;
links[i].num_codecs = 1; links[i].num_codecs = 1;
} }
if (drv_data->amp_codec_id == MAX98360A) { if (drv_data->amp_codec_id == MAX98360A) {
@ -1513,6 +1513,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
struct device *dev = card->dev; struct device *dev = card->dev;
struct acp_card_drvdata *drv_data = card->drvdata; struct acp_card_drvdata *drv_data = card->drvdata;
int i = 0, num_links = 0; int i = 0, num_links = 0;
int rc;
if (drv_data->hs_cpu_id) if (drv_data->hs_cpu_id)
num_links++; num_links++;
@ -1536,7 +1537,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].dpcm_capture = 1; links[i].dpcm_capture = 1;
if (!drv_data->hs_codec_id) { if (!drv_data->hs_codec_id) {
/* Use dummy codec if codec id not specified */ /* Use dummy codec if codec id not specified */
links[i].codecs = &asoc_dummy_dlc; links[i].codecs = &snd_soc_dummy_dlc;
links[i].num_codecs = 1; links[i].num_codecs = 1;
} }
if (drv_data->hs_codec_id == RT5682) { if (drv_data->hs_codec_id == RT5682) {
@ -1551,6 +1552,13 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].init = acp_card_rt5682s_init; links[i].init = acp_card_rt5682s_init;
links[i].ops = &acp_card_rt5682s_ops; links[i].ops = &acp_card_rt5682s_ops;
} }
if (drv_data->hs_codec_id == ES83XX) {
rc = acp_ops_configure_link(card, &links[i]);
if (rc != 0) {
dev_err(dev, "Failed to configure link for ES83XX: %d\n", rc);
return rc;
}
}
i++; i++;
} }
@ -1570,7 +1578,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].dpcm_capture = 1; links[i].dpcm_capture = 1;
if (!drv_data->hs_codec_id) { if (!drv_data->hs_codec_id) {
/* Use dummy codec if codec id not specified */ /* Use dummy codec if codec id not specified */
links[i].codecs = &asoc_dummy_dlc; links[i].codecs = &snd_soc_dummy_dlc;
links[i].num_codecs = 1; links[i].num_codecs = 1;
} }
if (drv_data->hs_codec_id == NAU8825) { if (drv_data->hs_codec_id == NAU8825) {
@ -1598,7 +1606,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].dpcm_playback = 1; links[i].dpcm_playback = 1;
if (!drv_data->amp_codec_id) { if (!drv_data->amp_codec_id) {
/* Use dummy codec if codec id not specified */ /* Use dummy codec if codec id not specified */
links[i].codecs = &asoc_dummy_dlc; links[i].codecs = &snd_soc_dummy_dlc;
links[i].num_codecs = 1; links[i].num_codecs = 1;
} }
if (drv_data->amp_codec_id == RT1019) { if (drv_data->amp_codec_id == RT1019) {
@ -1633,7 +1641,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].dpcm_playback = 1; links[i].dpcm_playback = 1;
if (!drv_data->amp_codec_id) { if (!drv_data->amp_codec_id) {
/* Use dummy codec if codec id not specified */ /* Use dummy codec if codec id not specified */
links[i].codecs = &asoc_dummy_dlc; links[i].codecs = &snd_soc_dummy_dlc;
links[i].num_codecs = 1; links[i].num_codecs = 1;
} }
if (drv_data->amp_codec_id == MAX98360A) { if (drv_data->amp_codec_id == MAX98360A) {
@ -1661,7 +1669,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].num_codecs = ARRAY_SIZE(dmic_codec); links[i].num_codecs = ARRAY_SIZE(dmic_codec);
} else { } else {
/* Use dummy codec if codec id not specified */ /* Use dummy codec if codec id not specified */
links[i].codecs = &asoc_dummy_dlc; links[i].codecs = &snd_soc_dummy_dlc;
links[i].num_codecs = 1; links[i].num_codecs = 1;
} }
links[i].cpus = pdm_dmic; links[i].cpus = pdm_dmic;

View File

@ -20,6 +20,10 @@
#define TDM_CHANNELS 8 #define TDM_CHANNELS 8
#define ACP_OPS(priv, cb) ((priv)->ops.cb)
#define acp_get_drvdata(card) ((struct acp_card_drvdata *)(card)->drvdata)
enum be_id { enum be_id {
HEADSET_BE_ID = 0, HEADSET_BE_ID = 0,
AMP_BE_ID, AMP_BE_ID,
@ -43,6 +47,7 @@ enum codec_endpoints {
NAU8825, NAU8825,
NAU8821, NAU8821,
MAX98388, MAX98388,
ES83XX,
}; };
enum platform_end_point { enum platform_end_point {
@ -50,6 +55,14 @@ enum platform_end_point {
REMBRANDT, REMBRANDT,
}; };
struct acp_mach_ops {
int (*probe)(struct snd_soc_card *card);
int (*configure_link)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
int (*configure_widgets)(struct snd_soc_card *card);
int (*suspend_pre)(struct snd_soc_card *card);
int (*resume_post)(struct snd_soc_card *card);
};
struct acp_card_drvdata { struct acp_card_drvdata {
unsigned int hs_cpu_id; unsigned int hs_cpu_id;
unsigned int amp_cpu_id; unsigned int amp_cpu_id;
@ -61,6 +74,9 @@ struct acp_card_drvdata {
unsigned int platform; unsigned int platform;
struct clk *wclk; struct clk *wclk;
struct clk *bclk; struct clk *bclk;
struct acp_mach_ops ops;
struct snd_soc_acpi_mach *acpi_mach;
void *mach_priv;
bool soc_mclk; bool soc_mclk;
bool tdm_mode; bool tdm_mode;
}; };
@ -69,4 +85,55 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card);
int acp_legacy_dai_links_create(struct snd_soc_card *card); int acp_legacy_dai_links_create(struct snd_soc_card *card);
extern const struct dmi_system_id acp_quirk_table[]; extern const struct dmi_system_id acp_quirk_table[];
static inline int acp_ops_probe(struct snd_soc_card *card)
{
int ret = 1;
struct acp_card_drvdata *priv = acp_get_drvdata(card);
if (ACP_OPS(priv, probe))
ret = ACP_OPS(priv, probe)(card);
return ret;
}
static inline int acp_ops_configure_link(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link)
{
int ret = 1;
struct acp_card_drvdata *priv = acp_get_drvdata(card);
if (ACP_OPS(priv, configure_link))
ret = ACP_OPS(priv, configure_link)(card, dai_link);
return ret;
}
static inline int acp_ops_configure_widgets(struct snd_soc_card *card)
{
int ret = 1;
struct acp_card_drvdata *priv = acp_get_drvdata(card);
if (ACP_OPS(priv, configure_widgets))
ret = ACP_OPS(priv, configure_widgets)(card);
return ret;
}
static inline int acp_ops_suspend_pre(struct snd_soc_card *card)
{
int ret = 1;
struct acp_card_drvdata *priv = acp_get_drvdata(card);
if (ACP_OPS(priv, suspend_pre))
ret = ACP_OPS(priv, suspend_pre)(card);
return ret;
}
static inline int acp_ops_resume_post(struct snd_soc_card *card)
{
int ret = 1;
struct acp_card_drvdata *priv = acp_get_drvdata(card);
if (ACP_OPS(priv, resume_post))
ret = ACP_OPS(priv, resume_post)(card);
return ret;
}
#endif #endif

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