aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml14
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,sai.yaml6
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,spdif.yaml35
-rw-r--r--Documentation/devicetree/bindings/sound/fsl-asoc-card.txt117
-rw-r--r--Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml195
-rw-r--r--Documentation/devicetree/bindings/sound/nuvoton,nau8325.yaml80
-rw-r--r--include/sound/control.h23
-rw-r--r--include/sound/hdaudio_ext.h3
-rw-r--r--include/sound/soc-acpi-intel-ssp-common.h (renamed from sound/soc/intel/boards/sof_ssp_common.h)29
-rw-r--r--include/sound/soc-acpi.h12
-rw-r--r--include/sound/soc-jack.h2
-rw-r--r--sound/soc/Kconfig8
-rw-r--r--sound/soc/Makefile4
-rw-r--r--sound/soc/amd/acp/acp-pci.c13
-rw-r--r--sound/soc/codecs/cs-amp-lib.c5
-rw-r--r--sound/soc/codecs/cs42l43.c12
-rw-r--r--sound/soc/codecs/es8326.c37
-rw-r--r--sound/soc/codecs/es8326.h2
-rw-r--r--sound/soc/codecs/max98373-sdw.c1
-rw-r--r--sound/soc/codecs/nau8325.c900
-rw-r--r--sound/soc/codecs/nau8325.h391
-rw-r--r--sound/soc/codecs/rt1017-sdca-sdw.c1
-rw-r--r--sound/soc/codecs/rt1308-sdw.c1
-rw-r--r--sound/soc/codecs/rt1316-sdw.c9
-rw-r--r--sound/soc/codecs/rt1318-sdw.c9
-rw-r--r--sound/soc/codecs/rt5682-sdw.c17
-rw-r--r--sound/soc/codecs/rt700-sdw.c1
-rw-r--r--sound/soc/codecs/rt700.c16
-rw-r--r--sound/soc/codecs/rt711-sdca-sdw.c7
-rw-r--r--sound/soc/codecs/rt711-sdca.c18
-rw-r--r--sound/soc/codecs/rt711-sdw.c9
-rw-r--r--sound/soc/codecs/rt711.c16
-rw-r--r--sound/soc/codecs/rt712-sdca-dmic.c25
-rw-r--r--sound/soc/codecs/rt712-sdca-sdw.c8
-rw-r--r--sound/soc/codecs/rt712-sdca.c20
-rw-r--r--sound/soc/codecs/rt715-sdca-sdw.c3
-rw-r--r--sound/soc/codecs/rt715-sdca.c50
-rw-r--r--sound/soc/codecs/rt715-sdw.c5
-rw-r--r--sound/soc/codecs/rt715.c24
-rw-r--r--sound/soc/codecs/rt722-sdca-sdw.c5
-rw-r--r--sound/soc/codecs/rt722-sdca.c21
-rw-r--r--sound/soc/codecs/sdw-mockup.c1
-rw-r--r--sound/soc/codecs/tlv320aic32x4-spi.c1
-rw-r--r--sound/soc/codecs/tlv320aic3x-spi.c1
-rw-r--r--sound/soc/codecs/wm_adsp.c3
-rw-r--r--sound/soc/generic/simple-card-utils.c2
-rw-r--r--sound/soc/intel/avs/avs.h2
-rw-r--r--sound/soc/intel/avs/boards/da7219.c1
-rw-r--r--sound/soc/intel/avs/boards/dmic.c1
-rw-r--r--sound/soc/intel/avs/boards/es8336.c3
-rw-r--r--sound/soc/intel/avs/boards/hdaudio.c6
-rw-r--r--sound/soc/intel/avs/boards/i2s_test.c1
-rw-r--r--sound/soc/intel/avs/boards/max98357a.c1
-rw-r--r--sound/soc/intel/avs/boards/max98373.c1
-rw-r--r--sound/soc/intel/avs/boards/max98927.c1
-rw-r--r--sound/soc/intel/avs/boards/nau8825.c3
-rw-r--r--sound/soc/intel/avs/boards/probe.c1
-rw-r--r--sound/soc/intel/avs/boards/rt274.c3
-rw-r--r--sound/soc/intel/avs/boards/rt286.c3
-rw-r--r--sound/soc/intel/avs/boards/rt298.c3
-rw-r--r--sound/soc/intel/avs/boards/rt5514.c1
-rw-r--r--sound/soc/intel/avs/boards/rt5663.c3
-rw-r--r--sound/soc/intel/avs/boards/rt5682.c3
-rw-r--r--sound/soc/intel/avs/boards/ssm4567.c1
-rw-r--r--sound/soc/intel/avs/utils.c8
-rw-r--r--sound/soc/intel/boards/Kconfig14
-rw-r--r--sound/soc/intel/boards/Makefile7
-rw-r--r--sound/soc/intel/boards/sof_board_helpers.c33
-rw-r--r--sound/soc/intel/boards/sof_board_helpers.h9
-rw-r--r--sound/soc/intel/boards/sof_cirrus_common.h2
-rw-r--r--sound/soc/intel/boards/sof_cs42l42.c17
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.h2
-rw-r--r--sound/soc/intel/boards/sof_nau8825.c7
-rw-r--r--sound/soc/intel/boards/sof_nuvoton_common.h2
-rw-r--r--sound/soc/intel/boards/sof_realtek_common.h2
-rw-r--r--sound/soc/intel/boards/sof_sdw.c1090
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h42
-rw-r--r--sound/soc/intel/boards/sof_sdw_cs42l42.c1
-rw-r--r--sound/soc/intel/boards/sof_sdw_cs42l43.c50
-rw-r--r--sound/soc/intel/boards/sof_sdw_cs_amp.c1
-rw-r--r--sound/soc/intel/boards/sof_sdw_maxim.c1
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt5682.c1
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt700.c1
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711.c2
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt712_sdca.c25
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715.c26
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715_sdca.c26
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt722_sdca.c38
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt_amp.c1
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt_dmic.c54
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c4
-rw-r--r--sound/soc/intel/boards/sof_ssp_common.c122
-rw-r--r--sound/soc/intel/common/Makefile2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-adl-match.c139
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-arl-match.c24
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c87
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-rpl-match.c90
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-ssp-common.c159
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-tgl-match.c85
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c3
-rw-r--r--sound/soc/loongson/loongson_i2s_pci.c1
-rw-r--r--sound/soc/sh/rcar/cmd.c6
-rw-r--r--sound/soc/sh/rcar/core.c4
-rw-r--r--sound/soc/sh/rcar/ctu.c6
-rw-r--r--sound/soc/sh/rcar/dma.c6
-rw-r--r--sound/soc/sh/rcar/dvc.c6
-rw-r--r--sound/soc/sh/rcar/gen.c519
-rw-r--r--sound/soc/sh/rcar/mix.c6
-rw-r--r--sound/soc/sh/rcar/rsnd.h22
-rw-r--r--sound/soc/sh/rcar/src.c12
-rw-r--r--sound/soc/sh/rcar/ssi.c2
-rw-r--r--sound/soc/sh/rcar/ssiu.c2
-rw-r--r--sound/soc/soc-card-test.c184
-rw-r--r--sound/soc/soc-card.c21
-rw-r--r--sound/soc/soc-jack.c23
-rw-r--r--sound/soc/soc-ops.c2
-rw-r--r--sound/soc/sof/amd/acp-loader.c2
-rw-r--r--sound/soc/sof/intel/hda-common-ops.c3
-rw-r--r--sound/soc/sof/intel/hda-dai-ops.c52
-rw-r--r--sound/soc/sof/intel/hda-dai.c124
-rw-r--r--sound/soc/sof/intel/hda-dsp.c20
-rw-r--r--sound/soc/sof/intel/hda-loader.c7
-rw-r--r--sound/soc/sof/intel/hda-pcm.c29
-rw-r--r--sound/soc/sof/intel/hda-stream.c70
-rw-r--r--sound/soc/sof/intel/hda.c184
-rw-r--r--sound/soc/sof/intel/hda.h19
-rw-r--r--sound/soc/sof/intel/lnl.c12
-rw-r--r--sound/soc/sof/intel/lnl.h15
-rw-r--r--sound/soc/sof/intel/mtl.c77
-rw-r--r--sound/soc/sof/intel/mtl.h58
-rw-r--r--sound/soc/sof/ipc4-loader.c8
-rw-r--r--sound/soc/sof/ipc4-mtrace.c11
-rw-r--r--sound/soc/sof/ipc4-pcm.c191
-rw-r--r--sound/soc/sof/ipc4-priv.h16
-rw-r--r--sound/soc/sof/ipc4-topology.c85
-rw-r--r--sound/soc/sof/ipc4-topology.h3
-rw-r--r--sound/soc/sof/ops.h24
-rw-r--r--sound/soc/sof/pcm.c66
-rw-r--r--sound/soc/sof/sof-audio.c29
-rw-r--r--sound/soc/sof/sof-audio.h11
-rw-r--r--sound/soc/sof/sof-priv.h24
-rw-r--r--sound/soc/sunxi/sun8i-codec.c14
142 files changed, 4269 insertions, 2084 deletions
diff --git a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
index bfef2fcb75b1..76aa1f248488 100644
--- a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
@@ -74,6 +74,9 @@ properties:
- const: asrck_f
- const: spba
+ power-domains:
+ maxItems: 1
+
fsl,asrc-rate:
$ref: /schemas/types.yaml#/definitions/uint32
description: The mutual sample rate used by DPCM Back Ends
@@ -131,6 +134,17 @@ allOf:
properties:
fsl,asrc-clk-map: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8qm-asrc
+ - fsl,imx8qxp-asrc
+ then:
+ required:
+ - power-domains
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/sound/fsl,sai.yaml b/Documentation/devicetree/bindings/sound/fsl,sai.yaml
index 2456d958adee..a5d9c246cc47 100644
--- a/Documentation/devicetree/bindings/sound/fsl,sai.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,sai.yaml
@@ -81,14 +81,12 @@ properties:
dmas:
minItems: 1
- items:
- - description: DMA controller phandle and request line for RX
- - description: DMA controller phandle and request line for TX
+ maxItems: 2
dma-names:
minItems: 1
items:
- - const: rx
+ - enum: [ rx, tx ]
- const: tx
interrupts:
diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml
index 1d64e8337aa4..204f361cea27 100644
--- a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml
@@ -31,7 +31,10 @@ properties:
maxItems: 1
interrupts:
- maxItems: 1
+ minItems: 1
+ items:
+ - description: Combined or receive interrupt
+ - description: Transmit interrupt
dmas:
items:
@@ -86,6 +89,9 @@ properties:
registers. Set this flag for HCDs with big endian descriptors and big
endian registers.
+ power-domains:
+ maxItems: 1
+
required:
- compatible
- reg
@@ -97,6 +103,33 @@ required:
additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - fsl,imx8qm-spdif
+ - fsl,imx8qxp-spdif
+ then:
+ properties:
+ interrupts:
+ minItems: 2
+ else:
+ properties:
+ interrupts:
+ maxItems: 1
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8qm-spdif
+ - fsl,imx8qxp-spdif
+ then:
+ required:
+ - power-domains
+
examples:
- |
spdif@2004000 {
diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
deleted file mode 100644
index 4e8dbc5abfd1..000000000000
--- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
+++ /dev/null
@@ -1,117 +0,0 @@
-Freescale Generic ASoC Sound Card with ASRC support
-
-The Freescale Generic ASoC Sound Card can be used, ideally, for all Freescale
-SoCs connecting with external CODECs.
-
-The idea of this generic sound card is a bit like ASoC Simple Card. However,
-for Freescale SoCs (especially those released in recent years), most of them
-have ASRC (Documentation/devicetree/bindings/sound/fsl,asrc.txt) inside. And
-this is a specific feature that might be painstakingly controlled and merged
-into the Simple Card.
-
-So having this generic sound card allows all Freescale SoC users to benefit
-from the simplification of a new card support and the capability of the wide
-sample rates support through ASRC.
-
-Note: The card is initially designed for those sound cards who use AC'97, I2S
- and PCM DAI formats. However, it'll be also possible to support those non
- AC'97/I2S/PCM type sound cards, such as S/PDIF audio and HDMI audio, as
- long as the driver has been properly upgraded.
-
-
-The compatible list for this generic sound card currently:
- "fsl,imx-audio-ac97"
-
- "fsl,imx-audio-cs42888"
-
- "fsl,imx-audio-cs427x"
- (compatible with CS4271 and CS4272)
-
- "fsl,imx-audio-wm8962"
-
- "fsl,imx-audio-sgtl5000"
- (compatible with Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt)
-
- "fsl,imx-audio-wm8960"
-
- "fsl,imx-audio-mqs"
-
- "fsl,imx-audio-wm8524"
-
- "fsl,imx-audio-tlv320aic32x4"
-
- "fsl,imx-audio-tlv320aic31xx"
-
- "fsl,imx-audio-si476x"
-
- "fsl,imx-audio-wm8958"
-
- "fsl,imx-audio-nau8822"
-
-Required properties:
-
- - compatible : Contains one of entries in the compatible list.
-
- - model : The user-visible name of this sound complex
-
- - audio-cpu : The phandle of an CPU DAI controller
-
- - audio-codec : The phandle of an audio codec
-
-Optional properties:
-
- - audio-asrc : The phandle of ASRC. It can be absent if there's no
- need to add ASRC support via DPCM.
-
- - audio-routing : A list of the connections between audio components.
- Each entry is a pair of strings, the first being the
- connection's sink, the second being the connection's
- source. There're a few pre-designed board connectors:
- * Line Out Jack
- * Line In Jack
- * Headphone Jack
- * Mic Jack
- * Ext Spk
- * AMIC (stands for Analog Microphone Jack)
- * DMIC (stands for Digital Microphone Jack)
-
- Note: The "Mic Jack" and "AMIC" are redundant while
- coexisting in order to support the old bindings
- of wm8962 and sgtl5000.
-
- - hp-det-gpio : The GPIO that detect headphones are plugged in
- - mic-det-gpio : The GPIO that detect microphones are plugged in
- - bitclock-master : Indicates dai-link bit clock master; for details see simple-card.yaml.
- - frame-master : Indicates dai-link frame master; for details see simple-card.yaml.
- - dai-format : audio format, for details see simple-card.yaml.
- - frame-inversion : dai-link uses frame clock inversion, for details see simple-card.yaml.
- - bitclock-inversion : dai-link uses bit clock inversion, for details see simple-card.yaml.
- - mclk-id : main clock id, specific for each card configuration.
-
-Optional unless SSI is selected as a CPU DAI:
-
- - mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)
-
- - mux-ext-port : The external port of the i.MX audio muxer
-
-Example:
-sound-cs42888 {
- compatible = "fsl,imx-audio-cs42888";
- model = "cs42888-audio";
- audio-cpu = <&esai>;
- audio-asrc = <&asrc>;
- audio-codec = <&cs42888>;
- audio-routing =
- "Line Out Jack", "AOUT1L",
- "Line Out Jack", "AOUT1R",
- "Line Out Jack", "AOUT2L",
- "Line Out Jack", "AOUT2R",
- "Line Out Jack", "AOUT3L",
- "Line Out Jack", "AOUT3R",
- "Line Out Jack", "AOUT4L",
- "Line Out Jack", "AOUT4R",
- "AIN1L", "Line In Jack",
- "AIN1R", "Line In Jack",
- "AIN2L", "Line In Jack",
- "AIN2R", "Line In Jack";
-};
diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml b/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml
new file mode 100644
index 000000000000..42ca39eebd49
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml
@@ -0,0 +1,195 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/fsl-asoc-card.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale Generic ASoC Sound Card with ASRC support
+
+description:
+ The Freescale Generic ASoC Sound Card can be used, ideally,
+ for all Freescale SoCs connecting with external CODECs.
+
+ The idea of this generic sound card is a bit like ASoC Simple Card.
+ However, for Freescale SoCs (especially those released in recent years),
+ most of them have ASRC inside. And this is a specific feature that might
+ be painstakingly controlled and merged into the Simple Card.
+
+ So having this generic sound card allows all Freescale SoC users to
+ benefit from the simplification of a new card support and the capability
+ of the wide sample rates support through ASRC.
+
+ Note, The card is initially designed for those sound cards who use AC'97, I2S
+ and PCM DAI formats. However, it'll be also possible to support those non
+ AC'97/I2S/PCM type sound cards, such as S/PDIF audio and HDMI audio, as
+ long as the driver has been properly upgraded.
+
+maintainers:
+ - Shengjiu Wang <[email protected]>
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - fsl,imx-sgtl5000
+ - fsl,imx53-cpuvo-sgtl5000
+ - fsl,imx51-babbage-sgtl5000
+ - fsl,imx53-m53evk-sgtl5000
+ - fsl,imx53-qsb-sgtl5000
+ - fsl,imx53-voipac-sgtl5000
+ - fsl,imx6-armadeus-sgtl5000
+ - fsl,imx6-rex-sgtl5000
+ - fsl,imx6-sabreauto-cs42888
+ - fsl,imx6-wandboard-sgtl5000
+ - fsl,imx6dl-nit6xlite-sgtl5000
+ - fsl,imx6q-ba16-sgtl5000
+ - fsl,imx6q-nitrogen6_max-sgtl5000
+ - fsl,imx6q-nitrogen6_som2-sgtl5000
+ - fsl,imx6q-nitrogen6x-sgtl5000
+ - fsl,imx6q-sabrelite-sgtl5000
+ - fsl,imx6q-sabresd-wm8962
+ - fsl,imx6q-udoo-ac97
+ - fsl,imx6q-ventana-sgtl5000
+ - fsl,imx6sl-evk-wm8962
+ - fsl,imx6sx-sdb-mqs
+ - fsl,imx6sx-sdb-wm8962
+ - fsl,imx7d-evk-wm8960
+ - karo,tx53-audio-sgtl5000
+ - tq,imx53-mba53-sgtl5000
+ - enum:
+ - fsl,imx-audio-ac97
+ - fsl,imx-audio-cs42888
+ - fsl,imx-audio-mqs
+ - fsl,imx-audio-sgtl5000
+ - fsl,imx-audio-wm8960
+ - fsl,imx-audio-wm8962
+ - items:
+ - enum:
+ - fsl,imx-audio-ac97
+ - fsl,imx-audio-cs42888
+ - fsl,imx-audio-cs427x
+ - fsl,imx-audio-mqs
+ - fsl,imx-audio-nau8822
+ - fsl,imx-audio-sgtl5000
+ - fsl,imx-audio-si476x
+ - fsl,imx-audio-tlv320aic31xx
+ - fsl,imx-audio-tlv320aic32x4
+ - fsl,imx-audio-wm8524
+ - fsl,imx-audio-wm8960
+ - fsl,imx-audio-wm8962
+ - fsl,imx-audio-wm8958
+
+ model:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: The user-visible name of this sound complex
+
+ audio-asrc:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ The phandle of ASRC. It can be absent if there's no
+ need to add ASRC support via DPCM.
+
+ audio-codec:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: The phandle of an audio codec
+
+ audio-cpu:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: The phandle of an CPU DAI controller
+
+ audio-routing:
+ $ref: /schemas/types.yaml#/definitions/non-unique-string-array
+ description:
+ A list of the connections between audio components. Each entry is a
+ pair of strings, the first being the connection's sink, the second
+ being the connection's source. There're a few pre-designed board
+ connectors. "AMIC" stands for Analog Microphone Jack.
+ "DMIC" stands for Digital Microphone Jack. The "Mic Jack" and "AMIC"
+ are redundant while coexisting in order to support the old bindings
+ of wm8962 and sgtl5000.
+
+ hp-det-gpio:
+ deprecated: true
+ maxItems: 1
+ description: The GPIO that detect headphones are plugged in
+
+ hp-det-gpios:
+ maxItems: 1
+ description: The GPIO that detect headphones are plugged in
+
+ mic-det-gpio:
+ deprecated: true
+ maxItems: 1
+ description: The GPIO that detect microphones are plugged in
+
+ mic-det-gpios:
+ maxItems: 1
+ description: The GPIO that detect microphones are plugged in
+
+ bitclock-master:
+ $ref: simple-card.yaml#/definitions/bitclock-master
+ description: Indicates dai-link bit clock master.
+
+ frame-master:
+ $ref: simple-card.yaml#/definitions/frame-master
+ description: Indicates dai-link frame master.
+
+ format:
+ $ref: simple-card.yaml#/definitions/format
+ description: audio format.
+
+ frame-inversion:
+ $ref: simple-card.yaml#/definitions/frame-inversion
+ description: dai-link uses frame clock inversion.
+
+ bitclock-inversion:
+ $ref: simple-card.yaml#/definitions/bitclock-inversion
+ description: dai-link uses bit clock inversion.
+
+ mclk-id:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: main clock id, specific for each card configuration.
+
+ mux-int-port:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [1, 2, 7]
+ description: The internal port of the i.MX audio muxer (AUDMUX)
+
+ mux-ext-port:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [3, 4, 5, 6]
+ description: The external port of the i.MX audio muxer
+
+ ssi-controller:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: The phandle of an CPU DAI controller
+
+required:
+ - compatible
+ - model
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ sound-cs42888 {
+ compatible = "fsl,imx-audio-cs42888";
+ model = "cs42888-audio";
+ audio-cpu = <&esai>;
+ audio-asrc = <&asrc>;
+ audio-codec = <&cs42888>;
+ audio-routing =
+ "Line Out Jack", "AOUT1L",
+ "Line Out Jack", "AOUT1R",
+ "Line Out Jack", "AOUT2L",
+ "Line Out Jack", "AOUT2R",
+ "Line Out Jack", "AOUT3L",
+ "Line Out Jack", "AOUT3R",
+ "Line Out Jack", "AOUT4L",
+ "Line Out Jack", "AOUT4R",
+ "AIN1L", "Line In Jack",
+ "AIN1R", "Line In Jack",
+ "AIN2L", "Line In Jack",
+ "AIN2R", "Line In Jack";
+ };
diff --git a/Documentation/devicetree/bindings/sound/nuvoton,nau8325.yaml b/Documentation/devicetree/bindings/sound/nuvoton,nau8325.yaml
new file mode 100644
index 000000000000..979be0d336da
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nuvoton,nau8325.yaml
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/nuvoton,nau8325.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NAU8325 audio Amplifier
+
+maintainers:
+ - Seven Lee <[email protected]>
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: nuvoton,nau8325
+
+ reg:
+ maxItems: 1
+
+ nuvoton,vref-impedance-ohms:
+ description:
+ The vref impedance to be used in ohms. Middle of voltage enables
+ Tie-Off selection options. Due to the high impedance of the VREF
+ pin, it is important to use a low-leakage capacitor.
+
+ enum: [0, 25000, 125000, 2500]
+
+ nuvoton,dac-vref-microvolt:
+ description:
+ The DAC vref to be used in voltage. DAC reference voltage setting. Can
+ be used for minor tuning of the output level. Since the VDDA is range
+ between 1.62 to 1.98 voltage, the typical value for design is 1.8V. After
+ the minor tuning, the final microvolt are as the below.
+
+ enum: [1800000, 2700000, 2880000, 3060000]
+
+ nuvoton,alc-enable:
+ description:
+ Enable digital automatic level control (ALC) function.
+ type: boolean
+
+ nuvoton,clock-detection-disable:
+ description:
+ When clock detection is enabled, it will detect whether MCLK
+ and FS are within the range. MCLK range is from 2.048MHz to 24.576MHz.
+ FS range is from 8kHz to 96kHz. And also needs to detect the ratio
+ MCLK_SRC/LRCK of 256, 400 or 500, and needs to detect the BCLK
+ to make sure data is present. There needs to be at least 8 BCLK
+ cycles per Frame Sync.
+ type: boolean
+
+ nuvoton,clock-det-data:
+ description:
+ Request clock detection to require 2048 non-zero samples before enabling
+ the audio paths. If set then non-zero samples is required, otherwise it
+ doesn't matter.
+ type: boolean
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ codec@21 {
+ compatible = "nuvoton,nau8325";
+ reg = <0x21>;
+ nuvoton,vref-impedance-ohms = <125000>;
+ nuvoton,dac-vref-microvolt = <2880000>;
+ nuvoton,alc-enable;
+ nuvoton,clock-det-data;
+ };
+ };
diff --git a/include/sound/control.h b/include/sound/control.h
index 9a4f4f7138da..c1659036c4a7 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -167,6 +167,29 @@ snd_ctl_find_id_mixer(struct snd_card *card, const char *name)
return snd_ctl_find_id(card, &id);
}
+/**
+ * snd_ctl_find_id_mixer_locked - find the control instance with the given name string
+ * @card: the card instance
+ * @name: the name string
+ *
+ * Finds the control instance with the given name and
+ * @SNDRV_CTL_ELEM_IFACE_MIXER. Other fields are set to zero.
+ *
+ * This is merely a wrapper to snd_ctl_find_id_locked().
+ * The caller must down card->controls_rwsem before calling this function.
+ *
+ * Return: The pointer of the instance if found, or %NULL if not.
+ */
+static inline struct snd_kcontrol *
+snd_ctl_find_id_mixer_locked(struct snd_card *card, const char *name)
+{
+ struct snd_ctl_elem_id id = {};
+
+ id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ strscpy(id.name, name, sizeof(id.name));
+ return snd_ctl_find_id_locked(card, &id);
+}
+
int snd_ctl_create(struct snd_card *card);
int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h
index a8bebac1e4b2..957295364a5e 100644
--- a/include/sound/hdaudio_ext.h
+++ b/include/sound/hdaudio_ext.h
@@ -56,6 +56,9 @@ struct hdac_ext_stream {
u32 pphcldpl;
u32 pphcldpu;
+ u32 pplcllpl;
+ u32 pplcllpu;
+
bool decoupled:1;
bool link_locked:1;
bool link_prepared;
diff --git a/sound/soc/intel/boards/sof_ssp_common.h b/include/sound/soc-acpi-intel-ssp-common.h
index d24888bc99fd..b4597c8dac78 100644
--- a/sound/soc/intel/boards/sof_ssp_common.h
+++ b/include/sound/soc-acpi-intel-ssp-common.h
@@ -3,8 +3,8 @@
* Copyright(c) 2023 Intel Corporation.
*/
-#ifndef __SOF_SSP_COMMON_H
-#define __SOF_SSP_COMMON_H
+#ifndef __LINUX_SND_SOC_ACPI_INTEL_SSP_COMMON_H
+#define __LINUX_SND_SOC_ACPI_INTEL_SSP_COMMON_H
/* Cirrus Logic */
#define CS35L41_ACPI_HID "CSC3541"
@@ -37,7 +37,7 @@
#define RT5682_ACPI_HID "10EC5682"
#define RT5682S_ACPI_HID "RTL5682"
-enum sof_ssp_codec {
+enum snd_soc_acpi_intel_codec {
CODEC_NONE,
/* headphone codec */
@@ -65,16 +65,17 @@ enum sof_ssp_codec {
CODEC_RT1308,
};
-enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev);
-enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev);
+enum snd_soc_acpi_intel_codec
+snd_soc_acpi_intel_detect_codec_type(struct device *dev);
+enum snd_soc_acpi_intel_codec
+snd_soc_acpi_intel_detect_amp_type(struct device *dev);
-#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON)
-const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type);
-#else
-static inline const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type)
-{
- return NULL;
-}
-#endif
+const char *
+snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type);
-#endif /* __SOF_SSP_COMMON_H */
+const char *
+snd_soc_acpi_intel_get_codec_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type);
+const char *
+snd_soc_acpi_intel_get_amp_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type);
+
+#endif /* __LINUX_SND_SOC_ACPI_INTEL_SSP_COMMON_H */
diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h
index 23d6d6bfb073..1d8f35ca1d6f 100644
--- a/include/sound/soc-acpi.h
+++ b/include/sound/soc-acpi.h
@@ -151,6 +151,18 @@ struct snd_soc_acpi_link_adr {
*/
#define SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER BIT(2)
+/*
+ * when set the speaker amplifier name suffix (i.e. "-max98360a") will be
+ * appended to topology file name
+ */
+#define SND_SOC_ACPI_TPLG_INTEL_AMP_NAME BIT(3)
+
+/*
+ * when set the headphone codec name suffix (i.e. "-rt5682") will be appended to
+ * topology file name
+ */
+#define SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME BIT(4)
+
/**
* snd_soc_acpi_mach: ACPI-based machine descriptor. Most of the fields are
* related to the hardware, except for the firmware and topology file names.
diff --git a/include/sound/soc-jack.h b/include/sound/soc-jack.h
index a0abb1ee5110..3a81d4b8ca8a 100644
--- a/include/sound/soc-jack.h
+++ b/include/sound/soc-jack.h
@@ -44,7 +44,6 @@ struct snd_soc_jack_zone {
/**
* struct snd_soc_jack_gpio - Describes a gpio pin for jack detection
*
- * @gpio: legacy gpio number
* @idx: gpio descriptor index within the function of the GPIO
* consumer device
* @gpiod_dev: GPIO consumer device
@@ -59,7 +58,6 @@ struct snd_soc_jack_zone {
* ADC).
*/
struct snd_soc_jack_gpio {
- unsigned int gpio;
unsigned int idx;
struct device *gpiod_dev;
const char *name;
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 439fa631c342..a52afb423b46 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -66,6 +66,14 @@ config SND_SOC_TOPOLOGY_KUNIT_TEST
userspace applications such as pulseaudio, to prevent unnecessary
problems.
+config SND_SOC_CARD_KUNIT_TEST
+ tristate "KUnit tests for SoC card"
+ depends on KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ If you want to perform tests on ALSA SoC card functions say Y here.
+ If unsure, say N.
+
config SND_SOC_UTILS_KUNIT_TEST
tristate "KUnit tests for SoC utils"
depends on KUNIT
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 8376fdb217ed..f90f5300b36e 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -12,6 +12,10 @@ ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST),)
obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST) += soc-topology-test.o
endif
+ifneq ($(CONFIG_SND_SOC_CARD_KUNIT_TEST),)
+obj-$(CONFIG_SND_SOC_CARD_KUNIT_TEST) += soc-card-test.o
+endif
+
ifneq ($(CONFIG_SND_SOC_UTILS_KUNIT_TEST),)
# snd-soc-test-objs := soc-utils-test.o
obj-$(CONFIG_SND_SOC_UTILS_KUNIT_TEST) += soc-utils-test.o
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
index 8c8b1dcac628..5f35b90eab8d 100644
--- a/sound/soc/amd/acp/acp-pci.c
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -115,7 +115,10 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
goto unregister_dmic_dev;
}
- acp_init(chip);
+ ret = acp_init(chip);
+ if (ret)
+ goto unregister_dmic_dev;
+
res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL);
if (!res) {
ret = -ENOMEM;
@@ -133,11 +136,9 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
}
}
- if (flag == FLAG_AMD_LEGACY_ONLY_DMIC) {
- ret = check_acp_pdm(pci, chip);
- if (ret < 0)
- goto skip_pdev_creation;
- }
+ ret = check_acp_pdm(pci, chip);
+ if (ret < 0)
+ goto skip_pdev_creation;
chip->flag = flag;
memset(&pdevinfo, 0, sizeof(pdevinfo));
diff --git a/sound/soc/codecs/cs-amp-lib.c b/sound/soc/codecs/cs-amp-lib.c
index 01ef4db5407d..287ac01a3873 100644
--- a/sound/soc/codecs/cs-amp-lib.c
+++ b/sound/soc/codecs/cs-amp-lib.c
@@ -56,6 +56,11 @@ static int _cs_amp_write_cal_coeffs(struct cs_dsp *dsp,
dev_dbg(dsp->dev, "Calibration: Ambient=%#x, Status=%#x, CalR=%d\n",
data->calAmbient, data->calStatus, data->calR);
+ if (list_empty(&dsp->ctl_list)) {
+ dev_info(dsp->dev, "Calibration disabled due to missing firmware controls\n");
+ return -ENOENT;
+ }
+
ret = cs_amp_write_cal_coeff(dsp, controls, controls->ambient, data->calAmbient);
if (ret)
return ret;
diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c
index 860d5cda67bf..94685449f0f4 100644
--- a/sound/soc/codecs/cs42l43.c
+++ b/sound/soc/codecs/cs42l43.c
@@ -2364,7 +2364,8 @@ static int cs42l43_codec_runtime_resume(struct device *dev)
static int cs42l43_codec_suspend(struct device *dev)
{
- struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+ struct cs42l43_codec *priv = dev_get_drvdata(dev);
+ struct cs42l43 *cs42l43 = priv->core;
disable_irq(cs42l43->irq);
@@ -2373,7 +2374,8 @@ static int cs42l43_codec_suspend(struct device *dev)
static int cs42l43_codec_suspend_noirq(struct device *dev)
{
- struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+ struct cs42l43_codec *priv = dev_get_drvdata(dev);
+ struct cs42l43 *cs42l43 = priv->core;
enable_irq(cs42l43->irq);
@@ -2382,7 +2384,8 @@ static int cs42l43_codec_suspend_noirq(struct device *dev)
static int cs42l43_codec_resume(struct device *dev)
{
- struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+ struct cs42l43_codec *priv = dev_get_drvdata(dev);
+ struct cs42l43 *cs42l43 = priv->core;
enable_irq(cs42l43->irq);
@@ -2391,7 +2394,8 @@ static int cs42l43_codec_resume(struct device *dev)
static int cs42l43_codec_resume_noirq(struct device *dev)
{
- struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+ struct cs42l43_codec *priv = dev_get_drvdata(dev);
+ struct cs42l43 *cs42l43 = priv->core;
disable_irq(cs42l43->irq);
diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
index e8526844337d..93385f181d2c 100644
--- a/sound/soc/codecs/es8326.c
+++ b/sound/soc/codecs/es8326.c
@@ -404,9 +404,9 @@ static const struct _coeff_div coeff_div_v3[] = {
{125, 48000, 6000000, 0x04, 0x04, 0x1F, 0x2D, 0x8A, 0x0A, 0x27, 0x27},
{128, 8000, 1024000, 0x60, 0x00, 0x05, 0x75, 0x8A, 0x1B, 0x1F, 0x7F},
- {128, 16000, 2048000, 0x20, 0x00, 0x31, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
- {128, 44100, 5644800, 0xE0, 0x00, 0x01, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
- {128, 48000, 6144000, 0xE0, 0x00, 0x01, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
+ {128, 16000, 2048000, 0x20, 0x00, 0x31, 0x35, 0x08, 0x19, 0x1F, 0x3F},
+ {128, 44100, 5644800, 0xE0, 0x00, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
+ {128, 48000, 6144000, 0xE0, 0x00, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
{144, 8000, 1152000, 0x20, 0x00, 0x03, 0x35, 0x8A, 0x1B, 0x23, 0x47},
{144, 16000, 2304000, 0x20, 0x00, 0x11, 0x35, 0x8A, 0x1B, 0x23, 0x47},
{192, 8000, 1536000, 0x60, 0x02, 0x0D, 0x75, 0x8A, 0x1B, 0x1F, 0x7F},
@@ -415,10 +415,10 @@ static const struct _coeff_div coeff_div_v3[] = {
{200, 48000, 9600000, 0x04, 0x04, 0x0F, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
{250, 48000, 12000000, 0x04, 0x04, 0x0F, 0x2D, 0xCA, 0x0A, 0x27, 0x27},
- {256, 8000, 2048000, 0x60, 0x00, 0x31, 0x35, 0x8A, 0x1B, 0x1F, 0x7F},
- {256, 16000, 4096000, 0x20, 0x00, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
- {256, 44100, 11289600, 0xE0, 0x00, 0x30, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
- {256, 48000, 12288000, 0xE0, 0x00, 0x30, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
+ {256, 8000, 2048000, 0x60, 0x00, 0x31, 0x35, 0x08, 0x19, 0x1F, 0x7F},
+ {256, 16000, 4096000, 0x20, 0x00, 0x01, 0x35, 0x08, 0x19, 0x1F, 0x3F},
+ {256, 44100, 11289600, 0xE0, 0x01, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
+ {256, 48000, 12288000, 0xE0, 0x01, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
{288, 8000, 2304000, 0x20, 0x00, 0x01, 0x35, 0x8A, 0x1B, 0x23, 0x47},
{384, 8000, 3072000, 0x60, 0x02, 0x05, 0x75, 0x8A, 0x1B, 0x1F, 0x7F},
{384, 16000, 6144000, 0x20, 0x02, 0x03, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
@@ -427,10 +427,10 @@ static const struct _coeff_div coeff_div_v3[] = {
{400, 48000, 19200000, 0xE4, 0x04, 0x35, 0x6d, 0xCA, 0x0A, 0x1F, 0x1F},
{500, 48000, 24000000, 0xF8, 0x04, 0x3F, 0x6D, 0xCA, 0x0A, 0x1F, 0x1F},
- {512, 8000, 4096000, 0x60, 0x00, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x7F},
- {512, 16000, 8192000, 0x20, 0x00, 0x30, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
- {512, 44100, 22579200, 0xE0, 0x00, 0x00, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
- {512, 48000, 24576000, 0xE0, 0x00, 0x00, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
+ {512, 8000, 4096000, 0x60, 0x00, 0x01, 0x08, 0x19, 0x1B, 0x1F, 0x7F},
+ {512, 16000, 8192000, 0x20, 0x00, 0x30, 0x35, 0x08, 0x19, 0x1F, 0x3F},
+ {512, 44100, 22579200, 0xE0, 0x00, 0x00, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
+ {512, 48000, 24576000, 0xE0, 0x00, 0x00, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
{768, 8000, 6144000, 0x60, 0x02, 0x11, 0x35, 0x8A, 0x1B, 0x1F, 0x7F},
{768, 16000, 12288000, 0x20, 0x02, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
{768, 32000, 24576000, 0xE0, 0x02, 0x30, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
@@ -827,7 +827,6 @@ static void es8326_jack_detect_handler(struct work_struct *work)
dev_dbg(comp->dev, "Report hp remove event\n");
snd_soc_jack_report(es8326->jack, 0, SND_JACK_HEADSET);
/* mute adc when mic path switch */
- regmap_write(es8326->regmap, ES8326_ADC_SCALE, 0x33);
regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x44);
regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66);
es8326->hp = 0;
@@ -835,6 +834,7 @@ static void es8326_jack_detect_handler(struct work_struct *work)
regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x0a);
regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x03);
+ regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9);
/*
* Inverted HPJACK_POL bit to trigger one IRQ to double check HP Removal event
*/
@@ -857,6 +857,8 @@ static void es8326_jack_detect_handler(struct work_struct *work)
* set auto-check mode, then restart jack_detect_work after 400ms.
* Don't report jack status.
*/
+ regmap_write(es8326->regmap, ES8326_INT_SOURCE,
+ (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON));
regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
es8326_enable_micbias(es8326->component);
usleep_range(50000, 70000);
@@ -883,7 +885,6 @@ static void es8326_jack_detect_handler(struct work_struct *work)
snd_soc_jack_report(es8326->jack,
SND_JACK_HEADSET, SND_JACK_HEADSET);
- regmap_write(es8326->regmap, ES8326_ADC_SCALE, 0x33);
regmap_update_bits(es8326->regmap, ES8326_PGA_PDN,
0x08, 0x08);
regmap_update_bits(es8326->regmap, ES8326_PGAGAIN,
@@ -979,7 +980,7 @@ static int es8326_resume(struct snd_soc_component *component)
regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x0E);
regmap_write(es8326->regmap, ES8326_ANA_LP, 0xf0);
usleep_range(10000, 15000);
- regmap_write(es8326->regmap, ES8326_HPJACK_TIMER, 0xe9);
+ regmap_write(es8326->regmap, ES8326_HPJACK_TIMER, 0xd9);
regmap_write(es8326->regmap, ES8326_ANA_MICBIAS, 0xcb);
/* set headphone default type and detect pin */
regmap_write(es8326->regmap, ES8326_HPDET_TYPE, 0x83);
@@ -1030,8 +1031,7 @@ static int es8326_resume(struct snd_soc_component *component)
es8326_enable_micbias(es8326->component);
usleep_range(50000, 70000);
regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00);
- regmap_write(es8326->regmap, ES8326_INT_SOURCE,
- (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON));
+ regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9);
regmap_write(es8326->regmap, ES8326_INTOUT_IO,
es8326->interrupt_clk);
regmap_write(es8326->regmap, ES8326_SDINOUT1_IO,
@@ -1052,6 +1052,8 @@ static int es8326_resume(struct snd_soc_component *component)
es8326->hp = 0;
es8326->hpl_vol = 0x03;
es8326->hpr_vol = 0x03;
+
+ es8326_irq(es8326->irq, es8326);
return 0;
}
@@ -1062,6 +1064,9 @@ static int es8326_suspend(struct snd_soc_component *component)
cancel_delayed_work_sync(&es8326->jack_detect_work);
es8326_disable_micbias(component);
es8326->calibrated = false;
+ regmap_write(es8326->regmap, ES8326_CLK_MUX, 0x2d);
+ regmap_write(es8326->regmap, ES8326_DAC2HPMIX, 0x00);
+ regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x3b);
regmap_write(es8326->regmap, ES8326_CLK_CTL, ES8326_CLK_OFF);
regcache_cache_only(es8326->regmap, true);
diff --git a/sound/soc/codecs/es8326.h b/sound/soc/codecs/es8326.h
index ee12caef8105..c3e52e7bdef5 100644
--- a/sound/soc/codecs/es8326.h
+++ b/sound/soc/codecs/es8326.h
@@ -104,7 +104,7 @@
#define ES8326_MUTE (3 << 0)
/* ES8326_CLK_CTL */
-#define ES8326_CLK_ON (0x7e << 0)
+#define ES8326_CLK_ON (0x7f << 0)
#define ES8326_CLK_OFF (0 << 0)
/* ES8326_CLK_INV */
diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c
index 383e551f3bc7..26860882fd91 100644
--- a/sound/soc/codecs/max98373-sdw.c
+++ b/sound/soc/codecs/max98373-sdw.c
@@ -872,7 +872,6 @@ MODULE_DEVICE_TABLE(sdw, max98373_id);
static struct sdw_driver max98373_sdw_driver = {
.driver = {
.name = "max98373",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(max98373_of_match),
.acpi_match_table = ACPI_PTR(max98373_acpi_match),
.pm = &max98373_pm,
diff --git a/sound/soc/codecs/nau8325.c b/sound/soc/codecs/nau8325.c
new file mode 100644
index 000000000000..d65f73144597
--- /dev/null
+++ b/sound/soc/codecs/nau8325.c
@@ -0,0 +1,900 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// nau8325.c -- Nuvoton NAU8325 audio codec driver
+//
+// Copyright 2023 Nuvoton Technology Crop.
+// Author: Seven Lee <[email protected]>
+// David Lin <[email protected]>
+//
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include "nau8325.h"
+
+/* Range of Master Clock MCLK (Hz) */
+#define MASTER_CLK_MAX 49152000
+#define MASTER_CLK_MIN 2048000
+
+/* scaling for MCLK source */
+#define CLK_PROC_BYPASS (-1)
+
+/* the maximum CLK_DAC */
+#define CLK_DA_AD_MAX 6144000
+
+/* from MCLK input */
+#define MCLK_SRC 4
+
+static const struct nau8325_src_attr mclk_n1_div[] = {
+ { 1, 0x0 },
+ { 2, 0x1 },
+ { 3, 0x2 },
+};
+
+/* over sampling rate */
+static const struct nau8325_osr_attr osr_dac_sel[] = {
+ { 64, 2 }, /* OSR 64, SRC 1/4 */
+ { 256, 0 }, /* OSR 256, SRC 1 */
+ { 128, 1 }, /* OSR 128, SRC 1/2 */
+ { 0, 0 },
+ { 32, 3 }, /* OSR 32, SRC 1/8 */
+};
+
+static const struct nau8325_src_attr mclk_n2_div[] = {
+ { 0, 0x0 },
+ { 1, 0x1 },
+ { 2, 0x2 },
+ { 3, 0x3 },
+ { 4, 0x4 },
+};
+
+static const struct nau8325_src_attr mclk_n3_mult[] = {
+ { 0, 0x1 },
+ { 1, 0x2 },
+ { 2, 0x3 },
+ { 3, 0x4 },
+};
+
+/* Sample Rate and MCLK_SRC selections */
+static const struct nau8325_srate_attr target_srate_table[] = {
+ /* { FS, range, max, { MCLK source }} */
+ { 48000, 2, true, { 12288000, 19200000, 24000000 } },
+ { 16000, 1, false, { 4096000, 6400000, 8000000 } },
+ { 8000, 0, false, { 2048000, 3200000, 4000000 }},
+ { 44100, 2, true, { 11289600, 17640000, 22050000 }},
+ { 64000, 3, false, { 16384000, 25600000, 32000000 } },
+ { 96000, 3, true, { 24576000, 38400000, 48000000 } },
+ { 12000, 0, true, { 3072000, 4800000, 6000000 } },
+ { 24000, 1, true, { 6144000, 9600000, 12000000 } },
+ { 32000, 2, false, { 8192000, 12800000, 16000000 } },
+};
+
+static const struct reg_default nau8325_reg_defaults[] = {
+ { NAU8325_R00_HARDWARE_RST, 0x0000 },
+ { NAU8325_R01_SOFTWARE_RST, 0x0000 },
+ { NAU8325_R03_CLK_CTRL, 0x0000 },
+ { NAU8325_R04_ENA_CTRL, 0x0000 },
+ { NAU8325_R05_INTERRUPT_CTRL, 0x007f },
+ { NAU8325_R09_IRQOUT, 0x0000 },
+ { NAU8325_R0A_IO_CTRL, 0x0000 },
+ { NAU8325_R0B_PDM_CTRL, 0x0000 },
+ { NAU8325_R0C_TDM_CTRL, 0x0000 },
+ { NAU8325_R0D_I2S_PCM_CTRL1, 0x000a },
+ { NAU8325_R0E_I2S_PCM_CTRL2, 0x0000 },
+ { NAU8325_R0F_L_TIME_SLOT, 0x0000 },
+ { NAU8325_R10_R_TIME_SLOT, 0x0000 },
+ { NAU8325_R11_HPF_CTRL, 0x0000 },
+ { NAU8325_R12_MUTE_CTRL, 0x0000 },
+ { NAU8325_R13_DAC_VOLUME, 0xf3f3 },
+ { NAU8325_R29_DAC_CTRL1, 0x0081 },
+ { NAU8325_R2A_DAC_CTRL2, 0x0000 },
+ { NAU8325_R2C_ALC_CTRL1, 0x000e },
+ { NAU8325_R2D_ALC_CTRL2, 0x8400 },
+ { NAU8325_R2E_ALC_CTRL3, 0x0000 },
+ { NAU8325_R2F_ALC_CTRL4, 0x003f },
+ { NAU8325_R40_CLK_DET_CTRL, 0xa801 },
+ { NAU8325_R50_MIXER_CTRL, 0x0000 },
+ { NAU8325_R55_MISC_CTRL, 0x0000 },
+ { NAU8325_R60_BIAS_ADJ, 0x0000 },
+ { NAU8325_R61_ANALOG_CONTROL_1, 0x0000 },
+ { NAU8325_R62_ANALOG_CONTROL_2, 0x0000 },
+ { NAU8325_R63_ANALOG_CONTROL_3, 0x0000 },
+ { NAU8325_R64_ANALOG_CONTROL_4, 0x0000 },
+ { NAU8325_R65_ANALOG_CONTROL_5, 0x0000 },
+ { NAU8325_R66_ANALOG_CONTROL_6, 0x0000 },
+ { NAU8325_R69_CLIP_CTRL, 0x0000 },
+ { NAU8325_R73_RDAC, 0x0008 },
+};
+
+static bool nau8325_readable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case NAU8325_R02_DEVICE_ID ... NAU8325_R06_INT_CLR_STATUS:
+ case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME:
+ case NAU8325_R1D_DEBUG_READ1:
+ case NAU8325_R1F_DEBUG_READ2:
+ case NAU8325_R22_DEBUG_READ3:
+ case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2:
+ case NAU8325_R2C_ALC_CTRL1 ... NAU8325_R2F_ALC_CTRL4:
+ case NAU8325_R40_CLK_DET_CTRL:
+ case NAU8325_R49_TEST_STATUS ... NAU8325_R4A_ANALOG_READ:
+ case NAU8325_R50_MIXER_CTRL:
+ case NAU8325_R55_MISC_CTRL:
+ case NAU8325_R60_BIAS_ADJ ... NAU8325_R66_ANALOG_CONTROL_6:
+ case NAU8325_R69_CLIP_CTRL:
+ case NAU8325_R73_RDAC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool nau8325_writeable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case NAU8325_R00_HARDWARE_RST:
+ case NAU8325_R03_CLK_CTRL ... NAU8325_R06_INT_CLR_STATUS:
+ case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME:
+ case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2:
+ case NAU8325_R2C_ALC_CTRL1 ... NAU8325_R2F_ALC_CTRL4:
+ case NAU8325_R40_CLK_DET_CTRL:
+ case NAU8325_R50_MIXER_CTRL:
+ case NAU8325_R55_MISC_CTRL:
+ case NAU8325_R60_BIAS_ADJ ... NAU8325_R66_ANALOG_CONTROL_6:
+ case NAU8325_R69_CLIP_CTRL:
+ case NAU8325_R73_RDAC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool nau8325_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case NAU8325_R00_HARDWARE_RST ... NAU8325_R02_DEVICE_ID:
+ case NAU8325_R06_INT_CLR_STATUS:
+ case NAU8325_R1D_DEBUG_READ1:
+ case NAU8325_R1F_DEBUG_READ2:
+ case NAU8325_R22_DEBUG_READ3:
+ case NAU8325_R4A_ANALOG_READ:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const char * const nau8325_dac_oversampl_texts[] = {
+ "64", "256", "128", "32",
+};
+
+static const unsigned int nau8325_dac_oversampl_values[] = {
+ 0, 1, 2, 4,
+};
+
+static const struct soc_enum nau8325_dac_oversampl_enum =
+ SOC_VALUE_ENUM_SINGLE(NAU8325_R29_DAC_CTRL1,
+ NAU8325_DAC_OVERSAMPLE_SFT, 0x7,
+ ARRAY_SIZE(nau8325_dac_oversampl_texts),
+ nau8325_dac_oversampl_texts,
+ nau8325_dac_oversampl_values);
+
+static const DECLARE_TLV_DB_MINMAX_MUTE(dac_vol_tlv, -8000, 600);
+
+static const struct snd_kcontrol_new nau8325_snd_controls[] = {
+ SOC_ENUM("DAC Oversampling Rate", nau8325_dac_oversampl_enum),
+ SOC_DOUBLE_TLV("Speaker Volume", NAU8325_R13_DAC_VOLUME,
+ NAU8325_DAC_VOLUME_L_SFT, NAU8325_DAC_VOLUME_R_SFT,
+ NAU8325_DAC_VOLUME_R_EN, 0, dac_vol_tlv),
+ SOC_SINGLE("ALC Max Gain", NAU8325_R2C_ALC_CTRL1,
+ NAU8325_ALC_MAXGAIN_SFT, NAU8325_ALC_MAXGAIN_MAX, 0),
+ SOC_SINGLE("ALC Min Gain", NAU8325_R2C_ALC_CTRL1,
+ NAU8325_ALC_MINGAIN_SFT, NAU8325_ALC_MINGAIN_MAX, 0),
+ SOC_SINGLE("ALC Decay Timer", NAU8325_R2D_ALC_CTRL2,
+ NAU8325_ALC_DCY_SFT, NAU8325_ALC_DCY_MAX, 0),
+ SOC_SINGLE("ALC Attack Timer", NAU8325_R2D_ALC_CTRL2,
+ NAU8325_ALC_ATK_SFT, NAU8325_ALC_ATK_MAX, 0),
+ SOC_SINGLE("ALC Hold Time", NAU8325_R2D_ALC_CTRL2,
+ NAU8325_ALC_HLD_SFT, NAU8325_ALC_HLD_MAX, 0),
+ SOC_SINGLE("ALC Target Level", NAU8325_R2D_ALC_CTRL2,
+ NAU8325_ALC_LVL_SFT, NAU8325_ALC_LVL_MAX, 0),
+ SOC_SINGLE("ALC Enable Switch", NAU8325_R2E_ALC_CTRL3,
+ NAU8325_ALC_EN_SFT, 1, 0),
+};
+
+static int nau8325_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(nau8325->regmap, NAU8325_R12_MUTE_CTRL,
+ NAU8325_SOFT_MUTE, 0);
+ msleep(30);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Soft mute the output to prevent the pop noise. */
+ regmap_update_bits(nau8325->regmap, NAU8325_R12_MUTE_CTRL,
+ NAU8325_SOFT_MUTE, NAU8325_SOFT_MUTE);
+ msleep(30);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int nau8325_powerup_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);
+
+ if (nau8325->clock_detection)
+ return 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(nau8325->regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_PWRUP_DFT, NAU8325_PWRUP_DFT);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ regmap_update_bits(nau8325->regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_PWRUP_DFT, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget nau8325_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("Power Up", SND_SOC_NOPM, 0, 0,
+ nau8325_powerup_event, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("DACL", NULL, NAU8325_R04_ENA_CTRL,
+ NAU8325_DAC_LEFT_CH_EN_SFT, 0, nau8325_dac_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_DAC_E("DACR", NULL, NAU8325_R04_ENA_CTRL,
+ NAU8325_DAC_RIGHT_CH_EN_SFT, 0, nau8325_dac_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_AIF_IN("AIFRX", "Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_OUTPUT("SPKL"),
+ SND_SOC_DAPM_OUTPUT("SPKR"),
+};
+
+static const struct snd_soc_dapm_route nau8325_dapm_routes[] = {
+ { "DACL", NULL, "Power Up" },
+ { "DACR", NULL, "Power Up" },
+
+ { "DACL", NULL, "AIFRX" },
+ { "DACR", NULL, "AIFRX" },
+ { "SPKL", NULL, "DACL" },
+ { "SPKR", NULL, "DACR" },
+};
+
+static int nau8325_srate_clk_apply(struct nau8325 *nau8325,
+ const struct nau8325_srate_attr *srate_table,
+ int n1_sel, int mclk_mult_sel, int n2_sel)
+{
+ if (!srate_table || n2_sel < 0 || n2_sel >= ARRAY_SIZE(mclk_n2_div) ||
+ n1_sel < 0 || n1_sel >= ARRAY_SIZE(mclk_n1_div)) {
+ dev_dbg(nau8325->dev, "The CLK isn't supported.");
+ return -EINVAL;
+ }
+
+ regmap_update_bits(nau8325->regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_REG_SRATE_MASK | NAU8325_REG_DIV_MAX,
+ (srate_table->range << NAU8325_REG_SRATE_SFT) |
+ (srate_table->max ? NAU8325_REG_DIV_MAX : 0));
+ regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL,
+ NAU8325_MCLK_SRC_MASK, mclk_n2_div[n2_sel].val);
+ regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL,
+ NAU8325_CLK_MUL_SRC_MASK,
+ mclk_n1_div[n1_sel].val << NAU8325_CLK_MUL_SRC_SFT);
+
+ if (mclk_mult_sel != CLK_PROC_BYPASS) {
+ regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL,
+ NAU8325_MCLK_SEL_MASK,
+ mclk_n3_mult[mclk_mult_sel].val <<
+ NAU8325_MCLK_SEL_SFT);
+ } else {
+ regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL,
+ NAU8325_MCLK_SEL_MASK, 0);
+ }
+
+ switch (mclk_mult_sel) {
+ case 2:
+ regmap_update_bits(nau8325->regmap, NAU8325_R65_ANALOG_CONTROL_5,
+ NAU8325_MCLK4XEN_EN, NAU8325_MCLK4XEN_EN);
+ break;
+ case 3:
+ regmap_update_bits(nau8325->regmap, NAU8325_R65_ANALOG_CONTROL_5,
+ NAU8325_MCLK4XEN_EN | NAU8325_MCLK8XEN_EN,
+ NAU8325_MCLK4XEN_EN | NAU8325_MCLK8XEN_EN);
+ break;
+ default:
+ regmap_update_bits(nau8325->regmap, NAU8325_R65_ANALOG_CONTROL_5,
+ NAU8325_MCLK4XEN_EN | NAU8325_MCLK8XEN_EN, 0);
+ break;
+ }
+
+ return 0;
+}
+
+static int nau8325_clksrc_n2(struct nau8325 *nau8325,
+ const struct nau8325_srate_attr *srate_table,
+ int mclk, int *n2_sel)
+{
+ int i, mclk_src, ratio;
+
+ ratio = NAU8325_MCLK_FS_RATIO_NUM;
+ for (i = 0; i < ARRAY_SIZE(mclk_n2_div); i++) {
+ mclk_src = mclk >> mclk_n2_div[i].param;
+ if (srate_table->mclk_src[NAU8325_MCLK_FS_RATIO_256] == mclk_src) {
+ ratio = NAU8325_MCLK_FS_RATIO_256;
+ break;
+ } else if (srate_table->mclk_src[NAU8325_MCLK_FS_RATIO_400] == mclk_src) {
+ ratio = NAU8325_MCLK_FS_RATIO_400;
+ break;
+ } else if (srate_table->mclk_src[NAU8325_MCLK_FS_RATIO_500] == mclk_src) {
+ ratio = NAU8325_MCLK_FS_RATIO_500;
+ break;
+ }
+ }
+ if (ratio != NAU8325_MCLK_FS_RATIO_NUM)
+ *n2_sel = i;
+
+ return ratio;
+}
+
+static const struct nau8325_srate_attr *target_srate_attribute(int srate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(target_srate_table); i++)
+ if (target_srate_table[i].fs == srate)
+ break;
+
+ if (i == ARRAY_SIZE(target_srate_table))
+ goto proc_err;
+
+ return &target_srate_table[i];
+
+proc_err:
+ return NULL;
+}
+
+static int nau8325_clksrc_choose(struct nau8325 *nau8325,
+ const struct nau8325_srate_attr **srate_table,
+ int *n1_sel, int *mult_sel, int *n2_sel)
+{
+ int i, j, mclk, mclk_max, ratio, ratio_sel, n2_max;
+
+ if (!nau8325->mclk || !nau8325->fs)
+ goto proc_err;
+
+ /* select sampling rate and MCLK_SRC */
+ *srate_table = target_srate_attribute(nau8325->fs);
+ if (!*srate_table)
+ goto proc_err;
+
+ /* First check clock from MCLK directly, decide N2 for MCLK_SRC.
+ * If not good, consider 1/N1 and Multiplier.
+ */
+ ratio = nau8325_clksrc_n2(nau8325, *srate_table, nau8325->mclk, n2_sel);
+ if (ratio != NAU8325_MCLK_FS_RATIO_NUM) {
+ *n1_sel = 0;
+ *mult_sel = CLK_PROC_BYPASS;
+ *n2_sel = MCLK_SRC;
+ goto proc_done;
+ }
+
+ /* Get MCLK_SRC through 1/N, Multiplier, and then 1/N2. */
+ mclk_max = 0;
+ for (i = 0; i < ARRAY_SIZE(mclk_n1_div); i++) {
+ for (j = 0; j < ARRAY_SIZE(mclk_n3_mult); j++) {
+ mclk = nau8325->mclk << mclk_n3_mult[j].param;
+ mclk = mclk / mclk_n1_div[i].param;
+ ratio = nau8325_clksrc_n2(nau8325,
+ *srate_table, mclk, n2_sel);
+ if (ratio != NAU8325_MCLK_FS_RATIO_NUM &&
+ (mclk_max < mclk || i > *n1_sel)) {
+ mclk_max = mclk;
+ n2_max = *n2_sel;
+ *n1_sel = i;
+ *mult_sel = j;
+ ratio_sel = ratio;
+ goto proc_done;
+ }
+ }
+ }
+ if (mclk_max) {
+ *n2_sel = n2_max;
+ ratio = ratio_sel;
+ goto proc_done;
+ }
+
+proc_err:
+ dev_dbg(nau8325->dev, "The MCLK %d is invalid. It can't get MCLK_SRC of 256/400/500 FS (%d)",
+ nau8325->mclk, nau8325->fs);
+ return -EINVAL;
+proc_done:
+ dev_dbg(nau8325->dev, "nau8325->fs=%d,range=0x%x, %s, (n1,mu,n2,dmu):(%d,%d,%d), MCLK_SRC=%uHz (%d)",
+ nau8325->fs, (*srate_table)->range,
+ (*srate_table)->max ? "MAX" : "MIN",
+ *n1_sel == CLK_PROC_BYPASS ?
+ CLK_PROC_BYPASS : mclk_n1_div[*n1_sel].param,
+ *mult_sel == CLK_PROC_BYPASS ?
+ CLK_PROC_BYPASS : 1 << mclk_n3_mult[*mult_sel].param,
+ 1 << mclk_n2_div[*n2_sel].param,
+ (*srate_table)->mclk_src[ratio],
+ (*srate_table)->mclk_src[ratio] / nau8325->fs);
+
+ return 0;
+}
+
+static int nau8325_clock_config(struct nau8325 *nau8325)
+{
+ const struct nau8325_srate_attr *srate_table;
+ int ret, n1_sel, mult_sel, n2_sel;
+
+ ret = nau8325_clksrc_choose(nau8325, &srate_table,
+ &n1_sel, &mult_sel, &n2_sel);
+ if (ret)
+ goto err;
+
+ ret = nau8325_srate_clk_apply(nau8325, srate_table,
+ n1_sel, mult_sel, n2_sel);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ return ret;
+}
+
+static const struct nau8325_osr_attr *nau8325_get_osr(struct nau8325 *nau8325)
+{
+ unsigned int osr;
+
+ regmap_read(nau8325->regmap, NAU8325_R29_DAC_CTRL1, &osr);
+ osr &= NAU8325_DAC_OVERSAMPLE_MASK;
+ if (osr >= ARRAY_SIZE(osr_dac_sel))
+ return NULL;
+
+ return &osr_dac_sel[osr];
+}
+
+static int nau8325_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);
+ const struct nau8325_osr_attr *osr;
+
+ osr = nau8325_get_osr(nau8325);
+ if (!osr || !osr->osr)
+ return -EINVAL;
+
+ return snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE,
+ 0, CLK_DA_AD_MAX / osr->osr);
+}
+
+static int nau8325_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);
+ unsigned int val_len = 0;
+ const struct nau8325_osr_attr *osr;
+ int ret;
+
+ nau8325->fs = params_rate(params);
+ osr = nau8325_get_osr(nau8325);
+ if (!osr || !osr->osr || nau8325->fs * osr->osr > CLK_DA_AD_MAX) {
+ ret = -EINVAL;
+ goto err;
+ }
+ regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL,
+ NAU8325_CLK_DAC_SRC_MASK,
+ osr->clk_src << NAU8325_CLK_DAC_SRC_SFT);
+
+ ret = nau8325_clock_config(nau8325);
+ if (ret)
+ goto err;
+
+ switch (params_width(params)) {
+ case 16:
+ val_len |= NAU8325_I2S_DL_16;
+ break;
+ case 20:
+ val_len |= NAU8325_I2S_DL_20;
+ break;
+ case 24:
+ val_len |= NAU8325_I2S_DL_24;
+ break;
+ case 32:
+ val_len |= NAU8325_I2S_DL_32;
+ break;
+ default:
+ ret = -EINVAL;
+ goto err;
+ }
+
+ regmap_update_bits(nau8325->regmap, NAU8325_R0D_I2S_PCM_CTRL1,
+ NAU8325_I2S_DL_MASK, val_len);
+
+ return 0;
+
+err:
+ return ret;
+}
+
+static int nau8325_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_component *component = dai->component;
+ struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);
+ unsigned int ctrl1_val = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBC_CFC:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ ctrl1_val |= NAU8325_I2S_BP_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ ctrl1_val |= NAU8325_I2S_DF_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ ctrl1_val |= NAU8325_I2S_DF_LEFT;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ ctrl1_val |= NAU8325_I2S_DF_RIGTH;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ ctrl1_val |= NAU8325_I2S_DF_PCM_AB;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ ctrl1_val |= NAU8325_I2S_DF_PCM_AB;
+ ctrl1_val |= NAU8325_I2S_PCMB_EN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(nau8325->regmap, NAU8325_R0D_I2S_PCM_CTRL1,
+ NAU8325_I2S_DF_MASK | NAU8325_I2S_BP_MASK |
+ NAU8325_I2S_PCMB_EN, ctrl1_val);
+
+ return 0;
+}
+
+static int nau8325_set_sysclk(struct snd_soc_component *component, int clk_id,
+ int source, unsigned int freq, int dir)
+{
+ struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);
+
+ if (freq < MASTER_CLK_MIN || freq > MASTER_CLK_MAX) {
+ dev_dbg(nau8325->dev, "MCLK exceeds the range, MCLK:%d", freq);
+ return -EINVAL;
+ }
+
+ nau8325->mclk = freq;
+ dev_dbg(nau8325->dev, "MCLK %dHz", nau8325->mclk);
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver nau8325_component_driver = {
+ .set_sysclk = nau8325_set_sysclk,
+ .suspend_bias_off = true,
+ .controls = nau8325_snd_controls,
+ .num_controls = ARRAY_SIZE(nau8325_snd_controls),
+ .dapm_widgets = nau8325_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(nau8325_dapm_widgets),
+ .dapm_routes = nau8325_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(nau8325_dapm_routes),
+};
+
+static const struct snd_soc_dai_ops nau8325_dai_ops = {
+ .startup = nau8325_dai_startup,
+ .hw_params = nau8325_hw_params,
+ .set_fmt = nau8325_set_fmt,
+};
+
+#define NAU8325_RATES SNDRV_PCM_RATE_8000_96000
+#define NAU8325_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
+ | SNDRV_PCM_FMTBIT_S24_3LE)
+
+static struct snd_soc_dai_driver nau8325_dai = {
+ .name = NAU8325_CODEC_DAI,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = NAU8325_RATES,
+ .formats = NAU8325_FORMATS,
+ },
+ .ops = &nau8325_dai_ops,
+};
+
+static const struct regmap_config nau8325_regmap_config = {
+ .reg_bits = NAU8325_REG_ADDR_LEN,
+ .val_bits = NAU8325_REG_DATA_LEN,
+
+ .max_register = NAU8325_REG_MAX,
+ .readable_reg = nau8325_readable_reg,
+ .writeable_reg = nau8325_writeable_reg,
+ .volatile_reg = nau8325_volatile_reg,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = nau8325_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(nau8325_reg_defaults),
+};
+
+static void nau8325_reset_chip(struct regmap *regmap)
+{
+ regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0001);
+ regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0000);
+}
+
+static void nau8325_init_regs(struct nau8325 *nau8325)
+{
+ struct regmap *regmap = nau8325->regmap;
+ struct device *dev = nau8325->dev;
+
+ /* set ALC parameters */
+ regmap_update_bits(regmap, NAU8325_R2C_ALC_CTRL1,
+ NAU8325_ALC_MAXGAIN_MASK,
+ 0x7 << NAU8325_ALC_MAXGAIN_SFT);
+ regmap_update_bits(regmap, NAU8325_R2D_ALC_CTRL2,
+ NAU8325_ALC_DCY_MASK | NAU8325_ALC_ATK_MASK |
+ NAU8325_ALC_HLD_MASK, (0x5 << NAU8325_ALC_DCY_SFT) |
+ (0x3 << NAU8325_ALC_ATK_SFT) |
+ (0x5 << NAU8325_ALC_HLD_SFT));
+ /* Enable ALC to avoid signal distortion when battery low. */
+ if (nau8325->alc_enable)
+ regmap_update_bits(regmap, NAU8325_R2E_ALC_CTRL3,
+ NAU8325_ALC_EN, NAU8325_ALC_EN);
+ if (nau8325->clock_detection)
+ regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_CLKPWRUP_DIS |
+ NAU8325_PWRUP_DFT, 0);
+ else
+ regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_CLKPWRUP_DIS | NAU8325_PWRUP_DFT,
+ NAU8325_CLKPWRUP_DIS);
+ if (nau8325->clock_det_data)
+ regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_APWRUP_EN, NAU8325_APWRUP_EN);
+ else
+ regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_APWRUP_EN, 0);
+
+ /* DAC Reference Voltage Setting */
+ switch (nau8325->dac_vref_microvolt) {
+ case 1800000:
+ regmap_update_bits(regmap, NAU8325_R73_RDAC,
+ NAU8325_DACVREFSEL_MASK, 0 << NAU8325_DACVREFSEL_SFT);
+ break;
+ case 2700000:
+ regmap_update_bits(regmap, NAU8325_R73_RDAC,
+ NAU8325_DACVREFSEL_MASK, 1 << NAU8325_DACVREFSEL_SFT);
+ break;
+ case 2880000:
+ regmap_update_bits(regmap, NAU8325_R73_RDAC,
+ NAU8325_DACVREFSEL_MASK, 2 << NAU8325_DACVREFSEL_SFT);
+ break;
+ case 3060000:
+ regmap_update_bits(regmap, NAU8325_R73_RDAC,
+ NAU8325_DACVREFSEL_MASK, 3 << NAU8325_DACVREFSEL_SFT);
+ break;
+ default:
+ dev_dbg(dev, "Invalid dac-vref-microvolt %d", nau8325->dac_vref_microvolt);
+
+ }
+
+ /* DAC Reference Voltage Decoupling Capacitors. */
+ regmap_update_bits(regmap, NAU8325_R63_ANALOG_CONTROL_3,
+ NAU8325_CLASSD_COARSE_GAIN_MASK, 0x4);
+ /* Auto-Att Min Gain 0dB, Class-D N Driver Slew Rate -25%. */
+ regmap_update_bits(regmap, NAU8325_R64_ANALOG_CONTROL_4,
+ NAU8325_CLASSD_SLEWN_MASK, 0x7);
+
+ /* VMID Tieoff (VMID Resistor Selection) */
+ switch (nau8325->vref_impedance_ohms) {
+ case 0:
+ regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ,
+ NAU8325_BIAS_VMID_SEL_MASK, 0 << NAU8325_BIAS_VMID_SEL_SFT);
+ break;
+ case 25000:
+ regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ,
+ NAU8325_BIAS_VMID_SEL_MASK, 1 << NAU8325_BIAS_VMID_SEL_SFT);
+ break;
+ case 125000:
+ regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ,
+ NAU8325_BIAS_VMID_SEL_MASK, 2 << NAU8325_BIAS_VMID_SEL_SFT);
+ break;
+ case 2500:
+ regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ,
+ NAU8325_BIAS_VMID_SEL_MASK, 3 << NAU8325_BIAS_VMID_SEL_SFT);
+ break;
+ default:
+ dev_dbg(dev, "Invalid vref-impedance-ohms %d", nau8325->vref_impedance_ohms);
+ }
+
+
+ /* enable VMID, BIAS, DAC, DCA CLOCK, Voltage/Current Amps
+ */
+ regmap_update_bits(regmap, NAU8325_R61_ANALOG_CONTROL_1,
+ NAU8325_DACEN_MASK | NAU8325_DACCLKEN_MASK |
+ NAU8325_DACEN_R_MASK | NAU8325_DACCLKEN_R_MASK |
+ NAU8325_CLASSDEN_MASK | NAU8325_VMDFSTENB_MASK |
+ NAU8325_BIASEN_MASK | NAU8325_VMIDEN_MASK,
+ (0x1 << NAU8325_DACEN_SFT) |
+ (0x1 << NAU8325_DACCLKEN_SFT) |
+ (0x1 << NAU8325_DACEN_R_SFT) |
+ (0x1 << NAU8325_DACCLKEN_R_SFT) |
+ (0x1 << NAU8325_CLASSDEN_SFT) |
+ (0x1 << NAU8325_VMDFSTENB_SFT) |
+ (0x1 << NAU8325_BIASEN_SFT) | 0x3);
+
+ /* Enable ALC to avoid signal distortion when battery low. */
+ if (nau8325->alc_enable)
+ regmap_update_bits(regmap, NAU8325_R2E_ALC_CTRL3,
+ NAU8325_ALC_EN, NAU8325_ALC_EN);
+ if (nau8325->clock_det_data)
+ regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_APWRUP_EN, NAU8325_APWRUP_EN);
+ else
+ regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_APWRUP_EN, 0);
+ if (nau8325->clock_detection)
+ regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_CLKPWRUP_DIS |
+ NAU8325_PWRUP_DFT, 0);
+ else
+ regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,
+ NAU8325_CLKPWRUP_DIS | NAU8325_PWRUP_DFT,
+ NAU8325_CLKPWRUP_DIS);
+ regmap_update_bits(regmap, NAU8325_R29_DAC_CTRL1,
+ NAU8325_DAC_OVERSAMPLE_MASK,
+ NAU8325_DAC_OVERSAMPLE_128);
+}
+
+static void nau8325_print_device_properties(struct nau8325 *nau8325)
+{
+ struct device *dev = nau8325->dev;
+
+ dev_dbg(dev, "vref-impedance-ohms: %d", nau8325->vref_impedance_ohms);
+ dev_dbg(dev, "dac-vref-microvolt: %d", nau8325->dac_vref_microvolt);
+ dev_dbg(dev, "alc-enable: %d", nau8325->alc_enable);
+ dev_dbg(dev, "clock-det-data: %d", nau8325->clock_det_data);
+ dev_dbg(dev, "clock-detection-disable: %d", nau8325->clock_detection);
+}
+
+static int nau8325_read_device_properties(struct device *dev,
+ struct nau8325 *nau8325)
+{
+ int ret;
+
+ nau8325->alc_enable =
+ device_property_read_bool(dev, "nuvoton,alc-enable");
+ nau8325->clock_det_data =
+ device_property_read_bool(dev, "nuvoton,clock-det-data");
+ nau8325->clock_detection =
+ !device_property_read_bool(dev, "nuvoton,clock-detection-disable");
+
+ ret = device_property_read_u32(dev, "nuvoton,vref-impedance-ohms",
+ &nau8325->vref_impedance_ohms);
+ if (ret)
+ nau8325->vref_impedance_ohms = 125000;
+ ret = device_property_read_u32(dev, "nuvoton,dac-vref-microvolt",
+ &nau8325->dac_vref_microvolt);
+ if (ret)
+ nau8325->dac_vref_microvolt = 2880000;
+
+ return 0;
+}
+
+static int nau8325_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &i2c->dev;
+ struct nau8325 *nau8325 = dev_get_platdata(dev);
+ int ret, value;
+
+ if (!nau8325) {
+ nau8325 = devm_kzalloc(dev, sizeof(*nau8325), GFP_KERNEL);
+ if (!nau8325) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ ret = nau8325_read_device_properties(dev, nau8325);
+ if (ret)
+ goto err;
+ }
+ i2c_set_clientdata(i2c, nau8325);
+
+ nau8325->regmap = devm_regmap_init_i2c(i2c, &nau8325_regmap_config);
+ if (IS_ERR(nau8325->regmap)) {
+ ret = PTR_ERR(nau8325->regmap);
+ goto err;
+ }
+ nau8325->dev = dev;
+ nau8325_print_device_properties(nau8325);
+
+ nau8325_reset_chip(nau8325->regmap);
+ ret = regmap_read(nau8325->regmap, NAU8325_R02_DEVICE_ID, &value);
+ if (ret) {
+ dev_dbg(dev, "Failed to read device id (%d)", ret);
+ goto err;
+ }
+ nau8325_init_regs(nau8325);
+
+ ret = devm_snd_soc_register_component(dev, &nau8325_component_driver,
+ &nau8325_dai, 1);
+err:
+ return ret;
+}
+
+static const struct i2c_device_id nau8325_i2c_ids[] = {
+ { "nau8325", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, nau8325_i2c_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id nau8325_of_ids[] = {
+ { .compatible = "nuvoton,nau8325", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, nau8325_of_ids);
+#endif
+
+static struct i2c_driver nau8325_i2c_driver = {
+ .driver = {
+ .name = "nau8325",
+ .of_match_table = of_match_ptr(nau8325_of_ids),
+ },
+ .probe = nau8325_i2c_probe,
+ .id_table = nau8325_i2c_ids,
+};
+module_i2c_driver(nau8325_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC NAU8325 driver");
+MODULE_AUTHOR("Seven Lee <[email protected]>");
+MODULE_AUTHOR("David Lin <[email protected]>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/nau8325.h b/sound/soc/codecs/nau8325.h
new file mode 100644
index 000000000000..0d173b66a4d4
--- /dev/null
+++ b/sound/soc/codecs/nau8325.h
@@ -0,0 +1,391 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * nau8325.h -- Nuvoton NAU8325 audio codec driver
+ *
+ * Copyright 2023 Nuvoton Technology Crop.
+ * Author: Seven Lee <[email protected]>
+ * David Lin <[email protected]>
+ */
+
+#ifndef __NAU8325_H__
+#define __NAU8325_H__
+
+#define NAU8325_R00_HARDWARE_RST 0x00
+#define NAU8325_R01_SOFTWARE_RST 0x01
+#define NAU8325_R02_DEVICE_ID 0x02
+#define NAU8325_R03_CLK_CTRL 0x03
+#define NAU8325_R04_ENA_CTRL 0x04
+#define NAU8325_R05_INTERRUPT_CTRL 0x05
+#define NAU8325_R06_INT_CLR_STATUS 0x06
+#define NAU8325_R09_IRQOUT 0x09
+#define NAU8325_R0A_IO_CTRL 0x0a
+#define NAU8325_R0B_PDM_CTRL 0x0b
+#define NAU8325_R0C_TDM_CTRL 0x0c
+#define NAU8325_R0D_I2S_PCM_CTRL1 0x0d
+#define NAU8325_R0E_I2S_PCM_CTRL2 0x0e
+#define NAU8325_R0F_L_TIME_SLOT 0x0f
+#define NAU8325_R10_R_TIME_SLOT 0x10
+#define NAU8325_R11_HPF_CTRL 0x11
+#define NAU8325_R12_MUTE_CTRL 0x12
+#define NAU8325_R13_DAC_VOLUME 0x13
+#define NAU8325_R1D_DEBUG_READ1 0x1d
+#define NAU8325_R1F_DEBUG_READ2 0x1f
+#define NAU8325_R22_DEBUG_READ3 0x22
+#define NAU8325_R29_DAC_CTRL1 0x29
+#define NAU8325_R2A_DAC_CTRL2 0x2a
+#define NAU8325_R2C_ALC_CTRL1 0x2c
+#define NAU8325_R2D_ALC_CTRL2 0x2d
+#define NAU8325_R2E_ALC_CTRL3 0x2e
+#define NAU8325_R2F_ALC_CTRL4 0x2f
+#define NAU8325_R40_CLK_DET_CTRL 0x40
+#define NAU8325_R49_TEST_STATUS 0x49
+#define NAU8325_R4A_ANALOG_READ 0x4a
+#define NAU8325_R50_MIXER_CTRL 0x50
+#define NAU8325_R55_MISC_CTRL 0x55
+#define NAU8325_R60_BIAS_ADJ 0x60
+#define NAU8325_R61_ANALOG_CONTROL_1 0x61
+#define NAU8325_R62_ANALOG_CONTROL_2 0x62
+#define NAU8325_R63_ANALOG_CONTROL_3 0x63
+#define NAU8325_R64_ANALOG_CONTROL_4 0x64
+#define NAU8325_R65_ANALOG_CONTROL_5 0x65
+#define NAU8325_R66_ANALOG_CONTROL_6 0x66
+#define NAU8325_R69_CLIP_CTRL 0x69
+#define NAU8325_R73_RDAC 0x73
+#define NAU8325_REG_MAX NAU8325_R73_RDAC
+
+/* 16-bit control register address, and 16-bits control register data */
+#define NAU8325_REG_ADDR_LEN 16
+#define NAU8325_REG_DATA_LEN 16
+
+/* CLK_CTRL (0x03) */
+#define NAU8325_CLK_DAC_SRC_SFT 12
+#define NAU8325_CLK_DAC_SRC_MASK (0x3 << NAU8325_CLK_DAC_SRC_SFT)
+#define NAU8325_CLK_MUL_SRC_SFT 6
+#define NAU8325_CLK_MUL_SRC_MASK (0x3 << NAU8325_CLK_MUL_SRC_SFT)
+#define NAU8325_MCLK_SEL_SFT 3
+#define NAU8325_MCLK_SEL_MASK (0x7 << NAU8325_MCLK_SEL_SFT)
+#define NAU8325_MCLK_SRC_MASK 0x7
+
+/* ENA_CTRL (0x04) */
+#define NAU8325_DAC_LEFT_CH_EN_SFT 3
+#define NAU8325_DAC_LEFT_CH_EN (0x1 << NAU8325_DAC_LEFT_CH_EN_SFT)
+#define NAU8325_DAC_RIGHT_CH_EN_SFT 2
+#define NAU8325_DAC_RIGHT_CH_EN (0x1 << NAU8325_DAC_RIGHT_CH_EN_SFT)
+
+/* INTERRUPT_CTRL (0x05) */
+#define NAU8325_ARP_DWN_INT_SFT 12
+#define NAU8325_ARP_DWN_INT_MASK (0x1 << NAU8325_ARP_DWN_INT_SFT)
+#define NAU8325_CLIP_INT_SFT 11
+#define NAU8325_CLIP_INT_MASK (0x1 << NAU8325_CLIP_INT_SFT)
+#define NAU8325_LVD_INT_SFT 10
+#define NAU8325_LVD_INT_MASK (0x1 << NAU8325_LVD_INT_SFT)
+#define NAU8325_PWR_INT_DIS_SFT 8
+#define NAU8325_PWR_INT_DIS (0x1 << NAU8325_PWR_INT_DIS_SFT)
+#define NAU8325_OCP_OTP_SHTDWN_INT_SFT 4
+#define NAU8325_OCP_OTP_SHTDWN_INT_MASK (0x1 << NAU8325_OCP_OTP_SHTDWN_INT_SFT)
+#define NAU8325_CLIP_INT_DIS_SFT 3
+#define NAU8325_CLIP_INT_DIS (0x1 << NAU8325_CLIP_INT_DIS_SFT)
+#define NAU8325_LVD_INT_DIS_SFT 2
+#define NAU8325_LVD_INT_DIS (0x1 << NAU8325_LVD_INT_DIS_SFT)
+#define NAU8325_PWR_INT_MASK 0x1
+
+/* INT_CLR_STATUS (0x06) */
+#define NAU8325_INT_STATUS_MASK 0x7f
+
+/* IRQOUT (0x9) */
+#define NAU8325_IRQOUT_SEL_SEF 12
+#define NAU8325_IRQOUT_SEL_MASK (0xf << NAU8325_IRQOUT_SEL_SEF)
+#define NAU8325_DEM_DITH_SFT 7
+#define NAU8325_DEM_DITH_EN (0x1 << NAU8325_DEM_DITH_SFT)
+#define NAU8325_GAINZI3_SFT 5
+#define NAU8325_GAINZI3_MASK (0x1 << NAU8325_GAINZI3_SFT)
+#define NAU8325_GAINZI2_MASK 0x1f
+
+/* IO_CTRL (0x0a) */
+#define NAU8325_IRQ_PL_SFT 15
+#define NAU8325_IRQ_PL_ACT_HIGH (0x1 << NAU8325_IRQ_PL_SFT)
+#define NAU8325_IRQ_PS_SFT 14
+#define NAU8325_IRQ_PS_UP (0x1 << NAU8325_IRQ_PS_SFT)
+#define NAU8325_IRQ_PE_SFT 13
+#define NAU8325_IRQ_PE_EN (0x1 << NAU8325_IRQ_PE_SFT)
+#define NAU8325_IRQ_DS_SFT 12
+#define NAU8325_IRQ_DS_HIGH (0x1 << NAU8325_IRQ_DS_SFT)
+#define NAU8325_IRQ_OUTPUT_SFT 11
+#define NAU8325_IRQ_OUTPUT_EN (0x1 << NAU8325_IRQ_OUTPUT_SFT)
+#define NAU8325_IRQ_PIN_DEBUG_SFT 10
+#define NAU8325_IRQ_PIN_DEBUG_EN (0x1 << NAU8325_IRQ_PIN_DEBUG_SFT)
+
+/* PDM_CTRL (0x0b) */
+#define NAU8325_PDM_LCH_EDGE_SFT 1
+#define NAU8325_PDM_LCH_EDGE__MASK (0x1 << NAU8325_PDM_LCH_EDGE_SFT)
+#define NAU8325_PDM_MODE_EN 0x1
+
+/* TDM_CTRL (0x0c) */
+#define NAU8325_TDM_SFT 15
+#define NAU8325_TDM_EN (0x1 << NAU8325_TDM_SFT)
+#define NAU8325_PCM_OFFSET_CTRL_SFT 14
+#define NAU8325_PCM_OFFSET_CTRL_EN (0x1 << NAU8325_PCM_OFFSET_CTRL_SFT)
+#define NAU8325_DAC_LEFT_SFT 6
+#define NAU8325_NAU8325_DAC_LEFT_MASK (0x7 << NAU8325_DAC_LEFT_SFT)
+#define NAU8325_DAC_RIGHT_SFT 3
+#define NAU8325_DAC_RIGHT_MASK (0x7 << NAU8325_DAC_RIGHT_SFT)
+
+/* I2S_PCM_CTRL1 (0x0d) */
+#define NAU8325_DACCM_CTL_SFT 14
+#define NAU8325_DACCM_CTL_MASK (0x3 << NAU8325_DACCM_CTL_SFT)
+#define NAU8325_CMB8_0_SFT 10
+#define NAU8325_CMB8_0_MASK (0x1 << NAU8325_CMB8_0_SFT)
+#define NAU8325_UA_OFFSET_SFT 9
+#define NAU8325_UA_OFFSET_MASK (0x1 << NAU8325_UA_OFFSET_SFT)
+#define NAU8325_I2S_BP_SFT 7
+#define NAU8325_I2S_BP_MASK (0x1 << NAU8325_I2S_BP_SFT)
+#define NAU8325_I2S_BP_INV (0x1 << NAU8325_I2S_BP_SFT)
+#define NAU8325_I2S_PCMB_SFT 6
+#define NAU8325_I2S_PCMB_EN (0x1 << NAU8325_I2S_PCMB_SFT)
+#define NAU8325_I2S_DACPSHS0_SFT 5
+#define NAU8325_I2S_DACPSHS0_MASK (0x1 << NAU8325_I2S_DACPSHS0_SFT)
+#define NAU8325_I2S_DL_SFT 2
+#define NAU8325_I2S_DL_MASK (0x3 << NAU8325_I2S_DL_SFT)
+#define NAU8325_I2S_DL_32 (0x3 << NAU8325_I2S_DL_SFT)
+#define NAU8325_I2S_DL_24 (0x2 << NAU8325_I2S_DL_SFT)
+#define NAU8325_I2S_DL_20 (0x1 << NAU8325_I2S_DL_SFT)
+#define NAU8325_I2S_DL_16 (0x0 << NAU8325_I2S_DL_SFT)
+#define NAU8325_I2S_DF_MASK 0x3
+#define NAU8325_I2S_DF_RIGTH 0x0
+#define NAU8325_I2S_DF_LEFT 0x1
+#define NAU8325_I2S_DF_I2S 0x2
+#define NAU8325_I2S_DF_PCM_AB 0x3
+
+/* I2S_PCM_CTRL2 (0x0e) */
+#define NAU8325_PCM_TS_SFT 10
+#define NAU8325_PCM_TS_EN (0x1 << NAU8325_PCM_TS_SFT)
+#define NAU8325_PCM8BIT0_SFT 8
+#define NAU8325_PCM8BIT0_MASK (0x1 << NAU8325_PCM8BIT0_SFT)
+
+/* L_TIME_SLOT (0x0f)*/
+#define NAU8325_SHORT_FS_DET_SFT 13
+#define NAU8325_SHORT_FS_DET_DIS (0x1 << NAU8325_SHORT_FS_DET_SFT)
+#define NAU8325_TSLOT_L0_MASK 0x3ff
+
+/* R_TIME_SLOT (0x10)*/
+#define NAU8325_TSLOT_R0_MASK 0x3ff
+
+/* HPF_CTRL (0x11)*/
+#define NAU8325_DAC_HPF_SFT 15
+#define NAU8325_DAC_HPF_EN (0x1 << NAU8325_DAC_HPF_SFT)
+#define NAU8325_DAC_HPF_APP_SFT 14
+#define NAU8325_DAC_HPF_APP_MASK (0x1 << NAU8325_DAC_HPF_APP_SFT)
+#define NAU8325_DAC_HPF_FCUT_SFT 11
+#define NAU8325_DAC_HPF_FCUT_MASK (0x7 << NAU8325_DAC_HPF_FCUT_SFT)
+
+/* MUTE_CTRL (0x12)*/
+#define NAU8325_SOFT_MUTE_SFT 15
+#define NAU8325_SOFT_MUTE (0x1 << NAU8325_SOFT_MUTE_SFT)
+#define NAU8325_DAC_ZC_SFT 8
+#define NAU8325_DAC_ZC_EN (0x1 << NAU8325_DAC_ZC_SFT)
+#define NAU8325_UNMUTE_CTL_SFT 6
+#define NAU8325_UNMUTE_CTL_MASK (0x3 << NAU8325_UNMUTE_CTL_SFT)
+#define NAU8325_ANA_MUTE_SFT 4
+#define NAU8325_ANA_MUTE_MASK (0x3 << NAU8325_ANA_MUTE_SFT)
+#define NAU8325_AUTO_MUTE_SFT 3
+#define NAU8325_AUTO_MUTE_DIS (0x1 << NAU8325_AUTO_MUTE_SFT)
+
+/* DAC_VOLUME (0x13) */
+#define NAU8325_DAC_VOLUME_L_SFT 8
+#define NAU8325_DAC_VOLUME_L_EN (0xff << NAU8325_DAC_VOLUME_L_SFT)
+#define NAU8325_DAC_VOLUME_R_SFT 0
+#define NAU8325_DAC_VOLUME_R_EN (0xff << NAU8325_DAC_VOLUME_R_SFT)
+#define NAU8325_DAC_VOL_MAX 0xff
+
+/* DEBUG_READ1 (0x1d)*/
+#define NAU8325_OSR100_MASK (0x1 << 6)
+#define NAU8325_MIPS500_MASK (0x1 << 5)
+#define NAU8325_SHUTDWNDRVR_R_MASK (0x1 << 4)
+#define NAU8325_SHUTDWNDRVR_L_MASK (0x1 << 3)
+#define NAU8325_MUTEB_MASK (0x1 << 2)
+#define NAU8325_PDOSCB_MASK (0x1 << 1)
+#define NAU8325_POWERDOWN1B_D_MASK 0x1
+
+/* DEBUG_READ2 (0x1f)*/
+#define NAU8325_R_CHANNEL_Vol_SFT 8
+#define NAU8325_R_CHANNEL_Vol_MASK (0xff << NAU8325_R_CHANNEL_Vol_SFT)
+#define NAU8325_L_CHANNEL_Vol_MASK 0xff
+
+/* DEBUG_READ3(0x22)*/
+#define NAU8325_PGAL_GAIN_MASK (0x3f << 7)
+#define NAU8325_CLIP_MASK (0x1 << 6)
+#define NAU8325_SCAN_MODE_MASK (0x1 << 5)
+#define NAU8325_SDB_MASK (0x1 << 4)
+#define NAU8325_TALARM_MASK (0x1 << 3)
+#define NAU8325_SHORTR_MASK (0x1 << 2)
+#define NAU8325_SHORTL_MASK (0x1 << 1)
+#define NAU8325_TMDET_MASK 0x1
+
+/* DAC_CTRL1 (0x29) */
+#define NAU8325_DAC_OVERSAMPLE_SFT 0
+#define NAU8325_DAC_OVERSAMPLE_MASK 0x7
+#define NAU8325_DAC_OVERSAMPLE_256 1
+#define NAU8325_DAC_OVERSAMPLE_128 2
+#define NAU8325_DAC_OVERSAMPLE_64 0
+#define NAU8325_DAC_OVERSAMPLE_32 4
+
+/* ALC_CTRL1 (0x2c) */
+#define NAU8325_ALC_MAXGAIN_SFT 5
+#define NAU8325_ALC_MAXGAIN_MAX 0x7
+#define NAU8325_ALC_MAXGAIN_MASK (0x7 << NAU8325_ALC_MAXGAIN_SFT)
+#define NAU8325_ALC_MINGAIN_MAX 4
+#define NAU8325_ALC_MINGAIN_SFT 1
+#define NAU8325_ALC_MINGAIN_MASK (0x7 << NAU8325_ALC_MINGAIN_SFT)
+
+/* ALC_CTRL2 (0x2d) */
+#define NAU8325_ALC_DCY_SFT 12
+#define NAU8325_ALC_DCY_MAX 0xb
+#define NAU8325_ALC_DCY_MASK (0xf << NAU8325_ALC_DCY_SFT)
+#define NAU8325_ALC_ATK_SFT 8
+#define NAU8325_ALC_ATK_MAX 0xb
+#define NAU8325_ALC_ATK_MASK (0xf << NAU8325_ALC_ATK_SFT)
+#define NAU8325_ALC_HLD_SFT 4
+#define NAU8325_ALC_HLD_MAX 0xa
+#define NAU8325_ALC_HLD_MASK (0xf << NAU8325_ALC_HLD_SFT)
+#define NAU8325_ALC_LVL_SFT 0
+#define NAU8325_ALC_LVL_MAX 0xf
+#define NAU8325_ALC_LVL_MASK 0xf
+
+/* ALC_CTRL3 (0x2e) */
+#define NAU8325_ALC_EN_SFT 15
+#define NAU8325_ALC_EN (0x1 << NAU8325_ALC_EN_SFT)
+
+/* TEMP_COMP_CTRL (0x30) */
+#define NAU8325_TEMP_COMP_ACT2_MASK 0xff
+
+/* LPF_CTRL (0x33) */
+#define NAU8325_LPF_IN1_EN_SFT 15
+#define NAU8325_LPF_IN1_EN (0x1 << NAU8325_LPF_IN1_EN_SFT)
+#define NAU8325_LPF_IN1_TC_SFT 11
+#define NAU8325_LPF_IN1_TC_MASK (0xf << NAU8325_LPF_IN1_TC_SFT)
+#define NAU8325_LPF_IN2_EN_SFT 10
+#define NAU8325_LPF_IN2_EN (0x1 << NAU8325_LPF_IN2_EN_SFT)
+#define NAU8325_LPF_IN2_TC_SFT 6
+#define NAU8325_LPF_IN2_TC_MASK (0xf << NAU8325_LPF_IN2_TC_SFT)
+
+/* CLK_DET_CTRL (0x40) */
+#define NAU8325_APWRUP_SFT 15
+#define NAU8325_APWRUP_EN (0x1 << NAU8325_APWRUP_SFT)
+#define NAU8325_CLKPWRUP_SFT 14
+#define NAU8325_CLKPWRUP_DIS (0x1 << NAU8325_CLKPWRUP_SFT)
+#define NAU8325_PWRUP_DFT_SFT 13
+#define NAU8325_PWRUP_DFT (0x1 << NAU8325_PWRUP_DFT_SFT)
+#define NAU8325_REG_SRATE_SFT 10
+#define NAU8325_REG_SRATE_MASK (0x7 << NAU8325_REG_SRATE_SFT)
+#define NAU8325_REG_ALT_SRATE_SFT 9
+#define NAU8325_REG_ALT_SRATE_EN (0x1 << NAU8325_REG_ALT_SRATE_SFT)
+#define NAU8325_REG_DIV_MAX 0x1
+
+/* BIAS_ADJ (0x60) */
+#define NAU8325_BIAS_VMID_SEL_SFT 4
+#define NAU8325_BIAS_VMID_SEL_MASK (0x3 << NAU8325_BIAS_VMID_SEL_SFT)
+
+/* ANALOG_CONTROL_1 (0x61) */
+#define NAU8325_VMDFSTENB_SFT 14
+#define NAU8325_VMDFSTENB_MASK (0x3 << NAU8325_VMDFSTENB_SFT)
+#define NAU8325_CLASSDEN_SFT 12
+#define NAU8325_CLASSDEN_MASK (0x3 << NAU8325_CLASSDEN_SFT)
+#define NAU8325_DACCLKEN_R_SFT 10
+#define NAU8325_DACCLKEN_R_MASK (0x3 << NAU8325_DACCLKEN_R_SFT)
+#define NAU8325_DACEN_R_SFT 8
+#define NAU8325_DACEN_R_MASK (0x3 << NAU8325_DACEN_R_SFT)
+#define NAU8325_DACCLKEN_SFT 6
+#define NAU8325_DACCLKEN_MASK (0x3 << NAU8325_DACCLKEN_SFT)
+#define NAU8325_DACEN_SFT 4
+#define NAU8325_DACEN_MASK (0x3 << NAU8325_DACEN_SFT)
+#define NAU8325_BIASEN_SFT 2
+#define NAU8325_BIASEN_MASK (0x3 << NAU8325_BIASEN_SFT)
+#define NAU8325_VMIDEN_MASK 0x3
+
+/* ANALOG_CONTROL_2 (0x62) */
+#define NAU8325_PWMMOD_SFT 14
+#define NAU8325_PWMMOD_MASK (0x1 << NAU8325_PWMMOD_SFT)
+#define NAU8325_DACTEST_SFT 6
+#define NAU8325_DACTEST_MASK (0x3 << NAU8325_DACTEST_SFT)
+#define NAU8325_DACREFCAP_SFT 4
+#define NAU8325_DACREFCAP_MASK (0x3 << NAU8325_DACREFCAP_SFT)
+
+/* ANALOG_CONTROL_3 (0x63) */
+#define NAU8325_POWER_DOWN_L_SFT 12
+#define NAU8325_POWER_DOWN_L_MASK (0x3 << NAU8325_POWER_DOWN_L_SFT)
+#define NAU8325_POWER_DOWN_R_SFT 11
+#define NAU8325_POWER_DOWN_R_MASK (0x3 << NAU8325_DACREFCAP_SFT)
+#define NAU8325_CLASSD_FINE_SFT 5
+#define NAU8325_CLASSD_FINE_MASK (0x3 << NAU8325_CLASSD_FINE_SFT)
+#define NAU8325_CLASSD_COARSE_GAIN_MASK 0xf
+
+/* ANALOG_CONTROL_4 (0x64) */
+#define NAU8325_CLASSD_OCPN_SFT 12
+#define NAU8325_CLASSD_OCPN_MASK (0xf << NAU8325_CLASSD_OCPN_SFT)
+#define NAU8325_CLASSD_OCPP_SFT 8
+#define NAU8325_CLASSD_OCPP_MASK (0xf << NAU8325_CLASSD_OCPP_SFT)
+#define NAU8325_CLASSD_SLEWN_MASK 0xff
+
+/* ANALOG_CONTROL_5 (0x65) */
+#define NAU8325_MCLK_RANGE_SFT 2
+#define NAU8325_MCLK_RANGE_EN (0x1 << NAU8325_MCLK_RANGE_SFT)
+#define NAU8325_MCLK8XEN_SFT 1
+#define NAU8325_MCLK8XEN_EN (0x1 << NAU8325_MCLK8XEN_SFT)
+#define NAU8325_MCLK4XEN_EN 0x1
+
+/* ANALOG_CONTROL_6 (0x66) */
+#define NAU8325_VBATLOW_SFT 4
+#define NAU8325_VBATLOW_MASK (0x1 << NAU8325_VBATLOW_SFT)
+#define NAU8325_VDDSPK_LIM_SFT 3
+#define NAU8325_VDDSPK_LIM_EN (0x1 << NAU8325_VDDSPK_LIM_SFT)
+#define NAU8325_VDDSPK_LIM_MASK 0x7
+
+/* CLIP_CTRL (0x69)*/
+#define NAU8325_ANTI_CLIP_SFT 4
+#define NAU8325_ANTI_CLIP_EN (0x1 << NAU8325_ANTI_CLIP_SFT)
+
+/* RDAC (0x73) */
+#define NAU8325_CLK_DAC_DELAY_SFT 4
+#define NAU8325_CLK_DAC_DELAY_EN (0x7 << NAU8325_CLK_DAC_DELAY_SFT)
+#define NAU8325_DACVREFSEL_SFT 2
+#define NAU8325_DACVREFSEL_MASK (0x3 << NAU8325_DACVREFSEL_SFT)
+
+#define NAU8325_CODEC_DAI "nau8325-hifi"
+
+struct nau8325 {
+ struct device *dev;
+ struct regmap *regmap;
+ int mclk;
+ int fs;
+ int vref_impedance_ohms;
+ int dac_vref_microvolt;
+ int clock_detection;
+ int clock_det_data;
+ int alc_enable;
+};
+
+struct nau8325_src_attr {
+ int param;
+ unsigned int val;
+};
+
+enum {
+ NAU8325_MCLK_FS_RATIO_256,
+ NAU8325_MCLK_FS_RATIO_400,
+ NAU8325_MCLK_FS_RATIO_500,
+ NAU8325_MCLK_FS_RATIO_NUM,
+};
+
+struct nau8325_srate_attr {
+ int fs;
+ int range;
+ bool max;
+ unsigned int mclk_src[NAU8325_MCLK_FS_RATIO_NUM];
+};
+
+struct nau8325_osr_attr {
+ unsigned int osr;
+ unsigned int clk_src;
+};
+
+#endif /* __NAU8325_H__ */
diff --git a/sound/soc/codecs/rt1017-sdca-sdw.c b/sound/soc/codecs/rt1017-sdca-sdw.c
index 4dbbd8bdaaac..7c8103a0d562 100644
--- a/sound/soc/codecs/rt1017-sdca-sdw.c
+++ b/sound/soc/codecs/rt1017-sdca-sdw.c
@@ -809,7 +809,6 @@ static const struct dev_pm_ops rt1017_sdca_pm = {
static struct sdw_driver rt1017_sdca_sdw_driver = {
.driver = {
.name = "rt1017-sdca",
- .owner = THIS_MODULE,
.pm = &rt1017_sdca_pm,
},
.probe = rt1017_sdca_sdw_probe,
diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c
index 63d4abf964d4..563df483a466 100644
--- a/sound/soc/codecs/rt1308-sdw.c
+++ b/sound/soc/codecs/rt1308-sdw.c
@@ -804,7 +804,6 @@ static const struct dev_pm_ops rt1308_pm = {
static struct sdw_driver rt1308_sdw_driver = {
.driver = {
.name = "rt1308",
- .owner = THIS_MODULE,
.pm = &rt1308_pm,
},
.probe = rt1308_sdw_probe,
diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c
index 47511f70119a..22f1ed4e03f1 100644
--- a/sound/soc/codecs/rt1316-sdw.c
+++ b/sound/soc/codecs/rt1316-sdw.c
@@ -537,7 +537,7 @@ static int rt1316_sdw_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt1316->sdw_slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
+ dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@@ -577,12 +577,12 @@ static int rt1316_sdw_parse_dt(struct rt1316_sdw_priv *rt1316, struct device *de
if (rt1316->bq_params_cnt) {
rt1316->bq_params = devm_kzalloc(dev, rt1316->bq_params_cnt, GFP_KERNEL);
if (!rt1316->bq_params) {
- dev_err(dev, "Could not allocate bq_params memory\n");
+ dev_err(dev, "%s: Could not allocate bq_params memory\n", __func__);
ret = -ENOMEM;
} else {
ret = device_property_read_u8_array(dev, "realtek,bq-params", rt1316->bq_params, rt1316->bq_params_cnt);
if (ret < 0)
- dev_err(dev, "Could not read list of realtek,bq-params\n");
+ dev_err(dev, "%s: Could not read list of realtek,bq-params\n", __func__);
}
}
@@ -759,7 +759,7 @@ static int __maybe_unused rt1316_dev_resume(struct device *dev)
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT1316_PROBE_TIMEOUT));
if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;
@@ -781,7 +781,6 @@ static const struct dev_pm_ops rt1316_pm = {
static struct sdw_driver rt1316_sdw_driver = {
.driver = {
.name = "rt1316-sdca",
- .owner = THIS_MODULE,
.pm = &rt1316_pm,
},
.probe = rt1316_sdw_probe,
diff --git a/sound/soc/codecs/rt1318-sdw.c b/sound/soc/codecs/rt1318-sdw.c
index ff364bde4a08..319f71f5e60d 100644
--- a/sound/soc/codecs/rt1318-sdw.c
+++ b/sound/soc/codecs/rt1318-sdw.c
@@ -606,7 +606,7 @@ static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt1318->sdw_slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
+ dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@@ -631,8 +631,8 @@ static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream,
sampling_rate = RT1318_SDCA_RATE_192000HZ;
break;
default:
- dev_err(component->dev, "Rate %d is not supported\n",
- params_rate(params));
+ dev_err(component->dev, "%s: Rate %d is not supported\n",
+ __func__, params_rate(params));
return -EINVAL;
}
@@ -835,7 +835,7 @@ static int __maybe_unused rt1318_dev_resume(struct device *dev)
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT1318_PROBE_TIMEOUT));
if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
return -ETIMEDOUT;
}
@@ -855,7 +855,6 @@ static const struct dev_pm_ops rt1318_pm = {
static struct sdw_driver rt1318_sdw_driver = {
.driver = {
.name = "rt1318-sdca",
- .owner = THIS_MODULE,
.pm = &rt1318_pm,
},
.probe = rt1318_sdw_probe,
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
index e67c2e19cb1a..5edf11e136b4 100644
--- a/sound/soc/codecs/rt5682-sdw.c
+++ b/sound/soc/codecs/rt5682-sdw.c
@@ -132,7 +132,7 @@ static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt5682->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
+ dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@@ -315,8 +315,8 @@ static int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
&rt5682_sdw_indirect_regmap);
if (IS_ERR(rt5682->regmap)) {
ret = PTR_ERR(rt5682->regmap);
- dev_err(dev, "Failed to allocate register map: %d\n",
- ret);
+ dev_err(dev, "%s: Failed to allocate register map: %d\n",
+ __func__, ret);
return ret;
}
@@ -400,7 +400,7 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
}
if (val != DEVICE_ID) {
- dev_err(dev, "Device with ID register %x is not rt5682\n", val);
+ dev_err(dev, "%s: Device with ID register %x is not rt5682\n", __func__, val);
ret = -ENODEV;
goto err_nodev;
}
@@ -648,7 +648,7 @@ static int rt5682_bus_config(struct sdw_slave *slave,
ret = rt5682_clock_config(&slave->dev);
if (ret < 0)
- dev_err(&slave->dev, "Invalid clk config");
+ dev_err(&slave->dev, "%s: Invalid clk config", __func__);
return ret;
}
@@ -763,19 +763,19 @@ static int __maybe_unused rt5682_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
+ mutex_lock(&rt5682->disable_irq_lock);
if (rt5682->disable_irq == true) {
- mutex_lock(&rt5682->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
rt5682->disable_irq = false;
- mutex_unlock(&rt5682->disable_irq_lock);
}
+ mutex_unlock(&rt5682->disable_irq_lock);
goto regmap_sync;
}
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT5682_PROBE_TIMEOUT));
if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;
@@ -798,7 +798,6 @@ static const struct dev_pm_ops rt5682_pm = {
static struct sdw_driver rt5682_sdw_driver = {
.driver = {
.name = "rt5682",
- .owner = THIS_MODULE,
.pm = &rt5682_pm,
},
.probe = rt5682_sdw_probe,
diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c
index 52c33d56b143..24cb895b759f 100644
--- a/sound/soc/codecs/rt700-sdw.c
+++ b/sound/soc/codecs/rt700-sdw.c
@@ -558,7 +558,6 @@ static const struct dev_pm_ops rt700_pm = {
static struct sdw_driver rt700_sdw_driver = {
.driver = {
.name = "rt700",
- .owner = THIS_MODULE,
.pm = &rt700_pm,
},
.probe = rt700_sdw_probe,
diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c
index 0ebf344a1b60..434b926f96c8 100644
--- a/sound/soc/codecs/rt700.c
+++ b/sound/soc/codecs/rt700.c
@@ -37,8 +37,8 @@ static int rt700_index_write(struct regmap *regmap,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
- pr_err("Failed to set private value: %06x <= %04x ret=%d\n",
- addr, value, ret);
+ pr_err("%s: Failed to set private value: %06x <= %04x ret=%d\n",
+ __func__, addr, value, ret);
return ret;
}
@@ -52,8 +52,8 @@ static int rt700_index_read(struct regmap *regmap,
*value = 0;
ret = regmap_read(regmap, addr, value);
if (ret < 0)
- pr_err("Failed to get private value: %06x => %04x ret=%d\n",
- addr, *value, ret);
+ pr_err("%s: Failed to get private value: %06x => %04x ret=%d\n",
+ __func__, addr, *value, ret);
return ret;
}
@@ -930,14 +930,14 @@ static int rt700_pcm_hw_params(struct snd_pcm_substream *substream,
port_config.num += 2;
break;
default:
- dev_err(component->dev, "Invalid DAI id %d\n", dai->id);
+ dev_err(component->dev, "%s: Invalid DAI id %d\n", __func__, dai->id);
return -EINVAL;
}
retval = sdw_stream_add_slave(rt700->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
+ dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@@ -945,8 +945,8 @@ static int rt700_pcm_hw_params(struct snd_pcm_substream *substream,
/* bit 3:0 Number of Channel */
val |= (params_channels(params) - 1);
} else {
- dev_err(component->dev, "Unsupported channels %d\n",
- params_channels(params));
+ dev_err(component->dev, "%s: Unsupported channels %d\n",
+ __func__, params_channels(params));
return -EINVAL;
}
diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c
index 935e597022d3..f5933d2e085e 100644
--- a/sound/soc/codecs/rt711-sdca-sdw.c
+++ b/sound/soc/codecs/rt711-sdca-sdw.c
@@ -438,20 +438,20 @@ static int __maybe_unused rt711_sdca_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
+ mutex_lock(&rt711->disable_irq_lock);
if (rt711->disable_irq == true) {
- mutex_lock(&rt711->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
rt711->disable_irq = false;
- mutex_unlock(&rt711->disable_irq_lock);
}
+ mutex_unlock(&rt711->disable_irq_lock);
goto regmap_sync;
}
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT711_PROBE_TIMEOUT));
if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;
@@ -474,7 +474,6 @@ static const struct dev_pm_ops rt711_sdca_pm = {
static struct sdw_driver rt711_sdca_sdw_driver = {
.driver = {
.name = "rt711-sdca",
- .owner = THIS_MODULE,
.pm = &rt711_sdca_pm,
},
.probe = rt711_sdca_sdw_probe,
diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c
index 447154cb6010..1e8dbfc3ecd9 100644
--- a/sound/soc/codecs/rt711-sdca.c
+++ b/sound/soc/codecs/rt711-sdca.c
@@ -36,8 +36,8 @@ static int rt711_sdca_index_write(struct rt711_sdca_priv *rt711,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt711->slave->dev,
- "Failed to set private value: %06x <= %04x ret=%d\n",
- addr, value, ret);
+ "%s: Failed to set private value: %06x <= %04x ret=%d\n",
+ __func__, addr, value, ret);
return ret;
}
@@ -52,8 +52,8 @@ static int rt711_sdca_index_read(struct rt711_sdca_priv *rt711,
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt711->slave->dev,
- "Failed to get private value: %06x => %04x ret=%d\n",
- addr, *value, ret);
+ "%s: Failed to get private value: %06x => %04x ret=%d\n",
+ __func__, addr, *value, ret);
return ret;
}
@@ -1293,13 +1293,13 @@ static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt711->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
+ dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
if (params_channels(params) > 16) {
- dev_err(component->dev, "Unsupported channels %d\n",
- params_channels(params));
+ dev_err(component->dev, "%s: Unsupported channels %d\n",
+ __func__, params_channels(params));
return -EINVAL;
}
@@ -1318,8 +1318,8 @@ static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
sampling_rate = RT711_SDCA_RATE_192000HZ;
break;
default:
- dev_err(component->dev, "Rate %d is not supported\n",
- params_rate(params));
+ dev_err(component->dev, "%s: Rate %d is not supported\n",
+ __func__, params_rate(params));
return -EINVAL;
}
diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c
index 3f5773310ae8..8ca8bcd177ab 100644
--- a/sound/soc/codecs/rt711-sdw.c
+++ b/sound/soc/codecs/rt711-sdw.c
@@ -408,7 +408,7 @@ static int rt711_bus_config(struct sdw_slave *slave,
ret = rt711_clock_config(&slave->dev);
if (ret < 0)
- dev_err(&slave->dev, "Invalid clk config");
+ dev_err(&slave->dev, "%s: Invalid clk config", __func__);
return ret;
}
@@ -536,19 +536,19 @@ static int __maybe_unused rt711_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
+ mutex_lock(&rt711->disable_irq_lock);
if (rt711->disable_irq == true) {
- mutex_lock(&rt711->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
rt711->disable_irq = false;
- mutex_unlock(&rt711->disable_irq_lock);
}
+ mutex_unlock(&rt711->disable_irq_lock);
goto regmap_sync;
}
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT711_PROBE_TIMEOUT));
if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
return -ETIMEDOUT;
}
@@ -569,7 +569,6 @@ static const struct dev_pm_ops rt711_pm = {
static struct sdw_driver rt711_sdw_driver = {
.driver = {
.name = "rt711",
- .owner = THIS_MODULE,
.pm = &rt711_pm,
},
.probe = rt711_sdw_probe,
diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c
index 66eaed13b0d6..5446f9506a16 100644
--- a/sound/soc/codecs/rt711.c
+++ b/sound/soc/codecs/rt711.c
@@ -37,8 +37,8 @@ static int rt711_index_write(struct regmap *regmap,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
- pr_err("Failed to set private value: %06x <= %04x ret=%d\n",
- addr, value, ret);
+ pr_err("%s: Failed to set private value: %06x <= %04x ret=%d\n",
+ __func__, addr, value, ret);
return ret;
}
@@ -52,8 +52,8 @@ static int rt711_index_read(struct regmap *regmap,
*value = 0;
ret = regmap_read(regmap, addr, value);
if (ret < 0)
- pr_err("Failed to get private value: %06x => %04x ret=%d\n",
- addr, *value, ret);
+ pr_err("%s: Failed to get private value: %06x => %04x ret=%d\n",
+ __func__, addr, *value, ret);
return ret;
}
@@ -428,7 +428,7 @@ static void rt711_jack_init(struct rt711_priv *rt711)
RT711_HP_JD_FINAL_RESULT_CTL_JD12);
break;
default:
- dev_warn(rt711->component->dev, "Wrong JD source\n");
+ dev_warn(rt711->component->dev, "%s: Wrong JD source\n", __func__);
break;
}
@@ -1020,7 +1020,7 @@ static int rt711_pcm_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt711->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
+ dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@@ -1028,8 +1028,8 @@ static int rt711_pcm_hw_params(struct snd_pcm_substream *substream,
/* bit 3:0 Number of Channel */
val |= (params_channels(params) - 1);
} else {
- dev_err(component->dev, "Unsupported channels %d\n",
- params_channels(params));
+ dev_err(component->dev, "%s: Unsupported channels %d\n",
+ __func__, params_channels(params));
return -EINVAL;
}
diff --git a/sound/soc/codecs/rt712-sdca-dmic.c b/sound/soc/codecs/rt712-sdca-dmic.c
index 0926b26619bd..ee5435f3a80a 100644
--- a/sound/soc/codecs/rt712-sdca-dmic.c
+++ b/sound/soc/codecs/rt712-sdca-dmic.c
@@ -139,8 +139,8 @@ static int rt712_sdca_dmic_index_write(struct rt712_sdca_dmic_priv *rt712,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt712->slave->dev,
- "Failed to set private value: %06x <= %04x ret=%d\n",
- addr, value, ret);
+ "%s: Failed to set private value: %06x <= %04x ret=%d\n",
+ __func__, addr, value, ret);
return ret;
}
@@ -155,8 +155,8 @@ static int rt712_sdca_dmic_index_read(struct rt712_sdca_dmic_priv *rt712,
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt712->slave->dev,
- "Failed to get private value: %06x => %04x ret=%d\n",
- addr, *value, ret);
+ "%s: Failed to get private value: %06x => %04x ret=%d\n",
+ __func__, addr, *value, ret);
return ret;
}
@@ -317,7 +317,8 @@ static int rt712_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol,
for (i = 0; i < p->count; i++) {
err = regmap_write(rt712->mbq_regmap, p->reg_base + i, gain_val[i]);
if (err < 0)
- dev_err(&rt712->slave->dev, "0x%08x can't be set\n", p->reg_base + i);
+ dev_err(&rt712->slave->dev, "%s: 0x%08x can't be set\n",
+ __func__, p->reg_base + i);
}
return changed;
@@ -667,13 +668,13 @@ static int rt712_sdca_dmic_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt712->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
+ dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
if (params_channels(params) > 4) {
- dev_err(component->dev, "Unsupported channels %d\n",
- params_channels(params));
+ dev_err(component->dev, "%s: Unsupported channels %d\n",
+ __func__, params_channels(params));
return -EINVAL;
}
@@ -698,8 +699,8 @@ static int rt712_sdca_dmic_hw_params(struct snd_pcm_substream *substream,
sampling_rate = RT712_SDCA_RATE_192000HZ;
break;
default:
- dev_err(component->dev, "Rate %d is not supported\n",
- params_rate(params));
+ dev_err(component->dev, "%s: Rate %d is not supported\n",
+ __func__, params_rate(params));
return -EINVAL;
}
@@ -923,7 +924,8 @@ static int __maybe_unused rt712_sdca_dmic_dev_resume(struct device *dev)
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT712_PROBE_TIMEOUT));
if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ dev_err(&slave->dev, "%s: Initialization not complete, timed out\n",
+ __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;
@@ -976,7 +978,6 @@ static int rt712_sdca_dmic_sdw_remove(struct sdw_slave *slave)
static struct sdw_driver rt712_sdca_dmic_sdw_driver = {
.driver = {
.name = "rt712-sdca-dmic",
- .owner = THIS_MODULE,
.pm = &rt712_sdca_dmic_pm,
},
.probe = rt712_sdca_dmic_sdw_probe,
diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c
index 01ac555cd79b..ce337db86d1a 100644
--- a/sound/soc/codecs/rt712-sdca-sdw.c
+++ b/sound/soc/codecs/rt712-sdca-sdw.c
@@ -438,20 +438,21 @@ static int __maybe_unused rt712_sdca_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
+ mutex_lock(&rt712->disable_irq_lock);
if (rt712->disable_irq == true) {
- mutex_lock(&rt712->disable_irq_lock);
+
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
rt712->disable_irq = false;
- mutex_unlock(&rt712->disable_irq_lock);
}
+ mutex_unlock(&rt712->disable_irq_lock);
goto regmap_sync;
}
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT712_PROBE_TIMEOUT));
if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;
@@ -474,7 +475,6 @@ static const struct dev_pm_ops rt712_sdca_pm = {
static struct sdw_driver rt712_sdca_sdw_driver = {
.driver = {
.name = "rt712-sdca",
- .owner = THIS_MODULE,
.pm = &rt712_sdca_pm,
},
.probe = rt712_sdca_sdw_probe,
diff --git a/sound/soc/codecs/rt712-sdca.c b/sound/soc/codecs/rt712-sdca.c
index 6954fbe7ec5f..b503de9fda80 100644
--- a/sound/soc/codecs/rt712-sdca.c
+++ b/sound/soc/codecs/rt712-sdca.c
@@ -34,8 +34,8 @@ static int rt712_sdca_index_write(struct rt712_sdca_priv *rt712,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt712->slave->dev,
- "Failed to set private value: %06x <= %04x ret=%d\n",
- addr, value, ret);
+ "%s: Failed to set private value: %06x <= %04x ret=%d\n",
+ __func__, addr, value, ret);
return ret;
}
@@ -50,8 +50,8 @@ static int rt712_sdca_index_read(struct rt712_sdca_priv *rt712,
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt712->slave->dev,
- "Failed to get private value: %06x => %04x ret=%d\n",
- addr, *value, ret);
+ "%s: Failed to get private value: %06x => %04x ret=%d\n",
+ __func__, addr, *value, ret);
return ret;
}
@@ -1060,13 +1060,13 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt712->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
+ dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
if (params_channels(params) > 16) {
- dev_err(component->dev, "Unsupported channels %d\n",
- params_channels(params));
+ dev_err(component->dev, "%s: Unsupported channels %d\n",
+ __func__, params_channels(params));
return -EINVAL;
}
@@ -1085,8 +1085,8 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
sampling_rate = RT712_SDCA_RATE_192000HZ;
break;
default:
- dev_err(component->dev, "Rate %d is not supported\n",
- params_rate(params));
+ dev_err(component->dev, "%s: Rate %d is not supported\n",
+ __func__, params_rate(params));
return -EINVAL;
}
@@ -1106,7 +1106,7 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
sampling_rate);
break;
default:
- dev_err(component->dev, "Wrong DAI id\n");
+ dev_err(component->dev, "%s: Wrong DAI id\n", __func__);
return -EINVAL;
}
diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c
index ab54a67a27eb..d3fb02e8f31a 100644
--- a/sound/soc/codecs/rt715-sdca-sdw.c
+++ b/sound/soc/codecs/rt715-sdca-sdw.c
@@ -237,7 +237,7 @@ static int __maybe_unused rt715_dev_resume(struct device *dev)
time = wait_for_completion_timeout(&slave->enumeration_complete,
msecs_to_jiffies(RT715_PROBE_TIMEOUT));
if (!time) {
- dev_err(&slave->dev, "Enumeration not complete, timed out\n");
+ dev_err(&slave->dev, "%s: Enumeration not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;
@@ -270,7 +270,6 @@ static const struct dev_pm_ops rt715_pm = {
static struct sdw_driver rt715_sdw_driver = {
.driver = {
.name = "rt715-sdca",
- .owner = THIS_MODULE,
.pm = &rt715_pm,
},
.probe = rt715_sdca_sdw_probe,
diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c
index 4533eedd7e18..3a6dfe1f6c48 100644
--- a/sound/soc/codecs/rt715-sdca.c
+++ b/sound/soc/codecs/rt715-sdca.c
@@ -41,8 +41,8 @@ static int rt715_sdca_index_write(struct rt715_sdca_priv *rt715,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt715->slave->dev,
- "Failed to set private value: %08x <= %04x %d\n",
- addr, value, ret);
+ "%s: Failed to set private value: %08x <= %04x %d\n",
+ __func__, addr, value, ret);
return ret;
}
@@ -59,8 +59,8 @@ static int rt715_sdca_index_read(struct rt715_sdca_priv *rt715,
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt715->slave->dev,
- "Failed to get private value: %06x => %04x ret=%d\n",
- addr, *value, ret);
+ "%s: Failed to get private value: %06x => %04x ret=%d\n",
+ __func__, addr, *value, ret);
return ret;
}
@@ -152,8 +152,8 @@ static int rt715_sdca_set_amp_gain_put(struct snd_kcontrol *kcontrol,
mc->shift);
ret = regmap_write(rt715->mbq_regmap, mc->reg + i, gain_val);
if (ret != 0) {
- dev_err(component->dev, "Failed to write 0x%x=0x%x\n",
- mc->reg + i, gain_val);
+ dev_err(component->dev, "%s: Failed to write 0x%x=0x%x\n",
+ __func__, mc->reg + i, gain_val);
return ret;
}
}
@@ -188,8 +188,8 @@ static int rt715_sdca_set_amp_gain_4ch_put(struct snd_kcontrol *kcontrol,
ret = regmap_write(rt715->mbq_regmap, reg_base + i,
gain_val);
if (ret != 0) {
- dev_err(component->dev, "Failed to write 0x%x=0x%x\n",
- reg_base + i, gain_val);
+ dev_err(component->dev, "%s: Failed to write 0x%x=0x%x\n",
+ __func__, reg_base + i, gain_val);
return ret;
}
}
@@ -224,8 +224,8 @@ static int rt715_sdca_set_amp_gain_8ch_put(struct snd_kcontrol *kcontrol,
reg = i < 7 ? reg_base + i : (reg_base - 1) | BIT(15);
ret = regmap_write(rt715->mbq_regmap, reg, gain_val);
if (ret != 0) {
- dev_err(component->dev, "Failed to write 0x%x=0x%x\n",
- reg, gain_val);
+ dev_err(component->dev, "%s: Failed to write 0x%x=0x%x\n",
+ __func__, reg, gain_val);
return ret;
}
}
@@ -246,8 +246,8 @@ static int rt715_sdca_set_amp_gain_get(struct snd_kcontrol *kcontrol,
for (i = 0; i < 2; i++) {
ret = regmap_read(rt715->mbq_regmap, mc->reg + i, &val);
if (ret < 0) {
- dev_err(component->dev, "Failed to read 0x%x, ret=%d\n",
- mc->reg + i, ret);
+ dev_err(component->dev, "%s: Failed to read 0x%x, ret=%d\n",
+ __func__, mc->reg + i, ret);
return ret;
}
ucontrol->value.integer.value[i] = rt715_sdca_get_gain(val, mc->shift);
@@ -271,8 +271,8 @@ static int rt715_sdca_set_amp_gain_4ch_get(struct snd_kcontrol *kcontrol,
for (i = 0; i < 4; i++) {
ret = regmap_read(rt715->mbq_regmap, reg_base + i, &val);
if (ret < 0) {
- dev_err(component->dev, "Failed to read 0x%x, ret=%d\n",
- reg_base + i, ret);
+ dev_err(component->dev, "%s: Failed to read 0x%x, ret=%d\n",
+ __func__, reg_base + i, ret);
return ret;
}
ucontrol->value.integer.value[i] = rt715_sdca_get_gain(val, gain_sft);
@@ -297,8 +297,8 @@ static int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol,
for (i = 0; i < 8; i += 2) {
ret = regmap_read(rt715->mbq_regmap, reg_base + i, &val_l);
if (ret < 0) {
- dev_err(component->dev, "Failed to read 0x%x, ret=%d\n",
- reg_base + i, ret);
+ dev_err(component->dev, "%s: Failed to read 0x%x, ret=%d\n",
+ __func__, reg_base + i, ret);
return ret;
}
ucontrol->value.integer.value[i] = (val_l >> gain_sft) / 10;
@@ -306,8 +306,8 @@ static int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol,
reg = (i == 6) ? (reg_base - 1) | BIT(15) : reg_base + 1 + i;
ret = regmap_read(rt715->mbq_regmap, reg, &val_r);
if (ret < 0) {
- dev_err(component->dev, "Failed to read 0x%x, ret=%d\n",
- reg, ret);
+ dev_err(component->dev, "%s: Failed to read 0x%x, ret=%d\n",
+ __func__, reg, ret);
return ret;
}
ucontrol->value.integer.value[i + 1] = (val_r >> gain_sft) / 10;
@@ -834,15 +834,15 @@ static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
0xaf00);
break;
default:
- dev_err(component->dev, "Invalid DAI id %d\n", dai->id);
+ dev_err(component->dev, "%s: Invalid DAI id %d\n", __func__, dai->id);
return -EINVAL;
}
retval = sdw_stream_add_slave(rt715->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(component->dev, "Unable to configure port, retval:%d\n",
- retval);
+ dev_err(component->dev, "%s: Unable to configure port, retval:%d\n",
+ __func__, retval);
return retval;
}
@@ -893,8 +893,8 @@ static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
val = 0xf;
break;
default:
- dev_err(component->dev, "Unsupported sample rate %d\n",
- params_rate(params));
+ dev_err(component->dev, "%s: Unsupported sample rate %d\n",
+ __func__, params_rate(params));
return -EINVAL;
}
@@ -933,7 +933,7 @@ static const struct snd_soc_dai_ops rt715_sdca_ops = {
static struct snd_soc_dai_driver rt715_sdca_dai[] = {
{
- .name = "rt715-aif1",
+ .name = "rt715-sdca-aif1",
.id = RT715_AIF1,
.capture = {
.stream_name = "DP6 Capture",
@@ -945,7 +945,7 @@ static struct snd_soc_dai_driver rt715_sdca_dai[] = {
.ops = &rt715_sdca_ops,
},
{
- .name = "rt715-aif2",
+ .name = "rt715-sdca-aif2",
.id = RT715_AIF2,
.capture = {
.stream_name = "DP4 Capture",
diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c
index 21f37babd148..24b3443aeb02 100644
--- a/sound/soc/codecs/rt715-sdw.c
+++ b/sound/soc/codecs/rt715-sdw.c
@@ -482,7 +482,7 @@ static int rt715_bus_config(struct sdw_slave *slave,
ret = rt715_clock_config(&slave->dev);
if (ret < 0)
- dev_err(&slave->dev, "Invalid clk config");
+ dev_err(&slave->dev, "%s: Invalid clk config", __func__);
return 0;
}
@@ -554,7 +554,7 @@ static int __maybe_unused rt715_dev_resume(struct device *dev)
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT715_PROBE_TIMEOUT));
if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;
@@ -577,7 +577,6 @@ static const struct dev_pm_ops rt715_pm = {
static struct sdw_driver rt715_sdw_driver = {
.driver = {
.name = "rt715",
- .owner = THIS_MODULE,
.pm = &rt715_pm,
},
.probe = rt715_sdw_probe,
diff --git a/sound/soc/codecs/rt715.c b/sound/soc/codecs/rt715.c
index 9f732a5abd53..299c9b12377c 100644
--- a/sound/soc/codecs/rt715.c
+++ b/sound/soc/codecs/rt715.c
@@ -40,8 +40,8 @@ static int rt715_index_write(struct regmap *regmap, unsigned int reg,
ret = regmap_write(regmap, addr, value);
if (ret < 0) {
- pr_err("Failed to set private value: %08x <= %04x %d\n",
- addr, value, ret);
+ pr_err("%s: Failed to set private value: %08x <= %04x %d\n",
+ __func__, addr, value, ret);
}
return ret;
@@ -55,8 +55,8 @@ static int rt715_index_write_nid(struct regmap *regmap,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
- pr_err("Failed to set private value: %06x <= %04x ret=%d\n",
- addr, value, ret);
+ pr_err("%s: Failed to set private value: %06x <= %04x ret=%d\n",
+ __func__, addr, value, ret);
return ret;
}
@@ -70,8 +70,8 @@ static int rt715_index_read_nid(struct regmap *regmap,
*value = 0;
ret = regmap_read(regmap, addr, value);
if (ret < 0)
- pr_err("Failed to get private value: %06x => %04x ret=%d\n",
- addr, *value, ret);
+ pr_err("%s: Failed to get private value: %06x => %04x ret=%d\n",
+ __func__, addr, *value, ret);
return ret;
}
@@ -862,14 +862,14 @@ static int rt715_pcm_hw_params(struct snd_pcm_substream *substream,
rt715_index_write(rt715->regmap, RT715_SDW_INPUT_SEL, 0xa000);
break;
default:
- dev_err(component->dev, "Invalid DAI id %d\n", dai->id);
+ dev_err(component->dev, "%s: Invalid DAI id %d\n", __func__, dai->id);
return -EINVAL;
}
retval = sdw_stream_add_slave(rt715->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
+ dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@@ -883,8 +883,8 @@ static int rt715_pcm_hw_params(struct snd_pcm_substream *substream,
val |= 0x0 << 8;
break;
default:
- dev_err(component->dev, "Unsupported sample rate %d\n",
- params_rate(params));
+ dev_err(component->dev, "%s: Unsupported sample rate %d\n",
+ __func__, params_rate(params));
return -EINVAL;
}
@@ -892,8 +892,8 @@ static int rt715_pcm_hw_params(struct snd_pcm_substream *substream,
/* bit 3:0 Number of Channel */
val |= (params_channels(params) - 1);
} else {
- dev_err(component->dev, "Unsupported channels %d\n",
- params_channels(params));
+ dev_err(component->dev, "%s: Unsupported channels %d\n",
+ __func__, params_channels(params));
return -EINVAL;
}
diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c
index eb76f4c675b6..b33da2215ade 100644
--- a/sound/soc/codecs/rt722-sdca-sdw.c
+++ b/sound/soc/codecs/rt722-sdca-sdw.c
@@ -467,13 +467,13 @@ static int __maybe_unused rt722_sdca_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
+ mutex_lock(&rt722->disable_irq_lock);
if (rt722->disable_irq == true) {
- mutex_lock(&rt722->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_6);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
rt722->disable_irq = false;
- mutex_unlock(&rt722->disable_irq_lock);
}
+ mutex_unlock(&rt722->disable_irq_lock);
goto regmap_sync;
}
@@ -503,7 +503,6 @@ static const struct dev_pm_ops rt722_sdca_pm = {
static struct sdw_driver rt722_sdca_sdw_driver = {
.driver = {
.name = "rt722-sdca",
- .owner = THIS_MODULE,
.pm = &rt722_sdca_pm,
},
.probe = rt722_sdca_sdw_probe,
diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c
index 0e1c65a20392..e0ea3a23f7cc 100644
--- a/sound/soc/codecs/rt722-sdca.c
+++ b/sound/soc/codecs/rt722-sdca.c
@@ -35,8 +35,8 @@ int rt722_sdca_index_write(struct rt722_sdca_priv *rt722,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt722->slave->dev,
- "Failed to set private value: %06x <= %04x ret=%d\n",
- addr, value, ret);
+ "%s: Failed to set private value: %06x <= %04x ret=%d\n",
+ __func__, addr, value, ret);
return ret;
}
@@ -51,8 +51,8 @@ int rt722_sdca_index_read(struct rt722_sdca_priv *rt722,
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt722->slave->dev,
- "Failed to get private value: %06x => %04x ret=%d\n",
- addr, *value, ret);
+ "%s: Failed to get private value: %06x => %04x ret=%d\n",
+ __func__, addr, *value, ret);
return ret;
}
@@ -663,7 +663,8 @@ static int rt722_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol,
for (i = 0; i < p->count; i++) {
err = regmap_write(rt722->mbq_regmap, p->reg_base + i, gain_val[i]);
if (err < 0)
- dev_err(&rt722->slave->dev, "%#08x can't be set\n", p->reg_base + i);
+ dev_err(&rt722->slave->dev, "%s: %#08x can't be set\n",
+ __func__, p->reg_base + i);
}
return changed;
@@ -1211,13 +1212,13 @@ static int rt722_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt722->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
+ dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
if (params_channels(params) > 16) {
- dev_err(component->dev, "Unsupported channels %d\n",
- params_channels(params));
+ dev_err(component->dev, "%s: Unsupported channels %d\n",
+ __func__, params_channels(params));
return -EINVAL;
}
@@ -1236,8 +1237,8 @@ static int rt722_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
sampling_rate = RT722_SDCA_RATE_192000HZ;
break;
default:
- dev_err(component->dev, "Rate %d is not supported\n",
- params_rate(params));
+ dev_err(component->dev, "%s: Rate %d is not supported\n",
+ __func__, params_rate(params));
return -EINVAL;
}
diff --git a/sound/soc/codecs/sdw-mockup.c b/sound/soc/codecs/sdw-mockup.c
index 5498ff027c58..574c08b14f0c 100644
--- a/sound/soc/codecs/sdw-mockup.c
+++ b/sound/soc/codecs/sdw-mockup.c
@@ -262,7 +262,6 @@ MODULE_DEVICE_TABLE(sdw, sdw_mockup_id);
static struct sdw_driver sdw_mockup_sdw_driver = {
.driver = {
.name = "sdw-mockup",
- .owner = THIS_MODULE,
},
.probe = sdw_mockup_sdw_probe,
.remove = sdw_mockup_sdw_remove,
diff --git a/sound/soc/codecs/tlv320aic32x4-spi.c b/sound/soc/codecs/tlv320aic32x4-spi.c
index d5976c91766e..92246243ff94 100644
--- a/sound/soc/codecs/tlv320aic32x4-spi.c
+++ b/sound/soc/codecs/tlv320aic32x4-spi.c
@@ -56,7 +56,6 @@ MODULE_DEVICE_TABLE(of, aic32x4_of_id);
static struct spi_driver aic32x4_spi_driver = {
.driver = {
.name = "tlv320aic32x4",
- .owner = THIS_MODULE,
.of_match_table = aic32x4_of_id,
},
.probe = aic32x4_spi_probe,
diff --git a/sound/soc/codecs/tlv320aic3x-spi.c b/sound/soc/codecs/tlv320aic3x-spi.c
index deed6ec7e081..f8c1c16eaa0e 100644
--- a/sound/soc/codecs/tlv320aic3x-spi.c
+++ b/sound/soc/codecs/tlv320aic3x-spi.c
@@ -63,7 +63,6 @@ MODULE_DEVICE_TABLE(of, aic3x_of_id);
static struct spi_driver aic3x_spi_driver = {
.driver = {
.name = "tlv320aic3x",
- .owner = THIS_MODULE,
.of_match_table = aic3x_of_id,
},
.probe = aic3x_spi_probe,
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index e451c009f2d9..7d5c096e06cd 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -683,11 +683,12 @@ static void wm_adsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
unsigned int alg, void *buf, size_t len)
{
- struct cs_dsp_coeff_ctl *cs_ctl = cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg);
+ struct cs_dsp_coeff_ctl *cs_ctl;
struct wm_coeff_ctl *ctl;
int ret;
mutex_lock(&dsp->cs_dsp.pwr_lock);
+ cs_ctl = cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg);
ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len);
mutex_unlock(&dsp->cs_dsp.pwr_lock);
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 81077d16d22f..b4876b4f259d 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -752,8 +752,6 @@ int simple_util_init_jack(struct snd_soc_card *card,
if (!prefix)
prefix = "";
- sjack->gpio.gpio = -ENOENT;
-
if (is_hp) {
snprintf(prop, sizeof(prop), "%shp-det", prefix);
pin_name = pin ? pin : "Headphones";
diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h
index f80f79415344..9a02e2b528bc 100644
--- a/sound/soc/intel/avs/avs.h
+++ b/sound/soc/intel/avs/avs.h
@@ -107,7 +107,7 @@ struct avs_spec {
};
struct avs_fw_entry {
- char *name;
+ const char *name;
const struct firmware *fw;
struct list_head node;
diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c
index c018f84fe025..fc072dc58968 100644
--- a/sound/soc/intel/avs/boards/da7219.c
+++ b/sound/soc/intel/avs/boards/da7219.c
@@ -296,5 +296,6 @@ static struct platform_driver avs_da7219_driver = {
module_platform_driver(avs_da7219_driver);
+MODULE_DESCRIPTION("Intel da7219 machine driver");
MODULE_AUTHOR("Cezary Rojewski <[email protected]>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/dmic.c b/sound/soc/intel/avs/boards/dmic.c
index ba2bc7f689eb..d9e5e85f5233 100644
--- a/sound/soc/intel/avs/boards/dmic.c
+++ b/sound/soc/intel/avs/boards/dmic.c
@@ -96,4 +96,5 @@ static struct platform_driver avs_dmic_driver = {
module_platform_driver(avs_dmic_driver);
+MODULE_DESCRIPTION("Intel DMIC machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c
index 1090082e7d5b..ff3bd1513269 100644
--- a/sound/soc/intel/avs/boards/es8336.c
+++ b/sound/soc/intel/avs/boards/es8336.c
@@ -85,7 +85,7 @@ static const struct snd_kcontrol_new card_controls[] = {
SOC_DAPM_PIN_SWITCH("Internal Mic"),
};
-static struct snd_soc_jack_pin card_headset_pins[] = {
+static const struct snd_soc_jack_pin card_headset_pins[] = {
{
.pin = "Headphone",
.mask = SND_JACK_HEADPHONE,
@@ -326,4 +326,5 @@ static struct platform_driver avs_es8336_driver = {
module_platform_driver(avs_es8336_driver);
+MODULE_DESCRIPTION("Intel es8336 machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c
index 79b4aca41333..4433175814f8 100644
--- a/sound/soc/intel/avs/boards/hdaudio.c
+++ b/sound/soc/intel/avs/boards/hdaudio.c
@@ -54,7 +54,7 @@ static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int
if (!dl[i].cpus->dai_name)
return -ENOMEM;
- dl[i].codecs->name = devm_kstrdup(dev, cname, GFP_KERNEL);
+ dl[i].codecs->name = devm_kstrdup_const(dev, cname, GFP_KERNEL);
if (!dl[i].codecs->name)
return -ENOMEM;
@@ -155,7 +155,7 @@ static int avs_probing_link_init(struct snd_soc_pcm_runtime *rtm)
return 0;
}
-static struct snd_soc_dai_link probing_link = {
+static const struct snd_soc_dai_link probing_link = {
.name = "probing-LINK",
.id = -1,
.nonatomic = 1,
@@ -191,7 +191,7 @@ static int avs_hdaudio_probe(struct platform_device *pdev)
if (!binder->platforms || !binder->codecs)
return -ENOMEM;
- binder->codecs->name = devm_kstrdup(dev, dev_name(&codec->core.dev), GFP_KERNEL);
+ binder->codecs->name = devm_kstrdup_const(dev, dev_name(&codec->core.dev), GFP_KERNEL);
if (!binder->codecs->name)
return -ENOMEM;
diff --git a/sound/soc/intel/avs/boards/i2s_test.c b/sound/soc/intel/avs/boards/i2s_test.c
index 282256d18cc6..d41955685664 100644
--- a/sound/soc/intel/avs/boards/i2s_test.c
+++ b/sound/soc/intel/avs/boards/i2s_test.c
@@ -125,4 +125,5 @@ static struct platform_driver avs_i2s_test_driver = {
module_platform_driver(avs_i2s_test_driver);
+MODULE_DESCRIPTION("Intel i2s test machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c
index a83b95f25129..1ff85e4d8e16 100644
--- a/sound/soc/intel/avs/boards/max98357a.c
+++ b/sound/soc/intel/avs/boards/max98357a.c
@@ -154,4 +154,5 @@ static struct platform_driver avs_max98357a_driver = {
module_platform_driver(avs_max98357a_driver)
+MODULE_DESCRIPTION("Intel max98357a machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/max98373.c b/sound/soc/intel/avs/boards/max98373.c
index 3b980a025e6f..8d31586b73ea 100644
--- a/sound/soc/intel/avs/boards/max98373.c
+++ b/sound/soc/intel/avs/boards/max98373.c
@@ -211,4 +211,5 @@ static struct platform_driver avs_max98373_driver = {
module_platform_driver(avs_max98373_driver)
+MODULE_DESCRIPTION("Intel max98373 machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c
index 86dd2b228df3..572ec58073d0 100644
--- a/sound/soc/intel/avs/boards/max98927.c
+++ b/sound/soc/intel/avs/boards/max98927.c
@@ -208,4 +208,5 @@ static struct platform_driver avs_max98927_driver = {
module_platform_driver(avs_max98927_driver)
+MODULE_DESCRIPTION("Intel max98927 machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c
index 1c1e2083f474..3164745b1516 100644
--- a/sound/soc/intel/avs/boards/nau8825.c
+++ b/sound/soc/intel/avs/boards/nau8825.c
@@ -67,7 +67,7 @@ static const struct snd_soc_dapm_route card_base_routes[] = {
{ "Headset Mic", NULL, "Platform Clock" },
};
-static struct snd_soc_jack_pin card_headset_pins[] = {
+static const struct snd_soc_jack_pin card_headset_pins[] = {
{
.pin = "Headphone Jack",
.mask = SND_JACK_HEADPHONE,
@@ -313,4 +313,5 @@ static struct platform_driver avs_nau8825_driver = {
module_platform_driver(avs_nau8825_driver)
+MODULE_DESCRIPTION("Intel nau8825 machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/probe.c b/sound/soc/intel/avs/boards/probe.c
index a9469b5ecb40..8be6887bbc6e 100644
--- a/sound/soc/intel/avs/boards/probe.c
+++ b/sound/soc/intel/avs/boards/probe.c
@@ -69,4 +69,5 @@ static struct platform_driver avs_probe_mb_driver = {
module_platform_driver(avs_probe_mb_driver);
+MODULE_DESCRIPTION("Intel probe machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c
index bfcb8845fd15..e3aa28780df5 100644
--- a/sound/soc/intel/avs/boards/rt274.c
+++ b/sound/soc/intel/avs/boards/rt274.c
@@ -75,7 +75,7 @@ static const struct snd_soc_dapm_route card_base_routes[] = {
{"MIC", NULL, "Platform Clock"},
};
-static struct snd_soc_jack_pin card_headset_pins[] = {
+static const struct snd_soc_jack_pin card_headset_pins[] = {
{
.pin = "Headphone Jack",
.mask = SND_JACK_HEADPHONE,
@@ -276,4 +276,5 @@ static struct platform_driver avs_rt274_driver = {
module_platform_driver(avs_rt274_driver);
+MODULE_DESCRIPTION("Intel rt274 machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c
index 28d7d86b1cc9..d24316fc4db9 100644
--- a/sound/soc/intel/avs/boards/rt286.c
+++ b/sound/soc/intel/avs/boards/rt286.c
@@ -38,7 +38,7 @@ static const struct snd_soc_dapm_route card_base_routes[] = {
{"Speaker", NULL, "SPOL"},
};
-static struct snd_soc_jack_pin card_headset_pins[] = {
+static const struct snd_soc_jack_pin card_headset_pins[] = {
{
.pin = "Headphone Jack",
.mask = SND_JACK_HEADPHONE,
@@ -247,4 +247,5 @@ static struct platform_driver avs_rt286_driver = {
module_platform_driver(avs_rt286_driver);
+MODULE_DESCRIPTION("Intel rt286 machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c
index 80f490b9e118..7fd28544f786 100644
--- a/sound/soc/intel/avs/boards/rt298.c
+++ b/sound/soc/intel/avs/boards/rt298.c
@@ -49,7 +49,7 @@ static const struct snd_soc_dapm_route card_base_routes[] = {
{"Speaker", NULL, "SPOL"},
};
-static struct snd_soc_jack_pin card_headset_pins[] = {
+static const struct snd_soc_jack_pin card_headset_pins[] = {
{
.pin = "Headphone Jack",
.mask = SND_JACK_HEADPHONE,
@@ -266,4 +266,5 @@ static struct platform_driver avs_rt298_driver = {
module_platform_driver(avs_rt298_driver);
+MODULE_DESCRIPTION("Intel rt298 machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/rt5514.c b/sound/soc/intel/avs/boards/rt5514.c
index 60105f453ae2..097ae5f73241 100644
--- a/sound/soc/intel/avs/boards/rt5514.c
+++ b/sound/soc/intel/avs/boards/rt5514.c
@@ -192,4 +192,5 @@ static struct platform_driver avs_rt5514_driver = {
module_platform_driver(avs_rt5514_driver);
+MODULE_DESCRIPTION("Intel rt5514 machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/rt5663.c b/sound/soc/intel/avs/boards/rt5663.c
index b4762c2a7bf2..ba8c42d026da 100644
--- a/sound/soc/intel/avs/boards/rt5663.c
+++ b/sound/soc/intel/avs/boards/rt5663.c
@@ -43,7 +43,7 @@ static const struct snd_soc_dapm_route card_routes[] = {
{ "IN1N", NULL, "Headset Mic" },
};
-static struct snd_soc_jack_pin card_headset_pins[] = {
+static const struct snd_soc_jack_pin card_headset_pins[] = {
{
.pin = "Headphone Jack",
.mask = SND_JACK_HEADPHONE,
@@ -265,4 +265,5 @@ static struct platform_driver avs_rt5663_driver = {
module_platform_driver(avs_rt5663_driver);
+MODULE_DESCRIPTION("Intel rt5663 machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c
index 243f979fda98..823f04dba2f7 100644
--- a/sound/soc/intel/avs/boards/rt5682.c
+++ b/sound/soc/intel/avs/boards/rt5682.c
@@ -80,7 +80,7 @@ static const struct snd_soc_dapm_route card_base_routes[] = {
{ "IN1P", NULL, "Headset Mic" },
};
-static struct snd_soc_jack_pin card_jack_pins[] = {
+static const struct snd_soc_jack_pin card_jack_pins[] = {
{
.pin = "Headphone Jack",
.mask = SND_JACK_HEADPHONE,
@@ -341,5 +341,6 @@ static struct platform_driver avs_rt5682_driver = {
module_platform_driver(avs_rt5682_driver)
+MODULE_DESCRIPTION("Intel rt5682 machine driver");
MODULE_AUTHOR("Cezary Rojewski <[email protected]>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c
index abb87bb88fff..9e78a3b91208 100644
--- a/sound/soc/intel/avs/boards/ssm4567.c
+++ b/sound/soc/intel/avs/boards/ssm4567.c
@@ -197,4 +197,5 @@ static struct platform_driver avs_ssm4567_driver = {
module_platform_driver(avs_ssm4567_driver)
+MODULE_DESCRIPTION("Intel ssm4567 machine driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/utils.c b/sound/soc/intel/avs/utils.c
index 82416b86662d..8100c2fa0a7e 100644
--- a/sound/soc/intel/avs/utils.c
+++ b/sound/soc/intel/avs/utils.c
@@ -250,7 +250,7 @@ int avs_request_firmware(struct avs_dev *adev, const struct firmware **fw_p, con
if (!entry)
return -ENOMEM;
- entry->name = kstrdup(name, GFP_KERNEL);
+ entry->name = kstrdup_const(name, GFP_KERNEL);
if (!entry->name) {
kfree(entry);
return -ENOMEM;
@@ -258,7 +258,7 @@ int avs_request_firmware(struct avs_dev *adev, const struct firmware **fw_p, con
ret = request_firmware(&entry->fw, name, adev->dev);
if (ret < 0) {
- kfree(entry->name);
+ kfree_const(entry->name);
kfree(entry);
return ret;
}
@@ -282,7 +282,7 @@ void avs_release_last_firmware(struct avs_dev *adev)
list_del(&entry->node);
release_firmware(entry->fw);
- kfree(entry->name);
+ kfree_const(entry->name);
kfree(entry);
}
@@ -296,7 +296,7 @@ void avs_release_firmwares(struct avs_dev *adev)
list_for_each_entry_safe(entry, tmp, &adev->fw_list, node) {
list_del(&entry->node);
release_firmware(entry->fw);
- kfree(entry->name);
+ kfree_const(entry->name);
kfree(entry);
}
}
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index e5df64fec319..9f4a85513702 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -41,9 +41,6 @@ config SND_SOC_INTEL_SOF_CIRRUS_COMMON
config SND_SOC_INTEL_SOF_NUVOTON_COMMON
tristate
-config SND_SOC_INTEL_SOF_SSP_COMMON
- tristate
-
config SND_SOC_INTEL_SOF_BOARD_HELPERS
tristate
@@ -503,7 +500,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH
select SND_SOC_INTEL_SOF_BOARD_HELPERS
select SND_SOC_INTEL_SOF_MAXIM_COMMON
select SND_SOC_INTEL_SOF_REALTEK_COMMON
- select SND_SOC_INTEL_SOF_SSP_COMMON
+ select SND_SOC_ACPI_INTEL_MATCH
help
This adds support for ASoC machine driver for SOF platforms
with rt5650 or rt5682 codec.
@@ -521,7 +518,7 @@ config SND_SOC_INTEL_SOF_CS42L42_MACH
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_BOARD_HELPERS
select SND_SOC_INTEL_SOF_MAXIM_COMMON
- select SND_SOC_INTEL_SOF_SSP_COMMON
+ select SND_SOC_ACPI_INTEL_MATCH
help
This adds support for ASoC machine driver for SOF platforms
with cs42l42 codec.
@@ -574,7 +571,7 @@ config SND_SOC_INTEL_SOF_NAU8825_MACH
select SND_SOC_INTEL_SOF_MAXIM_COMMON
select SND_SOC_INTEL_SOF_NUVOTON_COMMON
select SND_SOC_INTEL_SOF_REALTEK_COMMON
- select SND_SOC_INTEL_SOF_SSP_COMMON
+ select SND_SOC_ACPI_INTEL_MATCH
help
This adds support for ASoC machine driver for SOF platforms
with nau8825 codec.
@@ -626,7 +623,7 @@ config SND_SOC_INTEL_SOF_DA7219_MACH
select SND_SOC_DMIC
select SND_SOC_INTEL_SOF_BOARD_HELPERS
select SND_SOC_INTEL_SOF_MAXIM_COMMON
- select SND_SOC_INTEL_SOF_SSP_COMMON
+ select SND_SOC_ACPI_INTEL_MATCH
help
This adds support for ASoC machine driver for SOF platforms
with Dialog DA7219 I2S audio codec.
@@ -646,7 +643,7 @@ config SND_SOC_INTEL_SOF_SSP_AMP_MACH
select SND_SOC_INTEL_SOF_BOARD_HELPERS
select SND_SOC_INTEL_SOF_REALTEK_COMMON
select SND_SOC_INTEL_SOF_CIRRUS_COMMON
- select SND_SOC_INTEL_SOF_SSP_COMMON
+ select SND_SOC_ACPI_INTEL_MATCH
help
This adds support for ASoC machine driver for SOF platforms
with RT1308/CS35L41 I2S audio codec.
@@ -678,7 +675,6 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
depends on MFD_INTEL_LPSS || COMPILE_TEST
depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST
depends on SOUNDWIRE
- select SND_SOC_INTEL_SOF_BOARD_HELPERS
select SND_SOC_MAX98363
select SND_SOC_MAX98373_I2C
select SND_SOC_MAX98373_SDW
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index bbf796a5f7ba..a93b658ed672 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -40,8 +40,8 @@ snd-soc-sof-sdw-objs += sof_sdw.o \
sof_sdw_maxim.o sof_sdw_rt_amp.o \
sof_sdw_rt5682.o sof_sdw_rt700.o \
sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \
- sof_sdw_rt712_sdca.o sof_sdw_rt715.o \
- sof_sdw_rt715_sdca.o sof_sdw_rt722_sdca.o \
+ sof_sdw_rt712_sdca.o sof_sdw_rt722_sdca.o \
+ sof_sdw_rt_dmic.o \
sof_sdw_cs42l42.o sof_sdw_cs42l43.o \
sof_sdw_cs_amp.o \
sof_sdw_dmic.o \
@@ -101,8 +101,5 @@ obj-$(CONFIG_SND_SOC_INTEL_SOF_CIRRUS_COMMON) += snd-soc-intel-sof-cirrus-common
snd-soc-intel-sof-nuvoton-common-objs += sof_nuvoton_common.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_NUVOTON_COMMON) += snd-soc-intel-sof-nuvoton-common.o
-snd-soc-intel-sof-ssp-common-objs += sof_ssp_common.o
-obj-$(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON) += snd-soc-intel-sof-ssp-common.o
-
snd-soc-intel-sof-board-helpers-objs += sof_board_helpers.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_BOARD_HELPERS) += snd-soc-intel-sof-board-helpers.o
diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c
index a5135be94f32..eb140e13153f 100644
--- a/sound/soc/intel/boards/sof_board_helpers.c
+++ b/sound/soc/intel/boards/sof_board_helpers.c
@@ -103,13 +103,13 @@ static struct snd_soc_dai_link_component platform_component[] = {
};
static int set_ssp_codec_link(struct device *dev, struct snd_soc_dai_link *link,
- int be_id, enum sof_ssp_codec codec_type,
+ int be_id, enum snd_soc_acpi_intel_codec codec_type,
int ssp_codec)
{
struct snd_soc_dai_link_component *cpus;
dev_dbg(dev, "link %d: ssp codec %s, ssp %d\n", be_id,
- sof_ssp_get_codec_name(codec_type), ssp_codec);
+ snd_soc_acpi_intel_get_codec_name(codec_type), ssp_codec);
/* link name */
link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec);
@@ -259,12 +259,13 @@ static int set_idisp_hdmi_link(struct device *dev, struct snd_soc_dai_link *link
}
static int set_ssp_amp_link(struct device *dev, struct snd_soc_dai_link *link,
- int be_id, enum sof_ssp_codec amp_type, int ssp_amp)
+ int be_id, enum snd_soc_acpi_intel_codec amp_type,
+ int ssp_amp)
{
struct snd_soc_dai_link_component *cpus;
dev_dbg(dev, "link %d: ssp amp %s, ssp %d\n", be_id,
- sof_ssp_get_codec_name(amp_type), ssp_amp);
+ snd_soc_acpi_intel_get_codec_name(amp_type), ssp_amp);
/* link name */
link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_amp);
@@ -598,8 +599,8 @@ sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk)
if (!ctx)
return NULL;
- ctx->codec_type = sof_ssp_detect_codec_type(dev);
- ctx->amp_type = sof_ssp_detect_amp_type(dev);
+ ctx->codec_type = snd_soc_acpi_intel_detect_codec_type(dev);
+ ctx->amp_type = snd_soc_acpi_intel_detect_amp_type(dev);
ctx->dmic_be_num = 2;
ctx->hdmi_num = (board_quirk & SOF_NUM_IDISP_HDMI_MASK) >>
@@ -630,26 +631,8 @@ sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk)
}
EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, SND_SOC_INTEL_SOF_BOARD_HELPERS);
-struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd,
- const char * const dai_name[], int num_dais)
-{
- struct snd_soc_dai *dai;
- int index;
- int i;
-
- for (index = 0; index < num_dais; index++)
- for_each_rtd_codec_dais(rtd, i, dai)
- if (strstr(dai->name, dai_name[index])) {
- dev_dbg(rtd->card->dev, "get dai %s\n", dai->name);
- return dai;
- }
-
- return NULL;
-}
-EXPORT_SYMBOL_NS(get_codec_dai_by_name, SND_SOC_INTEL_SOF_BOARD_HELPERS);
-
MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers");
MODULE_AUTHOR("Brent Lu <[email protected]>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON);
+MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH);
diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h
index 2f27ad8726f8..644f6b4a1b7b 100644
--- a/sound/soc/intel/boards/sof_board_helpers.h
+++ b/sound/soc/intel/boards/sof_board_helpers.h
@@ -7,8 +7,8 @@
#define __SOF_INTEL_BOARD_HELPERS_H
#include <sound/soc.h>
+#include <sound/soc-acpi-intel-ssp-common.h>
#include "sof_hdmi_common.h"
-#include "sof_ssp_common.h"
/*
* Common board quirks: from bit 8 to 31, LSB 8 bits reserved for machine
@@ -132,8 +132,8 @@ struct sof_card_private {
struct snd_soc_jack headset_jack;
struct sof_hdmi_private hdmi;
- enum sof_ssp_codec codec_type;
- enum sof_ssp_codec amp_type;
+ enum snd_soc_acpi_intel_codec codec_type;
+ enum snd_soc_acpi_intel_codec amp_type;
int dmic_be_num;
int hdmi_num;
@@ -167,7 +167,4 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
struct sof_card_private *
sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk);
-struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd,
- const char * const dai_name[], int num_dais);
-
#endif /* __SOF_INTEL_BOARD_HELPERS_H */
diff --git a/sound/soc/intel/boards/sof_cirrus_common.h b/sound/soc/intel/boards/sof_cirrus_common.h
index d4ecf8d023d1..1c87637b9ef7 100644
--- a/sound/soc/intel/boards/sof_cirrus_common.h
+++ b/sound/soc/intel/boards/sof_cirrus_common.h
@@ -9,7 +9,7 @@
#define __SOF_CIRRUS_COMMON_H
#include <sound/soc.h>
-#include "sof_ssp_common.h"
+#include <sound/soc-acpi-intel-ssp-common.h>
/*
* Cirrus Logic CS35L41/CS35L53
diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c
index 40ecfeaa1d26..f4fee2ee0d63 100644
--- a/sound/soc/intel/boards/sof_cs42l42.c
+++ b/sound/soc/intel/boards/sof_cs42l42.c
@@ -263,13 +263,28 @@ static const struct platform_device_id board_ids[] = {
SOF_SSP_PORT_AMP(1)),
},
{
- .name = "adl_mx98360a_cs4242",
+ .name = "adl_cs42l42_def",
.driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) |
SOF_SSP_PORT_AMP(1) |
SOF_NUM_IDISP_HDMI(4) |
SOF_BT_OFFLOAD_PRESENT |
SOF_SSP_PORT_BT_OFFLOAD(2)),
},
+ {
+ .name = "rpl_cs42l42_def",
+ .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) |
+ SOF_SSP_PORT_AMP(1) |
+ SOF_NUM_IDISP_HDMI(4) |
+ SOF_BT_OFFLOAD_PRESENT |
+ SOF_SSP_PORT_BT_OFFLOAD(2)),
+ },
+ {
+ .name = "mtl_cs42l42_def",
+ .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(2) |
+ SOF_SSP_PORT_AMP(0) |
+ SOF_BT_OFFLOAD_PRESENT |
+ SOF_SSP_PORT_BT_OFFLOAD(1)),
+ },
{ }
};
MODULE_DEVICE_TABLE(platform, board_ids);
diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h
index fe0212fbad8e..8886f985de68 100644
--- a/sound/soc/intel/boards/sof_maxim_common.h
+++ b/sound/soc/intel/boards/sof_maxim_common.h
@@ -11,7 +11,7 @@
#define __SOF_MAXIM_COMMON_H
#include <sound/soc.h>
-#include "sof_ssp_common.h"
+#include <sound/soc-acpi-intel-ssp-common.h>
/*
* Maxim MAX98373
diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c
index 23fe8b4015cc..fe5f9e8dd652 100644
--- a/sound/soc/intel/boards/sof_nau8825.c
+++ b/sound/soc/intel/boards/sof_nau8825.c
@@ -319,6 +319,13 @@ static const struct platform_device_id board_ids[] = {
SOF_SSP_PORT_BT_OFFLOAD(2) |
SOF_BT_OFFLOAD_PRESENT),
},
+ {
+ .name = "mtl_nau8825_def",
+ .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(2) |
+ SOF_SSP_PORT_AMP(0) |
+ SOF_SSP_PORT_BT_OFFLOAD(1) |
+ SOF_BT_OFFLOAD_PRESENT),
+ },
{ }
};
MODULE_DEVICE_TABLE(platform, board_ids);
diff --git a/sound/soc/intel/boards/sof_nuvoton_common.h b/sound/soc/intel/boards/sof_nuvoton_common.h
index 53a84f9a67c0..8a0f283260e7 100644
--- a/sound/soc/intel/boards/sof_nuvoton_common.h
+++ b/sound/soc/intel/boards/sof_nuvoton_common.h
@@ -9,7 +9,7 @@
#define __SOF_NUVOTON_COMMON_H
#include <sound/soc.h>
-#include "sof_ssp_common.h"
+#include <sound/soc-acpi-intel-ssp-common.h>
/*
* Nuvoton NAU8318
diff --git a/sound/soc/intel/boards/sof_realtek_common.h b/sound/soc/intel/boards/sof_realtek_common.h
index e3fa2924c1c1..289e85b61660 100644
--- a/sound/soc/intel/boards/sof_realtek_common.h
+++ b/sound/soc/intel/boards/sof_realtek_common.h
@@ -11,7 +11,7 @@
#define __SOF_REALTEK_COMMON_H
#include <sound/soc.h>
-#include "sof_ssp_common.h"
+#include <sound/soc-acpi-intel-ssp-common.h>
/*
* Realtek ALC1011
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index 08f330ed5c2e..b94835448b1b 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -5,6 +5,7 @@
* sof_sdw - ASOC Machine driver for Intel SoundWire platforms
*/
+#include <linux/bitmap.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/module.h>
@@ -35,7 +36,9 @@ static void log_quirks(struct device *dev)
dev_dbg(dev, "SSP port %ld\n",
SOF_SSP_GET_PORT(sof_sdw_quirk));
if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION)
- dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n");
+ dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n");
+ if (sof_sdw_quirk & SOF_CODEC_SPKR)
+ dev_dbg(dev, "quirk SOF_CODEC_SPKR enabled\n");
}
static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
@@ -514,6 +517,24 @@ static struct snd_soc_dai_link_component platform_component[] = {
}
};
+struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd,
+ const char * const dai_name[],
+ int num_dais)
+{
+ struct snd_soc_dai *dai;
+ int index;
+ int i;
+
+ for (index = 0; index < num_dais; index++)
+ for_each_rtd_codec_dais(rtd, i, dai)
+ if (strstr(dai->name, dai_name[index])) {
+ dev_dbg(rtd->card->dev, "get dai %s\n", dai->name);
+ return dai;
+ }
+
+ return NULL;
+}
+
/* these wrappers are only needed to avoid typecast compilation errors */
int sdw_startup(struct snd_pcm_substream *substream)
{
@@ -730,7 +751,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt712-sdca-dmic-aif1",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .rtd_init = rt712_sdca_dmic_rtd_init,
+ .rtd_init = rt_dmic_rtd_init,
},
},
.dai_num = 1,
@@ -760,7 +781,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt712-sdca-dmic-aif1",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .rtd_init = rt712_sdca_dmic_rtd_init,
+ .rtd_init = rt_dmic_rtd_init,
},
},
.dai_num = 1,
@@ -819,10 +840,10 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dais = {
{
.direction = {false, true},
- .dai_name = "rt715-aif2",
+ .dai_name = "rt715-sdca-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .rtd_init = rt715_sdca_rtd_init,
+ .rtd_init = rt_dmic_rtd_init,
},
},
.dai_num = 1,
@@ -834,10 +855,10 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dais = {
{
.direction = {false, true},
- .dai_name = "rt715-aif2",
+ .dai_name = "rt715-sdca-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .rtd_init = rt715_sdca_rtd_init,
+ .rtd_init = rt_dmic_rtd_init,
},
},
.dai_num = 1,
@@ -852,7 +873,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt715-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .rtd_init = rt715_rtd_init,
+ .rtd_init = rt_dmic_rtd_init,
},
},
.dai_num = 1,
@@ -867,7 +888,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt715-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .rtd_init = rt715_rtd_init,
+ .rtd_init = rt_dmic_rtd_init,
},
},
.dai_num = 1,
@@ -883,6 +904,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt_sdca_jack_init,
.exit = sof_sdw_rt_sdca_jack_exit,
+ .rtd_init = rt_sdca_jack_rtd_init,
},
{
.direction = {true, false},
@@ -890,14 +912,14 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_type = SOF_SDW_DAI_TYPE_AMP,
/* No feedback capability is provided by rt722-sdca codec driver*/
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
- .init = sof_sdw_rt722_spk_init,
+ .rtd_init = rt722_spk_rtd_init,
},
{
.direction = {false, true},
.dai_name = "rt722-sdca-aif3",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .init = sof_sdw_rt722_sdca_dmic_init,
+ .rtd_init = rt_dmic_rtd_init,
},
},
.dai_num = 3,
@@ -994,8 +1016,17 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_UNUSED_DAI_ID, SDW_JACK_IN_DAI_ID},
},
+ {
+ .direction = {true, false},
+ .dai_name = "cs42l43-dp6",
+ .dai_type = SOF_SDW_DAI_TYPE_AMP,
+ .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
+ .init = sof_sdw_cs42l43_spk_init,
+ .rtd_init = cs42l43_spk_rtd_init,
+ .quirk = SOF_CODEC_SPKR,
+ },
},
- .dai_num = 3,
+ .dai_num = 4,
},
{
.part_id = 0xaaaa, /* generic codec mockup */
@@ -1006,7 +1037,6 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "sdw-mockup-aif1",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
- .init = NULL,
},
},
.dai_num = 1,
@@ -1020,7 +1050,6 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "sdw-mockup-aif1",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
- .init = NULL,
},
},
.dai_num = 1,
@@ -1034,7 +1063,6 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "sdw-mockup-aif1",
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
- .init = NULL,
},
},
.dai_num = 1,
@@ -1048,14 +1076,13 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.direction = {false, true},
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .init = NULL,
},
},
.dai_num = 1,
},
};
-static inline int find_codec_info_part(const u64 adr)
+static struct sof_sdw_codec_info *find_codec_info_part(const u64 adr)
{
unsigned int part_id, sdw_version;
int i;
@@ -1070,102 +1097,41 @@ static inline int find_codec_info_part(const u64 adr)
if (part_id == codec_info_list[i].part_id &&
(!codec_info_list[i].version_id ||
sdw_version == codec_info_list[i].version_id))
- return i;
+ return &codec_info_list[i];
- return -EINVAL;
+ return NULL;
}
-static inline int find_codec_info_acpi(const u8 *acpi_id)
+static struct sof_sdw_codec_info *find_codec_info_acpi(const u8 *acpi_id)
{
int i;
if (!acpi_id[0])
- return -EINVAL;
+ return NULL;
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN))
- return i;
+ return &codec_info_list[i];
- return -EINVAL;
+ return NULL;
}
-/*
- * get BE dailink number and CPU DAI number based on sdw link adr.
- * Since some sdw slaves may be aggregated, the CPU DAI number
- * may be larger than the number of BE dailinks.
- */
-static int get_dailink_info(struct device *dev,
- const struct snd_soc_acpi_link_adr *adr_link,
- int *sdw_be_num, int *codecs_num)
+static struct sof_sdw_codec_info *find_codec_info_dai(const char *dai_name,
+ int *dai_index)
{
- bool group_visited[SDW_MAX_GROUPS];
- bool no_aggregation;
- int i;
- int j;
-
- no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
- *sdw_be_num = 0;
-
- if (!adr_link)
- return -EINVAL;
-
- for (i = 0; i < SDW_MAX_GROUPS; i++)
- group_visited[i] = false;
-
- for (; adr_link->num_adr; adr_link++) {
- const struct snd_soc_acpi_endpoint *endpoint;
- struct sof_sdw_codec_info *codec_info;
- int codec_index;
- int stream;
- u64 adr;
-
- /* make sure the link mask has a single bit set */
- if (!is_power_of_2(adr_link->mask))
- return -EINVAL;
-
- for (i = 0; i < adr_link->num_adr; i++) {
- adr = adr_link->adr_d[i].adr;
- codec_index = find_codec_info_part(adr);
- if (codec_index < 0)
- return codec_index;
-
- codec_info = &codec_info_list[codec_index];
-
- *codecs_num += codec_info->dai_num;
-
- if (!adr_link->adr_d[i].name_prefix) {
- dev_err(dev, "codec 0x%llx does not have a name prefix\n",
- adr_link->adr_d[i].adr);
- return -EINVAL;
- }
-
- endpoint = adr_link->adr_d[i].endpoints;
- if (endpoint->aggregated && !endpoint->group_id) {
- dev_err(dev, "invalid group id on link %x\n",
- adr_link->mask);
- return -EINVAL;
- }
-
- for (j = 0; j < codec_info->dai_num; j++) {
- /* count DAI number for playback and capture */
- for_each_pcm_streams(stream) {
- if (!codec_info->dais[j].direction[stream])
- continue;
+ int i, j;
- /* count BE for each non-aggregated slave or group */
- if (!endpoint->aggregated || no_aggregation ||
- !group_visited[endpoint->group_id])
- (*sdw_be_num)++;
- }
+ for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
+ for (j = 0; j < codec_info_list[i].dai_num; j++) {
+ if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) {
+ *dai_index = j;
+ return &codec_info_list[i];
}
-
- if (endpoint->aggregated)
- group_visited[endpoint->group_id] = true;
}
}
- return 0;
+ return NULL;
}
static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
@@ -1250,195 +1216,45 @@ static bool is_unique_device(const struct snd_soc_acpi_link_adr *adr_link,
return true;
}
-static int fill_sdw_codec_dlc(struct device *dev,
- const struct snd_soc_acpi_link_adr *adr_link,
- struct snd_soc_dai_link_component *codec,
- int adr_index, int dai_index)
+static const char *get_codec_name(struct device *dev,
+ const struct sof_sdw_codec_info *codec_info,
+ const struct snd_soc_acpi_link_adr *adr_link,
+ int adr_index)
{
- unsigned int sdw_version, unique_id, mfg_id, link_id, part_id, class_id;
u64 adr = adr_link->adr_d[adr_index].adr;
- int codec_index;
-
- codec_index = find_codec_info_part(adr);
- if (codec_index < 0)
- return codec_index;
-
- sdw_version = SDW_VERSION(adr);
- link_id = SDW_DISCO_LINK_ID(adr);
- unique_id = SDW_UNIQUE_ID(adr);
- mfg_id = SDW_MFG_ID(adr);
- part_id = SDW_PART_ID(adr);
- class_id = SDW_CLASS_ID(adr);
-
- if (codec_info_list[codec_index].codec_name)
- codec->name = devm_kstrdup(dev,
- codec_info_list[codec_index].codec_name,
- GFP_KERNEL);
+ unsigned int sdw_version = SDW_VERSION(adr);
+ unsigned int link_id = SDW_DISCO_LINK_ID(adr);
+ unsigned int unique_id = SDW_UNIQUE_ID(adr);
+ unsigned int mfg_id = SDW_MFG_ID(adr);
+ unsigned int part_id = SDW_PART_ID(adr);
+ unsigned int class_id = SDW_CLASS_ID(adr);
+
+ if (codec_info->codec_name)
+ return devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL);
else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id,
class_id, adr_index))
- codec->name = devm_kasprintf(dev, GFP_KERNEL,
- "sdw:0:%01x:%04x:%04x:%02x", link_id,
- mfg_id, part_id, class_id);
+ return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x",
+ link_id, mfg_id, part_id, class_id);
else
- codec->name = devm_kasprintf(dev, GFP_KERNEL,
- "sdw:0:%01x:%04x:%04x:%02x:%01x", link_id,
- mfg_id, part_id, class_id, unique_id);
-
- if (!codec->name)
- return -ENOMEM;
-
- codec->dai_name = codec_info_list[codec_index].dais[dai_index].dai_name;
-
- return 0;
-}
-
-static int set_codec_init_func(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *adr_link,
- struct snd_soc_dai_link *dai_links,
- bool playback, int group_id, int adr_index, int dai_index)
-{
- int i = adr_index;
-
- do {
- /*
- * Initialize the codec. If codec is part of an aggregated
- * group (group_id>0), initialize all codecs belonging to
- * same group.
- * The first link should start with adr_link->adr_d[adr_index]
- * because that is the device that we want to initialize and
- * we should end immediately if it is not aggregated (group_id=0)
- */
- for ( ; i < adr_link->num_adr; i++) {
- int codec_index;
-
- codec_index = find_codec_info_part(adr_link->adr_d[i].adr);
- if (codec_index < 0)
- return codec_index;
-
- /* The group_id is > 0 iff the codec is aggregated */
- if (adr_link->adr_d[i].endpoints->group_id != group_id)
- continue;
-
- if (codec_info_list[codec_index].dais[dai_index].init)
- codec_info_list[codec_index].dais[dai_index].init(card,
- adr_link,
- dai_links,
- &codec_info_list[codec_index],
- playback);
- if (!group_id)
- return 0;
- }
-
- i = 0;
- adr_link++;
- } while (adr_link->mask);
-
- return 0;
-}
-
-/*
- * check endpoint status in slaves and gather link ID for all slaves in
- * the same group to generate different CPU DAI. Now only support
- * one sdw link with all slaves set with only single group id.
- *
- * one slave on one sdw link with aggregated = 0
- * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI
- *
- * two or more slaves on one sdw link with aggregated = 0
- * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs
- *
- * multiple links with multiple slaves with aggregated = 1
- * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs
- */
-static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
- struct device *dev, int *cpu_dai_id, int *cpu_dai_num,
- int *codec_num, unsigned int *group_id,
- int adr_index)
-{
- bool no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
- int i;
-
- if (!adr_link->adr_d[adr_index].endpoints->aggregated || no_aggregation) {
- cpu_dai_id[0] = ffs(adr_link->mask) - 1;
- *cpu_dai_num = 1;
- *codec_num = 1;
- *group_id = 0;
- return 0;
- }
-
- *codec_num = 0;
- *cpu_dai_num = 0;
- *group_id = adr_link->adr_d[adr_index].endpoints->group_id;
-
- /* Count endpoints with the same group_id in the adr_link */
- for (; adr_link && adr_link->num_adr; adr_link++) {
- unsigned int link_codecs = 0;
-
- for (i = 0; i < adr_link->num_adr; i++) {
- if (adr_link->adr_d[i].endpoints->aggregated &&
- adr_link->adr_d[i].endpoints->group_id == *group_id)
- link_codecs++;
- }
-
- if (link_codecs) {
- *codec_num += link_codecs;
-
- if (*cpu_dai_num >= SDW_MAX_CPU_DAIS) {
- dev_err(dev, "cpu_dai_id array overflowed\n");
- return -EINVAL;
- }
+ return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x",
+ link_id, mfg_id, part_id, class_id, unique_id);
- cpu_dai_id[(*cpu_dai_num)++] = ffs(adr_link->mask) - 1;
- }
- }
-
- return 0;
-}
-
-static void set_dailink_map(struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps,
- int codec_num, int cpu_num)
-{
- int step;
- int i;
-
- step = codec_num / cpu_num;
- for (i = 0; i < codec_num; i++) {
- sdw_codec_ch_maps[i].cpu = i / step;
- sdw_codec_ch_maps[i].codec = i;
- }
-}
-
-static inline int find_codec_info_dai(const char *dai_name, int *dai_index)
-{
- int i, j;
-
- for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
- for (j = 0; j < codec_info_list[i].dai_num; j++) {
- if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) {
- *dai_index = j;
- return i;
- }
- }
- }
-
- return -EINVAL;
+ return NULL;
}
static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct sof_sdw_codec_info *codec_info;
struct snd_soc_dai *dai;
- int codec_index;
int dai_index;
int ret;
int i;
for_each_rtd_codec_dais(rtd, i, dai) {
- codec_index = find_codec_info_dai(dai->name, &dai_index);
- if (codec_index < 0)
+ codec_info = find_codec_info_dai(dai->name, &dai_index);
+ if (!codec_info)
return -EINVAL;
- codec_info = &codec_info_list[codec_index];
/*
* A codec dai can be connected to different dai links for capture and playback,
* but we only need to call the rtd_init function once.
@@ -1458,187 +1274,445 @@ static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
+struct sof_sdw_endpoint {
+ struct list_head list;
+
+ u32 link_mask;
+ const char *codec_name;
+
+ struct sof_sdw_codec_info *codec_info;
+ const struct sof_sdw_dai_info *dai_info;
+};
+
+struct sof_sdw_dailink {
+ bool initialised;
+
+ u8 group_id;
+ u32 link_mask[SNDRV_PCM_STREAM_LAST + 1];
+ int num_devs[SNDRV_PCM_STREAM_LAST + 1];
+ struct list_head endpoints;
+};
+
static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
-static int create_sdw_dailink(struct snd_soc_card *card, int *link_index,
- struct snd_soc_dai_link *dai_links, int sdw_be_num,
- const struct snd_soc_acpi_link_adr *adr_link,
- struct snd_soc_codec_conf *codec_conf,
- int codec_count, int *be_id,
- int *codec_conf_index,
- bool *ignore_pch_dmic,
- bool append_dai_type,
- int adr_index,
- int dai_index)
+static int count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends)
{
- struct mc_private *ctx = snd_soc_card_get_drvdata(card);
struct device *dev = card->dev;
- const struct snd_soc_acpi_link_adr *adr_link_next;
- struct snd_soc_dai_link_component *codecs;
- struct snd_soc_dai_link_component *cpus;
- struct sof_sdw_codec_info *codec_info;
- int cpu_dai_id[SDW_MAX_CPU_DAIS];
- int cpu_dai_num;
- unsigned int group_id;
- int codec_dlc_index = 0;
- int codec_index;
- int codec_num;
- int stream;
- int i = 0;
- int j, k;
- int ret;
+ struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
+ struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
+ const struct snd_soc_acpi_link_adr *adr_link;
+ int i;
- ret = get_slave_info(adr_link, dev, cpu_dai_id, &cpu_dai_num, &codec_num,
- &group_id, adr_index);
- if (ret)
- return ret;
+ for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
+ *num_devs += adr_link->num_adr;
- codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL);
- if (!codecs)
- return -ENOMEM;
+ for (i = 0; i < adr_link->num_adr; i++)
+ *num_ends += adr_link->adr_d[i].num_endpoints;
+ }
- /* generate codec name on different links in the same group */
- j = adr_index;
- for (adr_link_next = adr_link; adr_link_next && adr_link_next->num_adr &&
- i < cpu_dai_num; adr_link_next++) {
- /* skip the link excluded by this processed group */
- if (cpu_dai_id[i] != ffs(adr_link_next->mask) - 1)
- continue;
+ dev_dbg(dev, "Found %d devices with %d endpoints\n", *num_devs, *num_ends);
- /* j reset after loop, adr_index only applies to first link */
- for (; j < adr_link_next->num_adr && codec_dlc_index < codec_num; j++) {
- const struct snd_soc_acpi_endpoint *endpoints;
+ return 0;
+}
- endpoints = adr_link_next->adr_d[j].endpoints;
+static struct sof_sdw_dailink *find_dailink(struct sof_sdw_dailink *dailinks,
+ const struct snd_soc_acpi_endpoint *new)
+{
+ while (dailinks->initialised) {
+ if (new->aggregated && dailinks->group_id == new->group_id)
+ return dailinks;
- if (group_id && (!endpoints->aggregated ||
- endpoints->group_id != group_id))
- continue;
+ dailinks++;
+ }
+
+ INIT_LIST_HEAD(&dailinks->endpoints);
+ dailinks->group_id = new->group_id;
+ dailinks->initialised = true;
+
+ return dailinks;
+}
+
+static int parse_sdw_endpoints(struct snd_soc_card *card,
+ struct sof_sdw_dailink *sof_dais,
+ struct sof_sdw_endpoint *sof_ends)
+{
+ struct device *dev = card->dev;
+ struct mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
+ struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
+ struct snd_soc_codec_conf *codec_conf = card->codec_conf;
+ const struct snd_soc_acpi_link_adr *adr_link;
+ struct sof_sdw_endpoint *sof_end = sof_ends;
+ int num_dais = 0;
+ int i, j;
+
+ for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
+ int num_link_dailinks = 0;
+
+ if (!is_power_of_2(adr_link->mask)) {
+ dev_err(dev, "link with multiple mask bits: 0x%x\n",
+ adr_link->mask);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < adr_link->num_adr; i++) {
+ const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i];
+ struct sof_sdw_codec_info *codec_info;
+ const char *codec_name;
- /* sanity check */
- if (*codec_conf_index >= codec_count) {
- dev_err(dev, "codec_conf array overflowed\n");
+ if (!adr_dev->name_prefix) {
+ dev_err(dev, "codec 0x%llx does not have a name prefix\n",
+ adr_dev->adr);
return -EINVAL;
}
- ret = fill_sdw_codec_dlc(dev, adr_link_next,
- &codecs[codec_dlc_index],
- j, dai_index);
- if (ret)
- return ret;
+ codec_info = find_codec_info_part(adr_dev->adr);
+ if (!codec_info)
+ return -EINVAL;
+
+ ctx->ignore_pch_dmic |= codec_info->ignore_pch_dmic;
- codec_conf[*codec_conf_index].dlc = codecs[codec_dlc_index];
- codec_conf[*codec_conf_index].name_prefix =
- adr_link_next->adr_d[j].name_prefix;
+ codec_name = get_codec_name(dev, codec_info, adr_link, i);
+ if (!codec_name)
+ return -ENOMEM;
+
+ codec_conf->dlc.name = codec_name;
+ codec_conf->name_prefix = adr_dev->name_prefix;
+ codec_conf++;
+
+ dev_dbg(dev, "Adding prefix %s for %s\n",
+ adr_dev->name_prefix, codec_name);
+
+ for (j = 0; j < adr_dev->num_endpoints; j++) {
+ const struct snd_soc_acpi_endpoint *adr_end;
+ const struct sof_sdw_dai_info *dai_info;
+ struct sof_sdw_dailink *sof_dai;
+ int stream;
+
+ adr_end = &adr_dev->endpoints[j];
+ dai_info = &codec_info->dais[adr_end->num];
+ sof_dai = find_dailink(sof_dais, adr_end);
+
+ if (dai_info->quirk && !(dai_info->quirk & sof_sdw_quirk))
+ continue;
+
+ dev_dbg(dev,
+ "Add dev: %d, 0x%llx end: %d, %s, %c/%c to %s: %d\n",
+ ffs(adr_link->mask) - 1, adr_dev->adr,
+ adr_end->num, type_strings[dai_info->dai_type],
+ dai_info->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-',
+ dai_info->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-',
+ adr_end->aggregated ? "group" : "solo",
+ adr_end->group_id);
+
+ if (adr_end->num >= codec_info->dai_num) {
+ dev_err(dev,
+ "%d is too many endpoints for codec: 0x%x\n",
+ adr_end->num, codec_info->part_id);
+ return -EINVAL;
+ }
- codec_dlc_index++;
- (*codec_conf_index)++;
+ for_each_pcm_streams(stream) {
+ if (dai_info->direction[stream] &&
+ dai_info->dailink[stream] < 0) {
+ dev_err(dev,
+ "Invalid dailink id %d for codec: 0x%x\n",
+ dai_info->dailink[stream],
+ codec_info->part_id);
+ return -EINVAL;
+ }
+
+ if (dai_info->direction[stream]) {
+ num_dais += !sof_dai->num_devs[stream];
+ sof_dai->num_devs[stream]++;
+ sof_dai->link_mask[stream] |= adr_link->mask;
+ }
+ }
+
+ num_link_dailinks += !!list_empty(&sof_dai->endpoints);
+ list_add_tail(&sof_end->list, &sof_dai->endpoints);
+
+ sof_end->link_mask = adr_link->mask;
+ sof_end->codec_name = codec_name;
+ sof_end->codec_info = codec_info;
+ sof_end->dai_info = dai_info;
+ sof_end++;
+ }
}
- j = 0;
- /* check next link to create codec dai in the processed group */
- i++;
+ ctx->append_dai_type |= (num_link_dailinks > 1);
}
- /* find codec info to create BE DAI */
- codec_index = find_codec_info_part(adr_link->adr_d[adr_index].adr);
- if (codec_index < 0)
- return codec_index;
- codec_info = &codec_info_list[codec_index];
+ WARN_ON(codec_conf != card->codec_conf + card->num_configs);
+
+ return num_dais;
+}
- if (codec_info->ignore_pch_dmic)
- *ignore_pch_dmic = true;
+static int create_sdw_dailink(struct snd_soc_card *card,
+ struct sof_sdw_dailink *sof_dai,
+ struct snd_soc_dai_link **dai_links,
+ int *be_id)
+{
+ struct device *dev = card->dev;
+ struct mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct sof_sdw_endpoint *sof_end;
+ int stream;
for_each_pcm_streams(stream) {
- struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps;
- char *name, *cpu_name;
- int playback, capture;
static const char * const sdw_stream_name[] = {
"SDW%d-Playback",
"SDW%d-Capture",
"SDW%d-Playback-%s",
"SDW%d-Capture-%s",
};
+ struct snd_soc_dai_link_ch_map *codec_maps;
+ struct snd_soc_dai_link_component *codecs;
+ struct snd_soc_dai_link_component *cpus;
+ int num_cpus = hweight32(sof_dai->link_mask[stream]);
+ int num_codecs = sof_dai->num_devs[stream];
+ int playback, capture;
+ int cur_link = 0;
+ int i = 0, j = 0;
+ char *name;
- if (!codec_info->dais[dai_index].direction[stream])
+ if (!sof_dai->num_devs[stream])
continue;
- *be_id = codec_info->dais[dai_index].dailink[stream];
+ sof_end = list_first_entry(&sof_dai->endpoints,
+ struct sof_sdw_endpoint, list);
+
+ *be_id = sof_end->dai_info->dailink[stream];
if (*be_id < 0) {
dev_err(dev, "Invalid dailink id %d\n", *be_id);
return -EINVAL;
}
- sdw_codec_ch_maps = devm_kcalloc(dev, codec_num,
- sizeof(*sdw_codec_ch_maps), GFP_KERNEL);
- if (!sdw_codec_ch_maps)
- return -ENOMEM;
-
/* create stream name according to first link id */
- if (append_dai_type) {
+ if (ctx->append_dai_type)
name = devm_kasprintf(dev, GFP_KERNEL,
- sdw_stream_name[stream + 2], cpu_dai_id[0],
- type_strings[codec_info->dais[dai_index].dai_type]);
- } else {
+ sdw_stream_name[stream + 2],
+ ffs(sof_end->link_mask) - 1,
+ type_strings[sof_end->dai_info->dai_type]);
+ else
name = devm_kasprintf(dev, GFP_KERNEL,
- sdw_stream_name[stream], cpu_dai_id[0]);
- }
+ sdw_stream_name[stream],
+ ffs(sof_end->link_mask) - 1);
if (!name)
return -ENOMEM;
- cpus = devm_kcalloc(dev, cpu_dai_num, sizeof(*cpus), GFP_KERNEL);
+ cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL);
if (!cpus)
return -ENOMEM;
- /*
- * generate CPU DAI name base on the sdw link ID and
- * PIN ID with offset of 2 according to sdw dai driver.
- */
- for (k = 0; k < cpu_dai_num; k++) {
- cpu_name = devm_kasprintf(dev, GFP_KERNEL,
- "SDW%d Pin%d", cpu_dai_id[k],
- ctx->sdw_pin_index[cpu_dai_id[k]]++);
- if (!cpu_name)
- return -ENOMEM;
+ codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL);
+ if (!codecs)
+ return -ENOMEM;
- cpus[k].dai_name = cpu_name;
- }
+ codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL);
+ if (!codec_maps)
+ return -ENOMEM;
- /*
- * We create sdw dai links at first stage, so link index should
- * not be larger than sdw_be_num
- */
- if (*link_index >= sdw_be_num) {
- dev_err(dev, "invalid dai link index %d\n", *link_index);
- return -EINVAL;
+ list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
+ if (!sof_end->dai_info->direction[stream])
+ continue;
+
+ if (cur_link != sof_end->link_mask) {
+ int link_num = ffs(sof_end->link_mask) - 1;
+ int pin_num = ctx->sdw_pin_index[link_num]++;
+
+ cur_link = sof_end->link_mask;
+
+ cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL,
+ "SDW%d Pin%d",
+ link_num, pin_num);
+ if (!cpus[i].dai_name)
+ return -ENOMEM;
+ i++;
+ }
+
+ codec_maps[j].cpu = i - 1;
+ codec_maps[j].codec = j;
+
+ codecs[j].name = sof_end->codec_name;
+ codecs[j].dai_name = sof_end->dai_info->dai_name;
+ j++;
}
+ WARN_ON(i != num_cpus || j != num_codecs);
+
playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
- init_dai_link(dev, dai_links + *link_index, be_id, name,
- playback, capture, cpus, cpu_dai_num, codecs, codec_num,
+ init_dai_link(dev, *dai_links, be_id, name, playback, capture,
+ cpus, num_cpus, codecs, num_codecs,
sof_sdw_rtd_init, &sdw_ops);
/*
* SoundWire DAILINKs use 'stream' functions and Bank Switch operations
* based on wait_for_completion(), tag them as 'nonatomic'.
*/
- dai_links[*link_index].nonatomic = true;
-
- set_dailink_map(sdw_codec_ch_maps, codec_num, cpu_dai_num);
- dai_links[*link_index].ch_maps = sdw_codec_ch_maps;
- ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++,
- playback, group_id, adr_index, dai_index);
- if (ret < 0) {
- dev_err(dev, "failed to init codec %d\n", codec_index);
+ (*dai_links)->nonatomic = true;
+ (*dai_links)->ch_maps = codec_maps;
+
+ list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
+ if (sof_end->dai_info->init)
+ sof_end->dai_info->init(card, *dai_links,
+ sof_end->codec_info,
+ playback);
+ }
+
+ (*dai_links)++;
+ }
+
+ return 0;
+}
+
+static int create_sdw_dailinks(struct snd_soc_card *card,
+ struct snd_soc_dai_link **dai_links, int *be_id,
+ struct sof_sdw_dailink *sof_dais)
+{
+ struct mc_private *ctx = snd_soc_card_get_drvdata(card);
+ int ret, i;
+
+ for (i = 0; i < SDW_MAX_LINKS; i++)
+ ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE;
+
+ /* generate DAI links by each sdw link */
+ while (sof_dais->initialised) {
+ int current_be_id;
+
+ ret = create_sdw_dailink(card, sof_dais, dai_links, &current_be_id);
+ if (ret)
+ return ret;
+
+ /* Update the be_id to match the highest ID used for SDW link */
+ if (*be_id < current_be_id)
+ *be_id = current_be_id;
+
+ sof_dais++;
+ }
+
+ return 0;
+}
+
+static int create_ssp_dailinks(struct snd_soc_card *card,
+ struct snd_soc_dai_link **dai_links, int *be_id,
+ struct sof_sdw_codec_info *ssp_info,
+ unsigned long ssp_mask)
+{
+ struct device *dev = card->dev;
+ int i, j = 0;
+ int ret;
+
+ for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) {
+ char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i);
+ char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
+ char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
+ ssp_info->acpi_id, j++);
+ int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK];
+ int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE];
+
+ ret = init_simple_dai_link(dev, *dai_links, be_id, name,
+ playback, capture, cpu_dai_name,
+ codec_name, ssp_info->dais[0].dai_name,
+ NULL, ssp_info->ops);
+ if (ret)
+ return ret;
+
+ ret = ssp_info->dais[0].init(card, *dai_links, ssp_info, 0);
+ if (ret < 0)
return ret;
+
+ (*dai_links)++;
+ }
+
+ return 0;
+}
+
+static int create_dmic_dailinks(struct snd_soc_card *card,
+ struct snd_soc_dai_link **dai_links, int *be_id)
+{
+ struct device *dev = card->dev;
+ int ret;
+
+ ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic01",
+ 0, 1, // DMIC only supports capture
+ "DMIC01 Pin", "dmic-codec", "dmic-hifi",
+ sof_sdw_dmic_init, NULL);
+ if (ret)
+ return ret;
+
+ (*dai_links)++;
+
+ ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic16k",
+ 0, 1, // DMIC only supports capture
+ "DMIC16k Pin", "dmic-codec", "dmic-hifi",
+ /* don't call sof_sdw_dmic_init() twice */
+ NULL, NULL);
+ if (ret)
+ return ret;
+
+ (*dai_links)++;
+
+ return 0;
+}
+
+static int create_hdmi_dailinks(struct snd_soc_card *card,
+ struct snd_soc_dai_link **dai_links, int *be_id,
+ int hdmi_num)
+{
+ struct device *dev = card->dev;
+ struct mc_private *ctx = snd_soc_card_get_drvdata(card);
+ int i, ret;
+
+ for (i = 0; i < hdmi_num; i++) {
+ char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1);
+ char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1);
+ char *codec_name, *codec_dai_name;
+
+ if (ctx->hdmi.idisp_codec) {
+ codec_name = "ehdaudio0D2";
+ codec_dai_name = devm_kasprintf(dev, GFP_KERNEL,
+ "intel-hdmi-hifi%d", i + 1);
+ } else {
+ codec_name = "snd-soc-dummy";
+ codec_dai_name = "snd-soc-dummy-dai";
}
+
+ ret = init_simple_dai_link(dev, *dai_links, be_id, name,
+ 1, 0, // HDMI only supports playback
+ cpu_dai_name, codec_name, codec_dai_name,
+ i == 0 ? sof_sdw_hdmi_init : NULL, NULL);
+ if (ret)
+ return ret;
+
+ (*dai_links)++;
}
return 0;
}
+static int create_bt_dailinks(struct snd_soc_card *card,
+ struct snd_soc_dai_link **dai_links, int *be_id)
+{
+ struct device *dev = card->dev;
+ int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
+ SOF_BT_OFFLOAD_SSP_SHIFT;
+ char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
+ char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port);
+ int ret;
+
+ ret = init_simple_dai_link(dev, *dai_links, be_id, name,
+ 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name,
+ snd_soc_dummy_dlc.dai_name, NULL, NULL);
+ if (ret)
+ return ret;
+
+ (*dai_links)++;
+
+ return 0;
+}
+
static int sof_card_dai_links_create(struct snd_soc_card *card)
{
struct device *dev = card->dev;
@@ -1646,38 +1720,61 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
- const struct snd_soc_acpi_link_adr *adr_link = mach_params->links;
- bool aggregation = !(sof_sdw_quirk & SOF_SDW_NO_AGGREGATION);
struct snd_soc_codec_conf *codec_conf;
- bool append_dai_type = false;
- bool ignore_pch_dmic = false;
- int codec_conf_num = 0;
- int codec_conf_index = 0;
- bool group_generated[SDW_MAX_GROUPS] = { };
- int ssp_codec_index, ssp_mask;
+ struct sof_sdw_codec_info *ssp_info;
+ struct sof_sdw_endpoint *sof_ends;
+ struct sof_sdw_dailink *sof_dais;
+ int num_devs = 0;
+ int num_ends = 0;
struct snd_soc_dai_link *dai_links;
- int num_links, link_index = 0;
- char *name, *cpu_dai_name;
- char *codec_name, *codec_dai_name;
- int i, j, be_id = 0;
- int codec_index;
+ int num_links;
+ int be_id = 0;
int hdmi_num;
+ unsigned long ssp_mask;
int ret;
- ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num);
+ ret = count_sdw_endpoints(card, &num_devs, &num_ends);
if (ret < 0) {
- dev_err(dev, "failed to get sdw link info %d\n", ret);
+ dev_err(dev, "failed to count devices/endpoints: %d\n", ret);
return ret;
}
+ /* One per DAI link, worst case is a DAI link for every endpoint */
+ sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL);
+ if (!sof_dais)
+ return -ENOMEM;
+
+ /* One per endpoint, ie. each DAI on each codec/amp */
+ sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL);
+ if (!sof_ends) {
+ ret = -ENOMEM;
+ goto err_dai;
+ }
+
+ /* will be populated when acpi endpoints are parsed */
+ codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
+ if (!codec_conf) {
+ ret = -ENOMEM;
+ goto err_end;
+ }
+
+ card->codec_conf = codec_conf;
+ card->num_configs = num_devs;
+
+ ret = parse_sdw_endpoints(card, sof_dais, sof_ends);
+ if (ret < 0)
+ goto err_end;
+
+ sdw_be_num = ret;
+
/*
* on generic tgl platform, I2S or sdw mode is supported
* based on board rework. A ACPI device is registered in
* system only when I2S mode is supported, not sdw mode.
* Here check ACPI ID to confirm I2S is supported.
*/
- ssp_codec_index = find_codec_info_acpi(mach->id);
- if (ssp_codec_index >= 0) {
+ ssp_info = find_codec_info_acpi(mach->id);
+ if (ssp_info) {
ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
ssp_num = hweight_long(ssp_mask);
}
@@ -1704,201 +1801,60 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
/* allocate BE dailinks */
num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num;
dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
- if (!dai_links)
- return -ENOMEM;
-
- /* allocate codec conf, will be populated when dailinks are created */
- codec_conf = devm_kcalloc(dev, codec_conf_num, sizeof(*codec_conf),
- GFP_KERNEL);
- if (!codec_conf)
- return -ENOMEM;
-
- /* SDW */
- if (!sdw_be_num)
- goto SSP;
-
- for (i = 0; i < SDW_MAX_LINKS; i++)
- ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE;
-
- for (; adr_link->num_adr; adr_link++) {
- /*
- * If there are two or more different devices on the same sdw link, we have to
- * append the codec type to the dai link name to prevent duplicated dai link name.
- * The same type devices on the same sdw link will be in the same
- * snd_soc_acpi_adr_device array. They won't be described in different adr_links.
- */
- for (i = 0; i < adr_link->num_adr; i++) {
- /* find codec info to get dai_num */
- codec_index = find_codec_info_part(adr_link->adr_d[i].adr);
- if (codec_index < 0)
- return codec_index;
- if (codec_info_list[codec_index].dai_num > 1) {
- append_dai_type = true;
- goto out;
- }
- for (j = 0; j < i; j++) {
- if ((SDW_PART_ID(adr_link->adr_d[i].adr) !=
- SDW_PART_ID(adr_link->adr_d[j].adr)) ||
- (SDW_MFG_ID(adr_link->adr_d[i].adr) !=
- SDW_MFG_ID(adr_link->adr_d[j].adr))) {
- append_dai_type = true;
- goto out;
- }
- }
- }
+ if (!dai_links) {
+ ret = -ENOMEM;
+ goto err_end;
}
-out:
-
- /* generate DAI links by each sdw link */
- for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) {
- for (i = 0; i < adr_link->num_adr; i++) {
- const struct snd_soc_acpi_endpoint *endpoint;
-
- endpoint = adr_link->adr_d[i].endpoints;
-
- /* this group has been generated */
- if (endpoint->aggregated &&
- group_generated[endpoint->group_id])
- continue;
- /* find codec info to get dai_num */
- codec_index = find_codec_info_part(adr_link->adr_d[i].adr);
- if (codec_index < 0)
- return codec_index;
-
- for (j = 0; j < codec_info_list[codec_index].dai_num ; j++) {
- int current_be_id;
-
- ret = create_sdw_dailink(card, &link_index, dai_links,
- sdw_be_num, adr_link,
- codec_conf, codec_conf_num,
- &current_be_id, &codec_conf_index,
- &ignore_pch_dmic, append_dai_type, i, j);
- if (ret < 0) {
- dev_err(dev, "failed to create dai link %d\n", link_index);
- return ret;
- }
-
- /* Update the be_id to match the highest ID used for SDW link */
- if (be_id < current_be_id)
- be_id = current_be_id;
- }
+ card->dai_link = dai_links;
+ card->num_links = num_links;
- if (aggregation && endpoint->aggregated)
- group_generated[endpoint->group_id] = true;
- }
+ /* SDW */
+ if (sdw_be_num) {
+ ret = create_sdw_dailinks(card, &dai_links, &be_id, sof_dais);
+ if (ret)
+ goto err_end;
}
-SSP:
/* SSP */
- if (!ssp_num)
- goto DMIC;
-
- for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) {
- struct sof_sdw_codec_info *info;
- int playback, capture;
-
- if (!(ssp_mask & 0x1))
- continue;
-
- info = &codec_info_list[ssp_codec_index];
-
- name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i);
- cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
- codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
- info->acpi_id, j++);
-
- playback = info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK];
- capture = info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE];
-
- ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name,
- playback, capture, cpu_dai_name,
- codec_name, info->dais[0].dai_name,
- NULL, info->ops);
+ if (ssp_num) {
+ ret = create_ssp_dailinks(card, &dai_links, &be_id,
+ ssp_info, ssp_mask);
if (ret)
- return ret;
-
- ret = info->dais[0].init(card, NULL, dai_links + link_index, info, 0);
- if (ret < 0)
- return ret;
-
- link_index++;
+ goto err_end;
}
-DMIC:
/* dmic */
if (dmic_num > 0) {
- if (ignore_pch_dmic) {
+ if (ctx->ignore_pch_dmic) {
dev_warn(dev, "Ignoring PCH DMIC\n");
- goto HDMI;
+ } else {
+ ret = create_dmic_dailinks(card, &dai_links, &be_id);
+ if (ret)
+ goto err_end;
}
-
- ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, "dmic01",
- 0, 1, // DMIC only supports capture
- "DMIC01 Pin", "dmic-codec", "dmic-hifi",
- sof_sdw_dmic_init, NULL);
- if (ret)
- return ret;
-
- link_index++;
-
- ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, "dmic16k",
- 0, 1, // DMIC only supports capture
- "DMIC16k Pin", "dmic-codec", "dmic-hifi",
- /* don't call sof_sdw_dmic_init() twice */
- NULL, NULL);
- if (ret)
- return ret;
-
- link_index++;
}
-HDMI:
/* HDMI */
- for (i = 0; i < hdmi_num; i++) {
- name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1);
- cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1);
-
- if (ctx->hdmi.idisp_codec) {
- codec_name = "ehdaudio0D2";
- codec_dai_name = devm_kasprintf(dev, GFP_KERNEL,
- "intel-hdmi-hifi%d", i + 1);
- } else {
- codec_name = "snd-soc-dummy";
- codec_dai_name = "snd-soc-dummy-dai";
- }
-
- ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name,
- 1, 0, // HDMI only supports playback
- cpu_dai_name, codec_name, codec_dai_name,
- i == 0 ? sof_sdw_hdmi_init : NULL, NULL);
- if (ret)
- return ret;
-
- link_index++;
- }
+ ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num);
+ if (ret)
+ goto err_end;
+ /* BT */
if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
- int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
- SOF_BT_OFFLOAD_SSP_SHIFT;
-
- name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
- cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port);
-
- ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name,
- 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name,
- snd_soc_dummy_dlc.dai_name, NULL, NULL);
+ ret = create_bt_dailinks(card, &dai_links, &be_id);
if (ret)
- return ret;
+ goto err_end;
}
- card->dai_link = dai_links;
- card->num_links = num_links;
+ WARN_ON(dai_links != card->dai_link + card->num_links);
- card->codec_conf = codec_conf;
- card->num_configs = codec_conf_num;
+err_end:
+ kfree(sof_ends);
+err_dai:
+ kfree(sof_dais);
- return 0;
+ return ret;
}
static int sof_sdw_card_late_probe(struct snd_soc_card *card)
diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h
index b1d57034361c..8468487a6bd6 100644
--- a/sound/soc/intel/boards/sof_sdw_common.h
+++ b/sound/soc/intel/boards/sof_sdw_common.h
@@ -50,7 +50,10 @@ enum {
#define SOF_SDW_PCH_DMIC BIT(6)
#define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 7)
#define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0))
+/* Deprecated and no longer supported by the code */
#define SOF_SDW_NO_AGGREGATION BIT(14)
+/* If a CODEC has an optional speaker output, this quirk will enable it */
+#define SOF_CODEC_SPKR BIT(15)
/* BT audio offload: reserve 3 bits for future */
#define SOF_BT_OFFLOAD_SSP_SHIFT 15
@@ -63,7 +66,7 @@ enum {
#define SOF_SDW_DAI_TYPE_AMP 1
#define SOF_SDW_DAI_TYPE_MIC 2
-#define SOF_SDW_MAX_DAI_NUM 3
+#define SOF_SDW_MAX_DAI_NUM 8
struct sof_sdw_codec_info;
@@ -73,13 +76,13 @@ struct sof_sdw_dai_info {
const int dai_type;
const int dailink[2]; /* dailink id for each direction */
int (*init)(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
int (*rtd_init)(struct snd_soc_pcm_runtime *rtd);
bool rtd_init_done; /* Indicate that the rtd_init callback is done */
+ unsigned long quirk;
};
struct sof_sdw_codec_info {
@@ -103,10 +106,16 @@ struct mc_private {
struct device *amp_dev1, *amp_dev2;
/* To store SDW Pin index for each SoundWire link */
unsigned int sdw_pin_index[SDW_MAX_LINKS];
+ bool append_dai_type;
+ bool ignore_pch_dmic;
};
extern unsigned long sof_sdw_quirk;
+struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd,
+ const char * const dai_name[],
+ int num_dais);
+
int sdw_startup(struct snd_pcm_substream *substream);
int sdw_prepare(struct snd_pcm_substream *substream);
int sdw_trigger(struct snd_pcm_substream *substream, int cmd);
@@ -125,7 +134,6 @@ int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd);
/* RT711 support */
int sof_sdw_rt711_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
@@ -133,7 +141,6 @@ int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_l
/* RT711-SDCA support */
int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
@@ -144,34 +151,25 @@ extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops;
/* generic amp support */
int sof_sdw_rt_amp_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
-/* RT722-SDCA support */
-int sof_sdw_rt722_spk_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-int sof_sdw_rt722_sdca_dmic_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-
/* MAXIM codec support */
int sof_sdw_maxim_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
+/* CS42L43 support */
+int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_links,
+ struct sof_sdw_codec_info *info,
+ bool playback);
+
/* CS AMP support */
int sof_sdw_cs_amp_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
@@ -180,16 +178,16 @@ int sof_sdw_cs_amp_init(struct snd_soc_card *card,
int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd);
int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd);
int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd);
int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd);
int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd);
int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd);
int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd);
int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd);
-int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd);
int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd);
-int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd);
-int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd);
int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd);
int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd);
diff --git a/sound/soc/intel/boards/sof_sdw_cs42l42.c b/sound/soc/intel/boards/sof_sdw_cs42l42.c
index 0dc297f7de01..b999f4e7901a 100644
--- a/sound/soc/intel/boards/sof_sdw_cs42l42.c
+++ b/sound/soc/intel/boards/sof_sdw_cs42l42.c
@@ -15,7 +15,6 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
-#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
static const struct snd_soc_dapm_widget cs42l42_widgets[] = {
diff --git a/sound/soc/intel/boards/sof_sdw_cs42l43.c b/sound/soc/intel/boards/sof_sdw_cs42l43.c
index a9b6edac2ecd..5361249f0f53 100644
--- a/sound/soc/intel/boards/sof_sdw_cs42l43.c
+++ b/sound/soc/intel/boards/sof_sdw_cs42l43.c
@@ -30,6 +30,17 @@ static const struct snd_soc_dapm_route cs42l43_hs_map[] = {
{ "cs42l43 ADC1_IN1_N", NULL, "Headset Mic" },
};
+static const struct snd_soc_dapm_widget cs42l43_spk_widgets[] = {
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+static const struct snd_soc_dapm_route cs42l43_spk_map[] = {
+ { "Speaker", NULL, "cs42l43 AMP1_OUT_P", },
+ { "Speaker", NULL, "cs42l43 AMP1_OUT_N", },
+ { "Speaker", NULL, "cs42l43 AMP2_OUT_P", },
+ { "Speaker", NULL, "cs42l43 AMP2_OUT_N", },
+};
+
static const struct snd_soc_dapm_widget cs42l43_dmic_widgets[] = {
SND_SOC_DAPM_MIC("DMIC", NULL),
};
@@ -108,6 +119,45 @@ int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
+int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ int ret;
+
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:cs42l43-spk",
+ card->components);
+ if (!card->components)
+ return -ENOMEM;
+
+ ret = snd_soc_dapm_new_controls(&card->dapm, cs42l43_spk_widgets,
+ ARRAY_SIZE(cs42l43_spk_widgets));
+ if (ret) {
+ dev_err(card->dev, "cs42l43 speaker widgets addition failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dapm_add_routes(&card->dapm, cs42l43_spk_map,
+ ARRAY_SIZE(cs42l43_spk_map));
+ if (ret)
+ dev_err(card->dev, "cs42l43 speaker map addition failed: %d\n", ret);
+
+ return ret;
+}
+
+int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_links,
+ struct sof_sdw_codec_info *info,
+ bool playback)
+{
+ /* Do init on playback link only. */
+ if (!playback)
+ return 0;
+
+ info->amp_num++;
+
+ return 0;
+}
+
int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
diff --git a/sound/soc/intel/boards/sof_sdw_cs_amp.c b/sound/soc/intel/boards/sof_sdw_cs_amp.c
index 56cf75bc6cc4..e29a586ce7c0 100644
--- a/sound/soc/intel/boards/sof_sdw_cs_amp.c
+++ b/sound/soc/intel/boards/sof_sdw_cs_amp.c
@@ -57,7 +57,6 @@ int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd)
}
int sof_sdw_cs_amp_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_sdw_maxim.c b/sound/soc/intel/boards/sof_sdw_maxim.c
index 034730432671..432e5112415a 100644
--- a/sound/soc/intel/boards/sof_sdw_maxim.c
+++ b/sound/soc/intel/boards/sof_sdw_maxim.c
@@ -139,7 +139,6 @@ static int mx8373_sdw_late_probe(struct snd_soc_card *card)
}
int sof_sdw_maxim_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c
index 6b008a5a343b..f812aea64322 100644
--- a/sound/soc/intel/boards/sof_sdw_rt5682.c
+++ b/sound/soc/intel/boards/sof_sdw_rt5682.c
@@ -15,7 +15,6 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
-#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
static const struct snd_soc_dapm_widget rt5682_widgets[] = {
diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c
index 88e785a54b16..a2648c900e74 100644
--- a/sound/soc/intel/boards/sof_sdw_rt700.c
+++ b/sound/soc/intel/boards/sof_sdw_rt700.c
@@ -13,7 +13,6 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
-#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
static const struct snd_soc_dapm_widget rt700_widgets[] = {
diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c
index cdd1587b246c..7e54fc5cbe09 100644
--- a/sound/soc/intel/boards/sof_sdw_rt711.c
+++ b/sound/soc/intel/boards/sof_sdw_rt711.c
@@ -15,7 +15,6 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
-#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
/*
@@ -159,7 +158,6 @@ int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_l
}
int sof_sdw_rt711_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c
index ebb4b58c198b..0c4cd4cdbd45 100644
--- a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c
+++ b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c
@@ -13,7 +13,6 @@
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
-#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
static const struct snd_soc_dapm_widget rt712_spk_widgets[] = {
@@ -67,27 +66,3 @@ int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-static const char * const dmics[] = {
- "rt712-sdca-dmic"
-};
-
-int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_card *card = rtd->card;
- struct snd_soc_dai *codec_dai;
- struct snd_soc_component *component;
-
- codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics));
- if (!codec_dai)
- return -EINVAL;
-
- component = codec_dai->component;
- card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "%s mic:%s",
- card->components, component->name_prefix);
- if (!card->components)
- return -ENOMEM;
-
- return 0;
-}
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c
deleted file mode 100644
index b5a886cd595d..000000000000
--- a/sound/soc/intel/boards/sof_sdw_rt715.c
+++ /dev/null
@@ -1,26 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-// Copyright (c) 2020 Intel Corporation
-
-/*
- * sof_sdw_rt715 - Helpers to handle RT715 from generic machine driver
- */
-
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <sound/soc.h>
-#include <sound/soc-acpi.h>
-#include "sof_sdw_common.h"
-
-int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_card *card = rtd->card;
-
- card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "%s mic:rt715",
- card->components);
- if (!card->components)
- return -ENOMEM;
-
- return 0;
-}
-
diff --git a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
deleted file mode 100644
index 4b37a8a6dd2e..000000000000
--- a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
+++ /dev/null
@@ -1,26 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-// Copyright (c) 2020 Intel Corporation
-
-/*
- * sof_sdw_rt715_sdca - Helpers to handle RT715-SDCA from generic machine driver
- */
-
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <sound/soc.h>
-#include <sound/soc-acpi.h>
-#include "sof_sdw_common.h"
-
-int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_card *card = rtd->card;
-
- card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "%s mic:rt715-sdca",
- card->components);
- if (!card->components)
- return -ENOMEM;
-
- return 0;
-}
-
diff --git a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c
index fe3a2bff95bc..e5c2a36e400b 100644
--- a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c
+++ b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c
@@ -27,7 +27,7 @@ static const struct snd_kcontrol_new rt722_spk_controls[] = {
SOC_DAPM_PIN_SWITCH("Speaker"),
};
-static int rt722_spk_init(struct snd_soc_pcm_runtime *rtd)
+int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
int ret;
@@ -59,39 +59,3 @@ static int rt722_spk_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-int sof_sdw_rt722_spk_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- dai_links->init = rt722_spk_init;
-
- return 0;
-}
-
-static int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_card *card = rtd->card;
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
- struct snd_soc_component *component = codec_dai->component;
-
- card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "%s mic:%s",
- card->components, component->name_prefix);
- if (!card->components)
- return -ENOMEM;
-
- return 0;
-}
-
-int sof_sdw_rt722_sdca_dmic_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- dai_links->init = rt722_sdca_dmic_rtd_init;
-
- return 0;
-}
diff --git a/sound/soc/intel/boards/sof_sdw_rt_amp.c b/sound/soc/intel/boards/sof_sdw_rt_amp.c
index 202edab95000..1b415708500e 100644
--- a/sound/soc/intel/boards/sof_sdw_rt_amp.c
+++ b/sound/soc/intel/boards/sof_sdw_rt_amp.c
@@ -281,7 +281,6 @@ int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_
}
int sof_sdw_rt_amp_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_sdw_rt_dmic.c b/sound/soc/intel/boards/sof_sdw_rt_dmic.c
new file mode 100644
index 000000000000..2f7ed9b31e79
--- /dev/null
+++ b/sound/soc/intel/boards/sof_sdw_rt_dmic.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2024 Intel Corporation
+
+/*
+ * sof_sdw_rt_dmic - Helpers to handle Realtek SDW DMIC from generic machine driver
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include "sof_board_helpers.h"
+#include "sof_sdw_common.h"
+
+static const char * const dmics[] = {
+ "rt715",
+ "rt715-sdca",
+ "rt712-sdca-dmic",
+ "rt722-sdca",
+};
+
+int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_component *component;
+ struct snd_soc_dai *codec_dai;
+ char *mic_name;
+
+ codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics));
+ if (!codec_dai)
+ return -EINVAL;
+
+ component = codec_dai->component;
+
+ /*
+ * rt715-sdca (aka rt714) is a special case that uses different name in card->components
+ * and component->name_prefix.
+ */
+ if (!strcmp(component->name_prefix, "rt714"))
+ mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "rt715-sdca");
+ else
+ mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s", component->name_prefix);
+
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s mic:%s", card->components,
+ mic_name);
+ if (!card->components)
+ return -ENOMEM;
+
+ dev_dbg(card->dev, "card->components: %s\n", card->components);
+
+ return 0;
+}
+MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c
index 5253d8332780..85c09513bc35 100644
--- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c
+++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c
@@ -15,7 +15,6 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
-#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
/*
@@ -86,7 +85,7 @@ static struct snd_soc_jack_pin rt_sdca_jack_pins[] = {
};
static const char * const jack_codecs[] = {
- "rt711", "rt712", "rt713"
+ "rt711", "rt712", "rt713", "rt722"
};
int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd)
@@ -192,7 +191,6 @@ int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link
}
int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_ssp_common.c b/sound/soc/intel/boards/sof_ssp_common.c
deleted file mode 100644
index 96072790e9c0..000000000000
--- a/sound/soc/intel/boards/sof_ssp_common.c
+++ /dev/null
@@ -1,122 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-//
-// Copyright(c) 2023 Intel Corporation. All rights reserved.
-
-#include <linux/device.h>
-#include <sound/soc-acpi.h>
-#include "sof_ssp_common.h"
-
-/*
- * Codec probe function
- */
-#define CODEC_MAP_ENTRY(n, h, t) \
- { \
- .name = n, \
- .acpi_hid = h, \
- .codec_type = t, \
- }
-
-struct codec_map {
- const char *name;
- const char *acpi_hid;
- enum sof_ssp_codec codec_type;
-};
-
-static const struct codec_map codecs[] = {
- /* Cirrus Logic */
- CODEC_MAP_ENTRY("CS42L42", CS42L42_ACPI_HID, CODEC_CS42L42),
-
- /* Dialog */
- CODEC_MAP_ENTRY("DA7219", DA7219_ACPI_HID, CODEC_DA7219),
-
- /* Everest */
- CODEC_MAP_ENTRY("ES8316", ES8316_ACPI_HID, CODEC_ES8316),
- CODEC_MAP_ENTRY("ES8326", ES8326_ACPI_HID, CODEC_ES8326),
- CODEC_MAP_ENTRY("ES8336", ES8336_ACPI_HID, CODEC_ES8336),
-
- /* Nuvoton */
- CODEC_MAP_ENTRY("NAU8825", NAU8825_ACPI_HID, CODEC_NAU8825),
-
- /* Realtek */
- CODEC_MAP_ENTRY("RT5650", RT5650_ACPI_HID, CODEC_RT5650),
- CODEC_MAP_ENTRY("RT5682", RT5682_ACPI_HID, CODEC_RT5682),
- CODEC_MAP_ENTRY("RT5682S", RT5682S_ACPI_HID, CODEC_RT5682S),
-};
-
-static const struct codec_map amps[] = {
- /* Cirrus Logic */
- CODEC_MAP_ENTRY("CS35L41", CS35L41_ACPI_HID, CODEC_CS35L41),
-
- /* Maxim */
- CODEC_MAP_ENTRY("MAX98357A", MAX_98357A_ACPI_HID, CODEC_MAX98357A),
- CODEC_MAP_ENTRY("MAX98360A", MAX_98360A_ACPI_HID, CODEC_MAX98360A),
- CODEC_MAP_ENTRY("MAX98373", MAX_98373_ACPI_HID, CODEC_MAX98373),
- CODEC_MAP_ENTRY("MAX98390", MAX_98390_ACPI_HID, CODEC_MAX98390),
-
- /* Nuvoton */
- CODEC_MAP_ENTRY("NAU8318", NAU8318_ACPI_HID, CODEC_NAU8318),
-
- /* Realtek */
- CODEC_MAP_ENTRY("RT1011", RT1011_ACPI_HID, CODEC_RT1011),
- CODEC_MAP_ENTRY("RT1015", RT1015_ACPI_HID, CODEC_RT1015),
- CODEC_MAP_ENTRY("RT1015P", RT1015P_ACPI_HID, CODEC_RT1015P),
- CODEC_MAP_ENTRY("RT1019P", RT1019P_ACPI_HID, CODEC_RT1019P),
- CODEC_MAP_ENTRY("RT1308", RT1308_ACPI_HID, CODEC_RT1308),
-};
-
-enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(codecs); i++) {
- if (!acpi_dev_present(codecs[i].acpi_hid, NULL, -1))
- continue;
-
- dev_dbg(dev, "codec %s found\n", codecs[i].name);
- return codecs[i].codec_type;
- }
-
- return CODEC_NONE;
-}
-EXPORT_SYMBOL_NS(sof_ssp_detect_codec_type, SND_SOC_INTEL_SOF_SSP_COMMON);
-
-enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(amps); i++) {
- if (!acpi_dev_present(amps[i].acpi_hid, NULL, -1))
- continue;
-
- dev_dbg(dev, "amp %s found\n", amps[i].name);
- return amps[i].codec_type;
- }
-
- return CODEC_NONE;
-}
-EXPORT_SYMBOL_NS(sof_ssp_detect_amp_type, SND_SOC_INTEL_SOF_SSP_COMMON);
-
-const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(codecs); i++) {
- if (codecs[i].codec_type != codec_type)
- continue;
-
- return codecs[i].name;
- }
- for (i = 0; i < ARRAY_SIZE(amps); i++) {
- if (amps[i].codec_type != codec_type)
- continue;
-
- return amps[i].name;
- }
-
- return NULL;
-}
-EXPORT_SYMBOL_NS(sof_ssp_get_codec_name, SND_SOC_INTEL_SOF_SSP_COMMON);
-
-MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers");
-MODULE_AUTHOR("Brent Lu <[email protected]>");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile
index f7370e5b4e9e..a86457674726 100644
--- a/sound/soc/intel/common/Makefile
+++ b/sound/soc/intel/common/Makefile
@@ -15,5 +15,7 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m
soc-acpi-intel-hda-match.o \
soc-acpi-intel-sdw-mockup-match.o
+snd-soc-acpi-intel-match-objs += soc-acpi-intel-ssp-common.o
+
obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o
diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
index 7ce8aade07d7..1ea2d9c582ee 100644
--- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
@@ -7,6 +7,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
+#include <sound/soc-acpi-intel-ssp-common.h>
static const struct snd_soc_acpi_codecs essx_83x6 = {
.num_codecs = 3,
@@ -447,11 +448,6 @@ static const struct snd_soc_acpi_link_adr adl_chromebook_base[] = {
{}
};
-static const struct snd_soc_acpi_codecs adl_max98373_amp = {
- .num_codecs = 1,
- .codecs = {"MX98373"}
-};
-
static const struct snd_soc_acpi_codecs adl_max98357a_amp = {
.num_codecs = 1,
.codecs = {"MX98357A"}
@@ -464,12 +460,7 @@ static const struct snd_soc_acpi_codecs adl_max98360a_amp = {
static const struct snd_soc_acpi_codecs adl_rt5682_rt5682s_hp = {
.num_codecs = 2,
- .codecs = {"10EC5682", "RTL5682"},
-};
-
-static const struct snd_soc_acpi_codecs adl_rt1015p_amp = {
- .num_codecs = 1,
- .codecs = {"RTL1015"}
+ .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID},
};
static const struct snd_soc_acpi_codecs adl_rt1019p_amp = {
@@ -477,49 +468,20 @@ static const struct snd_soc_acpi_codecs adl_rt1019p_amp = {
.codecs = {"RTL1019"}
};
-static const struct snd_soc_acpi_codecs adl_max98390_amp = {
- .num_codecs = 1,
- .codecs = {"MX98390"}
-};
-
static const struct snd_soc_acpi_codecs adl_lt6911_hdmi = {
.num_codecs = 1,
.codecs = {"INTC10B0"}
};
-static const struct snd_soc_acpi_codecs adl_nau8318_amp = {
- .num_codecs = 1,
- .codecs = {"NVTN2012"}
-};
-
-static struct snd_soc_acpi_codecs adl_rt5650_amp = {
- .num_codecs = 1,
- .codecs = {"10EC5650"}
-};
-
struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
{
.comp_ids = &adl_rt5682_rt5682s_hp,
- .drv_name = "adl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &adl_max98373_amp,
- .sof_tplg_filename = "sof-adl-max98373-rt5682.tplg",
- },
- {
- .comp_ids = &adl_rt5682_rt5682s_hp,
.drv_name = "adl_mx98357_rt5682",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &adl_max98357a_amp,
.sof_tplg_filename = "sof-adl-max98357a-rt5682.tplg",
},
{
- .comp_ids = &adl_rt5682_rt5682s_hp,
- .drv_name = "adl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &adl_max98360a_amp,
- .sof_tplg_filename = "sof-adl-max98360a-rt5682.tplg",
- },
- {
.id = "10508825",
.drv_name = "adl_rt1019p_8825",
.machine_quirk = snd_soc_acpi_codec_list,
@@ -527,53 +489,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
.sof_tplg_filename = "sof-adl-rt1019-nau8825.tplg",
},
{
- .id = "10508825",
- .drv_name = "adl_nau8825_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &adl_max98373_amp,
- .sof_tplg_filename = "sof-adl-max98373-nau8825.tplg",
- },
- {
- .id = "10508825",
- .drv_name = "adl_nau8825_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &adl_max98360a_amp,
- .sof_tplg_filename = "sof-adl-max98360a-nau8825.tplg",
- },
- {
- .comp_ids = &adl_rt5682_rt5682s_hp,
- .drv_name = "adl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &adl_rt1019p_amp,
- .sof_tplg_filename = "sof-adl-rt1019-rt5682.tplg",
- },
- {
- .id = "10508825",
- .drv_name = "adl_nau8825_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &adl_rt1015p_amp,
- .sof_tplg_filename = "sof-adl-rt1015-nau8825.tplg",
- },
- {
- .id = "10508825",
- .drv_name = "adl_nau8825_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &adl_nau8318_amp,
- .sof_tplg_filename = "sof-adl-nau8318-nau8825.tplg",
- },
- {
- .id = "10508825",
- .drv_name = "adl_nau8825_def",
- .sof_tplg_filename = "sof-adl-nau8825.tplg",
- },
- {
- .comp_ids = &adl_rt5682_rt5682s_hp,
- .drv_name = "adl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &adl_max98390_amp,
- .sof_tplg_filename = "sof-adl-max98390-rt5682.tplg",
- },
- {
.comp_ids = &adl_rt5682_rt5682s_hp,
.drv_name = "adl_rt5682_c1_h02",
.machine_quirk = snd_soc_acpi_codec_list,
@@ -581,18 +496,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
.sof_tplg_filename = "sof-adl-rt5682-ssp1-hdmi-ssp02.tplg",
},
{
- .comp_ids = &adl_rt5682_rt5682s_hp,
- .drv_name = "adl_rt5682_def",
- .sof_tplg_filename = "sof-adl-rt5682.tplg",
- },
- {
- .id = "10134242",
- .drv_name = "adl_mx98360a_cs4242",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &adl_max98360a_amp,
- .sof_tplg_filename = "sof-adl-max98360a-cs42l42.tplg",
- },
- {
.comp_ids = &essx_83x6,
.drv_name = "adl_es83x6_c1_h02",
.machine_quirk = snd_soc_acpi_codec_list,
@@ -608,19 +511,43 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
},
{
- .id = "10EC5650",
- .drv_name = "adl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &adl_rt5650_amp,
- .sof_tplg_filename = "sof-adl-rt5650.tplg",
- },
- {
.id = "DLGS7219",
.drv_name = "adl_da7219_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &adl_max98360a_amp,
.sof_tplg_filename = "sof-adl-max98360a-da7219.tplg",
},
+ /* place boards for each headphone codec: sof driver will complete the
+ * tplg name and machine driver will detect the amp type
+ */
+ {
+ .id = CS42L42_ACPI_HID,
+ .drv_name = "adl_cs42l42_def",
+ .sof_tplg_filename = "sof-adl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ {
+ .id = NAU8825_ACPI_HID,
+ .drv_name = "adl_nau8825_def",
+ .sof_tplg_filename = "sof-adl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ {
+ .id = RT5650_ACPI_HID,
+ .drv_name = "adl_rt5682_def",
+ .sof_tplg_filename = "sof-adl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ {
+ .comp_ids = &adl_rt5682_rt5682s_hp,
+ .drv_name = "adl_rt5682_def",
+ .sof_tplg_filename = "sof-adl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
/* place amp-only boards in the end of table */
{
.id = "CSC3541",
diff --git a/sound/soc/intel/common/soc-acpi-intel-arl-match.c b/sound/soc/intel/common/soc-acpi-intel-arl-match.c
index e52797aae6e6..79d26e0f2c28 100644
--- a/sound/soc/intel/common/soc-acpi-intel-arl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-arl-match.c
@@ -24,6 +24,15 @@ static const struct snd_soc_acpi_adr_device rt711_0_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = {
+ {
+ .adr = 0x000030025D071101ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt711"
+ }
+};
+
static const struct snd_soc_acpi_link_adr arl_rvp[] = {
{
.mask = BIT(0),
@@ -33,6 +42,15 @@ static const struct snd_soc_acpi_link_adr arl_rvp[] = {
{}
};
+static const struct snd_soc_acpi_link_adr arl_sdca_rvp[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt711_sdca_0_adr),
+ .adr_d = rt711_sdca_0_adr,
+ },
+ {}
+};
+
struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[] = {
{},
};
@@ -46,6 +64,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-arl-rt711.tplg",
},
+ {
+ .link_mask = 0x1, /* link0 required */
+ .links = arl_sdca_rvp,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-arl-rt711-l0.tplg",
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_arl_sdw_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index e9a5da079089..75935b454e5d 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -8,6 +8,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
+#include <sound/soc-acpi-intel-ssp-common.h>
#include "soc-acpi-intel-sdw-mockup-match.h"
static const struct snd_soc_acpi_codecs mtl_max98357a_amp = {
@@ -20,14 +21,9 @@ static const struct snd_soc_acpi_codecs mtl_max98360a_amp = {
.codecs = {"MX98360A"}
};
-static const struct snd_soc_acpi_codecs mtl_rt1019p_amp = {
- .num_codecs = 1,
- .codecs = {"RTL1019"}
-};
-
static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = {
.num_codecs = 2,
- .codecs = {"10EC5682", "RTL5682"},
+ .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID},
};
static const struct snd_soc_acpi_codecs mtl_essx_83x6 = {
@@ -40,11 +36,6 @@ static const struct snd_soc_acpi_codecs mtl_lt6911_hdmi = {
.codecs = {"INTC10B0"}
};
-static const struct snd_soc_acpi_codecs mtl_rt5650_amp = {
- .num_codecs = 1,
- .codecs = {"10EC5650"}
-};
-
struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = {
{
.comp_ids = &mtl_rt5682_rt5682s_hp,
@@ -61,13 +52,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = {
.sof_tplg_filename = "sof-mtl-max98360a-rt5682.tplg",
},
{
- .comp_ids = &mtl_rt5682_rt5682s_hp,
- .drv_name = "mtl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &mtl_rt1019p_amp,
- .sof_tplg_filename = "sof-mtl-rt1019-rt5682.tplg",
- },
- {
.comp_ids = &mtl_essx_83x6,
.drv_name = "mtl_es83x6_c1_h02",
.machine_quirk = snd_soc_acpi_codec_list,
@@ -82,12 +66,36 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = {
SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
},
+ /* place boards for each headphone codec: sof driver will complete the
+ * tplg name and machine driver will detect the amp type
+ */
{
- .id = "10EC5650",
+ .id = CS42L42_ACPI_HID,
+ .drv_name = "mtl_cs42l42_def",
+ .sof_tplg_filename = "sof-mtl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ {
+ .id = NAU8825_ACPI_HID,
+ .drv_name = "mtl_nau8825_def",
+ .sof_tplg_filename = "sof-mtl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ {
+ .id = RT5650_ACPI_HID,
.drv_name = "mtl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &mtl_rt5650_amp,
- .sof_tplg_filename = "sof-mtl-rt5650.tplg",
+ .sof_tplg_filename = "sof-mtl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ {
+ .comp_ids = &mtl_rt5682_rt5682s_hp,
+ .drv_name = "mtl_rt5682_def",
+ .sof_tplg_filename = "sof-mtl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
},
/* place amp-only boards in the end of table */
{
@@ -338,11 +346,38 @@ static const struct snd_soc_acpi_link_adr mtl_712_only[] = {
{}
};
+static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
+ { /* Jack Playback Endpoint */
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* DMIC Capture Endpoint */
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Jack Capture Endpoint */
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Speaker Playback Endpoint */
+ .num = 3,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = {
{
.adr = 0x00003001FA424301ull,
- .num_endpoints = 1,
- .endpoints = &single_endpoint,
+ .num_endpoints = ARRAY_SIZE(cs42l43_endpoints),
+ .endpoints = cs42l43_endpoints,
.name_prefix = "cs42l43"
}
};
@@ -352,13 +387,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_1_adr[] = {
.adr = 0x00013701FA355601ull,
.num_endpoints = 1,
.endpoints = &spk_r_endpoint,
- .name_prefix = "AMP8"
+ .name_prefix = "AMP3"
},
{
.adr = 0x00013601FA355601ull,
.num_endpoints = 1,
.endpoints = &spk_3_endpoint,
- .name_prefix = "AMP7"
+ .name_prefix = "AMP4"
}
};
diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c
index 77c917897c8d..34588db6138a 100644
--- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c
@@ -7,6 +7,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
+#include <sound/soc-acpi-intel-ssp-common.h>
static const struct snd_soc_acpi_endpoint single_endpoint = {
.num = 0,
@@ -347,7 +348,7 @@ static const struct snd_soc_acpi_link_adr rplp_crb[] = {
static const struct snd_soc_acpi_codecs rpl_rt5682_hp = {
.num_codecs = 2,
- .codecs = {"10EC5682", "RTL5682"},
+ .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID},
};
static const struct snd_soc_acpi_codecs rpl_essx_83x6 = {
@@ -365,26 +366,11 @@ static const struct snd_soc_acpi_codecs rpl_max98360a_amp = {
.codecs = {"MX98360A"},
};
-static const struct snd_soc_acpi_codecs rpl_max98373_amp = {
- .num_codecs = 1,
- .codecs = {"MX98373"}
-};
-
static const struct snd_soc_acpi_codecs rpl_lt6911_hdmi = {
.num_codecs = 1,
.codecs = {"INTC10B0"}
};
-static const struct snd_soc_acpi_codecs rpl_nau8318_amp = {
- .num_codecs = 1,
- .codecs = {"NVTN2012"}
-};
-
-static const struct snd_soc_acpi_codecs rpl_rt1019p_amp = {
- .num_codecs = 1,
- .codecs = {"RTL1019"}
-};
-
struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = {
{
.comp_ids = &rpl_rt5682_hp,
@@ -395,41 +381,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = {
},
{
.comp_ids = &rpl_rt5682_hp,
- .drv_name = "rpl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &rpl_max98360a_amp,
- .sof_tplg_filename = "sof-rpl-max98360a-rt5682.tplg",
- },
- {
- .id = "10508825",
- .drv_name = "rpl_nau8825_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &rpl_max98373_amp,
- .sof_tplg_filename = "sof-rpl-max98373-nau8825.tplg",
- },
- {
- .id = "10508825",
- .drv_name = "rpl_nau8825_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &rpl_max98360a_amp,
- .sof_tplg_filename = "sof-rpl-max98360a-nau8825.tplg",
- },
- {
- .id = "10508825",
- .drv_name = "rpl_nau8825_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &rpl_nau8318_amp,
- .sof_tplg_filename = "sof-rpl-nau8318-nau8825.tplg",
- },
- {
- .comp_ids = &rpl_rt5682_hp,
- .drv_name = "rpl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &rpl_rt1019p_amp,
- .sof_tplg_filename = "sof-rpl-rt1019-rt5682.tplg",
- },
- {
- .comp_ids = &rpl_rt5682_hp,
.drv_name = "rpl_rt5682_c1_h02",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &rpl_lt6911_hdmi,
@@ -450,6 +401,38 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = {
SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
},
+ /* place boards for each headphone codec: sof driver will complete the
+ * tplg name and machine driver will detect the amp type
+ */
+ {
+ .id = CS42L42_ACPI_HID,
+ .drv_name = "rpl_cs42l42_def",
+ .sof_tplg_filename = "sof-rpl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ {
+ .id = NAU8825_ACPI_HID,
+ .drv_name = "rpl_nau8825_def",
+ .sof_tplg_filename = "sof-rpl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ {
+ .id = RT5650_ACPI_HID,
+ .drv_name = "rpl_rt5682_def",
+ .sof_tplg_filename = "sof-rpl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ {
+ .comp_ids = &rpl_rt5682_hp,
+ .drv_name = "rpl_rt5682_def",
+ .sof_tplg_filename = "sof-rpl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ /* place amp-only boards in the end of table */
{
.id = "INTC10B0",
.drv_name = "rpl_lt6911_hdmi_ssp",
@@ -462,11 +445,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = {
.quirk_data = &rpl_max98360a_amp,
.sof_tplg_filename = "sof-rpl-max98360a-da7219.tplg",
},
- {
- .id = "10EC5650",
- .drv_name = "rpl_rt5682_def",
- .sof_tplg_filename = "sof-rpl-rt5650.tplg",
- },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_rpl_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c
new file mode 100644
index 000000000000..a887f019afe2
--- /dev/null
+++ b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright(c) 2023 Intel Corporation. All rights reserved.
+
+#include <linux/device.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-acpi-intel-ssp-common.h>
+
+/*
+ * Codec probe function
+ */
+#define CODEC_MAP_ENTRY(n, s, h, t) \
+ { \
+ .name = n, \
+ .tplg_suffix = s, \
+ .acpi_hid = h, \
+ .codec_type = t, \
+ }
+
+struct codec_map {
+ const char *name;
+ const char *tplg_suffix;
+ const char *acpi_hid;
+ enum snd_soc_acpi_intel_codec codec_type;
+};
+
+static const struct codec_map codecs[] = {
+ /* Cirrus Logic */
+ CODEC_MAP_ENTRY("CS42L42", "cs42l42", CS42L42_ACPI_HID, CODEC_CS42L42),
+
+ /* Dialog */
+ CODEC_MAP_ENTRY("DA7219", "da7219", DA7219_ACPI_HID, CODEC_DA7219),
+
+ /* Everest */
+ CODEC_MAP_ENTRY("ES8316", "es8336", ES8316_ACPI_HID, CODEC_ES8316),
+ CODEC_MAP_ENTRY("ES8326", "es8336", ES8326_ACPI_HID, CODEC_ES8326),
+ CODEC_MAP_ENTRY("ES8336", "es8336", ES8336_ACPI_HID, CODEC_ES8336),
+
+ /* Nuvoton */
+ CODEC_MAP_ENTRY("NAU8825", "nau8825", NAU8825_ACPI_HID, CODEC_NAU8825),
+
+ /* Realtek */
+ CODEC_MAP_ENTRY("RT5650", "rt5650", RT5650_ACPI_HID, CODEC_RT5650),
+ CODEC_MAP_ENTRY("RT5682", "rt5682", RT5682_ACPI_HID, CODEC_RT5682),
+ CODEC_MAP_ENTRY("RT5682S", "rt5682", RT5682S_ACPI_HID, CODEC_RT5682S),
+};
+
+static const struct codec_map amps[] = {
+ /* Cirrus Logic */
+ CODEC_MAP_ENTRY("CS35L41", "cs35l41", CS35L41_ACPI_HID, CODEC_CS35L41),
+
+ /* Maxim */
+ CODEC_MAP_ENTRY("MAX98357A", "max98357a", MAX_98357A_ACPI_HID, CODEC_MAX98357A),
+ CODEC_MAP_ENTRY("MAX98360A", "max98360a", MAX_98360A_ACPI_HID, CODEC_MAX98360A),
+ CODEC_MAP_ENTRY("MAX98373", "max98373", MAX_98373_ACPI_HID, CODEC_MAX98373),
+ CODEC_MAP_ENTRY("MAX98390", "max98390", MAX_98390_ACPI_HID, CODEC_MAX98390),
+
+ /* Nuvoton */
+ CODEC_MAP_ENTRY("NAU8318", "nau8318", NAU8318_ACPI_HID, CODEC_NAU8318),
+
+ /* Realtek */
+ CODEC_MAP_ENTRY("RT1011", "rt1011", RT1011_ACPI_HID, CODEC_RT1011),
+ CODEC_MAP_ENTRY("RT1015", "rt1015", RT1015_ACPI_HID, CODEC_RT1015),
+ CODEC_MAP_ENTRY("RT1015P", "rt1015", RT1015P_ACPI_HID, CODEC_RT1015P),
+ CODEC_MAP_ENTRY("RT1019P", "rt1019", RT1019P_ACPI_HID, CODEC_RT1019P),
+ CODEC_MAP_ENTRY("RT1308", "rt1308", RT1308_ACPI_HID, CODEC_RT1308),
+};
+
+enum snd_soc_acpi_intel_codec
+snd_soc_acpi_intel_detect_codec_type(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(codecs); i++) {
+ if (!acpi_dev_present(codecs[i].acpi_hid, NULL, -1))
+ continue;
+
+ dev_dbg(dev, "codec %s found\n", codecs[i].name);
+ return codecs[i].codec_type;
+ }
+
+ return CODEC_NONE;
+}
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_codec_type, SND_SOC_ACPI_INTEL_MATCH);
+
+enum snd_soc_acpi_intel_codec
+snd_soc_acpi_intel_detect_amp_type(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(amps); i++) {
+ if (!acpi_dev_present(amps[i].acpi_hid, NULL, -1))
+ continue;
+
+ dev_dbg(dev, "amp %s found\n", amps[i].name);
+ return amps[i].codec_type;
+ }
+
+ return CODEC_NONE;
+}
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_amp_type, SND_SOC_ACPI_INTEL_MATCH);
+
+const char *
+snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(codecs); i++) {
+ if (codecs[i].codec_type != codec_type)
+ continue;
+
+ return codecs[i].name;
+ }
+ for (i = 0; i < ARRAY_SIZE(amps); i++) {
+ if (amps[i].codec_type != codec_type)
+ continue;
+
+ return amps[i].name;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, SND_SOC_ACPI_INTEL_MATCH);
+
+const char *
+snd_soc_acpi_intel_get_codec_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(codecs); i++) {
+ if (codecs[i].codec_type != codec_type)
+ continue;
+
+ return codecs[i].tplg_suffix;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_tplg_suffix, SND_SOC_ACPI_INTEL_MATCH);
+
+const char *
+snd_soc_acpi_intel_get_amp_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(amps); i++) {
+ if (amps[i].codec_type != codec_type)
+ continue;
+
+ return amps[i].tplg_suffix;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_amp_tplg_suffix, SND_SOC_ACPI_INTEL_MATCH);
+
+MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers");
+MODULE_AUTHOR("Brent Lu <[email protected]>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index 0fba0a60d9c7..161ba532d270 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -8,6 +8,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
+#include <sound/soc-acpi-intel-ssp-common.h>
#include "soc-acpi-intel-sdw-mockup-match.h"
static const struct snd_soc_acpi_codecs essx_83x6 = {
@@ -15,11 +16,6 @@ static const struct snd_soc_acpi_codecs essx_83x6 = {
.codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
};
-static const struct snd_soc_acpi_codecs tgl_codecs = {
- .num_codecs = 1,
- .codecs = {"MX98357A"}
-};
-
static const struct snd_soc_acpi_endpoint single_endpoint = {
.num = 0,
.aggregated = 0,
@@ -414,11 +410,38 @@ static const struct snd_soc_acpi_link_adr tgl_712_only[] = {
{}
};
+static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
+ { /* Jack Playback Endpoint */
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* DMIC Capture Endpoint */
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Jack Capture Endpoint */
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Speaker Playback Endpoint */
+ .num = 3,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
static const struct snd_soc_acpi_adr_device cs42l43_3_adr[] = {
{
.adr = 0x00033001FA424301ull,
- .num_endpoints = 1,
- .endpoints = &single_endpoint,
+ .num_endpoints = ARRAY_SIZE(cs42l43_endpoints),
+ .endpoints = cs42l43_endpoints,
.name_prefix = "cs42l43"
}
};
@@ -443,13 +466,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_1_adr[] = {
.adr = 0x00013701FA355601ull,
.num_endpoints = 1,
.endpoints = &spk_l_endpoint,
- .name_prefix = "AMP8"
+ .name_prefix = "AMP3"
},
{
.adr = 0x00013601FA355601ull,
.num_endpoints = 1,
.endpoints = &spk_2_endpoint,
- .name_prefix = "AMP7"
+ .name_prefix = "AMP4"
}
};
@@ -472,19 +495,9 @@ static const struct snd_soc_acpi_link_adr tgl_cs42l43_cs35l56[] = {
{}
};
-static const struct snd_soc_acpi_codecs tgl_max98373_amp = {
- .num_codecs = 1,
- .codecs = {"MX98373"}
-};
-
-static const struct snd_soc_acpi_codecs tgl_rt1011_amp = {
- .num_codecs = 1,
- .codecs = {"10EC1011"}
-};
-
static const struct snd_soc_acpi_codecs tgl_rt5682_rt5682s_hp = {
.num_codecs = 2,
- .codecs = {"10EC5682", "RTL5682"},
+ .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID},
};
static const struct snd_soc_acpi_codecs tgl_lt6911_hdmi = {
@@ -494,27 +507,6 @@ static const struct snd_soc_acpi_codecs tgl_lt6911_hdmi = {
struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = {
{
- .comp_ids = &tgl_rt5682_rt5682s_hp,
- .drv_name = "tgl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &tgl_codecs,
- .sof_tplg_filename = "sof-tgl-max98357a-rt5682.tplg",
- },
- {
- .comp_ids = &tgl_rt5682_rt5682s_hp,
- .drv_name = "tgl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &tgl_max98373_amp,
- .sof_tplg_filename = "sof-tgl-max98373-rt5682.tplg",
- },
- {
- .comp_ids = &tgl_rt5682_rt5682s_hp,
- .drv_name = "tgl_rt5682_def",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &tgl_rt1011_amp,
- .sof_tplg_filename = "sof-tgl-rt1011-rt5682.tplg",
- },
- {
.comp_ids = &essx_83x6,
.drv_name = "sof-essx8336",
.sof_tplg_filename = "sof-tgl-es8336", /* the tplg suffix is added at run time */
@@ -522,6 +514,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = {
SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
},
+ /* place boards for each headphone codec: sof driver will complete the
+ * tplg name and machine driver will detect the amp type
+ */
+ {
+ .comp_ids = &tgl_rt5682_rt5682s_hp,
+ .drv_name = "tgl_rt5682_def",
+ .sof_tplg_filename = "sof-tgl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
+ /* place amp-only boards in the end of table */
{
.id = "10EC1308",
.drv_name = "tgl_rt1308_hdmi_ssp",
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index dd2f806526c1..ef00792e1d49 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -182,6 +182,9 @@ static int kirkwood_dma_hw_params(struct snd_soc_component *component,
const struct mbus_dram_target_info *dram = mv_mbus_dram_info();
unsigned long addr = substream->runtime->dma_addr;
+ if (!dram)
+ return 0;
+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
kirkwood_dma_conf_mbus_windows(priv->io,
KIRKWOOD_PLAYBACK_WIN, addr, dram);
diff --git a/sound/soc/loongson/loongson_i2s_pci.c b/sound/soc/loongson/loongson_i2s_pci.c
index fa90361865c6..ec18b122cd79 100644
--- a/sound/soc/loongson/loongson_i2s_pci.c
+++ b/sound/soc/loongson/loongson_i2s_pci.c
@@ -160,7 +160,6 @@ static struct pci_driver loongson_i2s_driver = {
.id_table = loongson_i2s_ids,
.probe = loongson_i2s_pci_probe,
.driver = {
- .owner = THIS_MODULE,
.pm = pm_sleep_ptr(&loongson_i2s_pm),
},
};
diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c
index 329e6ab1b222..8d9a1e345a22 100644
--- a/sound/soc/sh/rcar/cmd.c
+++ b/sound/soc/sh/rcar/cmd.c
@@ -119,7 +119,7 @@ static void rsnd_cmd_debug_info(struct seq_file *m,
struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
+ rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU,
0x180 + rsnd_mod_id_raw(mod) * 0x20, 0x30);
}
#define DEBUG_INFO .debug_info = rsnd_cmd_debug_info
@@ -157,10 +157,6 @@ int rsnd_cmd_probe(struct rsnd_priv *priv)
struct rsnd_cmd *cmd;
int i, nr;
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
/* same number as DVC */
nr = priv->dvc_nr;
if (!nr)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 0b1aa23c1189..6bc7027ed4db 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1512,7 +1512,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
continue;
for_each_endpoint_of_node(ports, dai_np) {
__rsnd_dai_probe(priv, dai_np, dai_np, 0, dai_i);
- if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
+ if (!rsnd_is_gen1(priv) && !rsnd_is_gen2(priv)) {
rdai = rsnd_rdai_get(priv, dai_i);
rsnd_parse_connect_graph(priv, &rdai->playback, dai_np);
@@ -1531,7 +1531,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
for_each_child_of_node(node, dai_np) {
__rsnd_dai_probe(priv, dai_np, np, dai_i, dai_i);
- if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
+ if (!rsnd_is_gen1(priv) && !rsnd_is_gen2(priv)) {
rdai = rsnd_rdai_get(priv, dai_i);
rsnd_parse_connect_simple(priv, &rdai->playback, dai_np);
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c
index e39eb2ac7e95..a26ec7b780cd 100644
--- a/sound/soc/sh/rcar/ctu.c
+++ b/sound/soc/sh/rcar/ctu.c
@@ -284,7 +284,7 @@ static void rsnd_ctu_debug_info(struct seq_file *m,
struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
+ rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU,
0x500 + rsnd_mod_id_raw(mod) * 0x100, 0x100);
}
#define DEBUG_INFO .debug_info = rsnd_ctu_debug_info
@@ -323,10 +323,6 @@ int rsnd_ctu_probe(struct rsnd_priv *priv)
char name[CTU_NAME_SIZE];
int i, nr, ret;
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
node = rsnd_ctu_of_node(priv);
if (!node)
return 0; /* not used is not error */
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 1c494e521463..7b499eee5080 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -585,8 +585,8 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
{
struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct device *dev = rsnd_priv_to_dev(priv);
- phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI);
- phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU);
+ phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SSI);
+ phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SCU);
int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod) ||
!!(rsnd_io_to_mod_ssiu(io) == mod);
int use_src = !!rsnd_io_to_mod_src(io);
@@ -666,7 +666,7 @@ rsnd_gen4_dma_addr(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
int is_play, int is_from)
{
struct rsnd_priv *priv = rsnd_io_to_priv(io);
- phys_addr_t addr = rsnd_gen_get_phy_addr(priv, RSND_GEN4_SDMC);
+ phys_addr_t addr = rsnd_gen_get_phy_addr(priv, RSND_BASE_SDMC);
int id = rsnd_mod_id(mod);
int busif = rsnd_mod_id_sub(mod);
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index 16befcbc312c..da91dd301aab 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -294,7 +294,7 @@ static void rsnd_dvc_debug_info(struct seq_file *m,
struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
+ rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU,
0xe00 + rsnd_mod_id(mod) * 0x100, 0x60);
}
#define DEBUG_INFO .debug_info = rsnd_dvc_debug_info
@@ -331,10 +331,6 @@ int rsnd_dvc_probe(struct rsnd_priv *priv)
char name[RSND_DVC_NAME_SIZE];
int i, nr, ret;
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
node = rsnd_dvc_of_node(priv);
if (!node)
return 0; /* not used is not error */
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index 86bdecc24956..d1f20cde66be 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -178,8 +178,6 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
if (!res)
- res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id);
- if (!res)
return -ENODEV;
base = devm_ioremap_resource(dev, res);
@@ -216,69 +214,219 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
}
/*
+ * (A) : Gen4 is 0xa0c, but it is not used.
+ * see
+ * rsnd_ssiu_init()
+ */
+static const struct rsnd_regmap_field_conf conf_common_ssiu[] = {
+ RSND_GEN_S_REG(SSI_MODE0, 0x800),
+ RSND_GEN_S_REG(SSI_MODE1, 0x804),
+ RSND_GEN_S_REG(SSI_MODE2, 0x808), // (A)
+ RSND_GEN_S_REG(SSI_CONTROL, 0x810),
+ RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840),
+ RSND_GEN_S_REG(SSI_SYS_STATUS1, 0x844),
+ RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848),
+ RSND_GEN_S_REG(SSI_SYS_STATUS3, 0x84c),
+ RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880),
+ RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884),
+ RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888),
+ RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE1, 0x854),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE3, 0x85c),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE5, 0x894),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE7, 0x89c),
+ RSND_GEN_S_REG(HDMI0_SEL, 0x9e0),
+ RSND_GEN_S_REG(HDMI1_SEL, 0x9e4),
+ RSND_GEN_M_REG(SSI_BUSIF0_MODE, 0x0, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF0_ADINR, 0x4, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF0_DALIGN, 0x8, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF1_MODE, 0x20, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF1_ADINR, 0x24, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF1_DALIGN, 0x28, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF2_MODE, 0x40, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF2_ADINR, 0x44, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF2_DALIGN, 0x48, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF3_MODE, 0x60, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF3_ADINR, 0x64, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF3_DALIGN, 0x68, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF4_MODE, 0x500, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF4_ADINR, 0x504, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF4_DALIGN, 0x508, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF5_MODE, 0x520, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF5_ADINR, 0x524, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF5_DALIGN, 0x528, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF6_MODE, 0x540, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF6_ADINR, 0x544, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF6_DALIGN, 0x548, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF7_MODE, 0x560, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF7_ADINR, 0x564, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF7_DALIGN, 0x568, 0x80),
+ RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80),
+ RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80),
+ RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80),
+ RSND_GEN_S_REG(SSI9_BUSIF0_MODE, 0x48c),
+ RSND_GEN_S_REG(SSI9_BUSIF0_ADINR, 0x484),
+ RSND_GEN_S_REG(SSI9_BUSIF0_DALIGN, 0x488),
+ RSND_GEN_S_REG(SSI9_BUSIF1_MODE, 0x4a0),
+ RSND_GEN_S_REG(SSI9_BUSIF1_ADINR, 0x4a4),
+ RSND_GEN_S_REG(SSI9_BUSIF1_DALIGN, 0x4a8),
+ RSND_GEN_S_REG(SSI9_BUSIF2_MODE, 0x4c0),
+ RSND_GEN_S_REG(SSI9_BUSIF2_ADINR, 0x4c4),
+ RSND_GEN_S_REG(SSI9_BUSIF2_DALIGN, 0x4c8),
+ RSND_GEN_S_REG(SSI9_BUSIF3_MODE, 0x4e0),
+ RSND_GEN_S_REG(SSI9_BUSIF3_ADINR, 0x4e4),
+ RSND_GEN_S_REG(SSI9_BUSIF3_DALIGN, 0x4e8),
+ RSND_GEN_S_REG(SSI9_BUSIF4_MODE, 0xd80),
+ RSND_GEN_S_REG(SSI9_BUSIF4_ADINR, 0xd84),
+ RSND_GEN_S_REG(SSI9_BUSIF4_DALIGN, 0xd88),
+ RSND_GEN_S_REG(SSI9_BUSIF5_MODE, 0xda0),
+ RSND_GEN_S_REG(SSI9_BUSIF5_ADINR, 0xda4),
+ RSND_GEN_S_REG(SSI9_BUSIF5_DALIGN, 0xda8),
+ RSND_GEN_S_REG(SSI9_BUSIF6_MODE, 0xdc0),
+ RSND_GEN_S_REG(SSI9_BUSIF6_ADINR, 0xdc4),
+ RSND_GEN_S_REG(SSI9_BUSIF6_DALIGN, 0xdc8),
+ RSND_GEN_S_REG(SSI9_BUSIF7_MODE, 0xde0),
+ RSND_GEN_S_REG(SSI9_BUSIF7_ADINR, 0xde4),
+ RSND_GEN_S_REG(SSI9_BUSIF7_DALIGN, 0xde8),
+};
+
+static const struct rsnd_regmap_field_conf conf_common_scu[] = {
+ RSND_GEN_M_REG(SRC_I_BUSIF_MODE, 0x0, 0x20),
+ RSND_GEN_M_REG(SRC_O_BUSIF_MODE, 0x4, 0x20),
+ RSND_GEN_M_REG(SRC_BUSIF_DALIGN, 0x8, 0x20),
+ RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
+ RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
+ RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20),
+ RSND_GEN_M_REG(CMD_BUSIF_MODE, 0x184, 0x20),
+ RSND_GEN_M_REG(CMD_BUSIF_DALIGN, 0x188, 0x20),
+ RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20),
+ RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20),
+ RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8),
+ RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc),
+ RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0),
+ RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1d4),
+ RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40),
+ RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40),
+ RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40),
+ RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40),
+ RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40),
+ RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40),
+ RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40),
+ RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40),
+ RSND_GEN_M_REG(CTU_SWRSR, 0x500, 0x100),
+ RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100),
+ RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100),
+ RSND_GEN_M_REG(CTU_CPMDR, 0x510, 0x100),
+ RSND_GEN_M_REG(CTU_SCMDR, 0x514, 0x100),
+ RSND_GEN_M_REG(CTU_SV00R, 0x518, 0x100),
+ RSND_GEN_M_REG(CTU_SV01R, 0x51c, 0x100),
+ RSND_GEN_M_REG(CTU_SV02R, 0x520, 0x100),
+ RSND_GEN_M_REG(CTU_SV03R, 0x524, 0x100),
+ RSND_GEN_M_REG(CTU_SV04R, 0x528, 0x100),
+ RSND_GEN_M_REG(CTU_SV05R, 0x52c, 0x100),
+ RSND_GEN_M_REG(CTU_SV06R, 0x530, 0x100),
+ RSND_GEN_M_REG(CTU_SV07R, 0x534, 0x100),
+ RSND_GEN_M_REG(CTU_SV10R, 0x538, 0x100),
+ RSND_GEN_M_REG(CTU_SV11R, 0x53c, 0x100),
+ RSND_GEN_M_REG(CTU_SV12R, 0x540, 0x100),
+ RSND_GEN_M_REG(CTU_SV13R, 0x544, 0x100),
+ RSND_GEN_M_REG(CTU_SV14R, 0x548, 0x100),
+ RSND_GEN_M_REG(CTU_SV15R, 0x54c, 0x100),
+ RSND_GEN_M_REG(CTU_SV16R, 0x550, 0x100),
+ RSND_GEN_M_REG(CTU_SV17R, 0x554, 0x100),
+ RSND_GEN_M_REG(CTU_SV20R, 0x558, 0x100),
+ RSND_GEN_M_REG(CTU_SV21R, 0x55c, 0x100),
+ RSND_GEN_M_REG(CTU_SV22R, 0x560, 0x100),
+ RSND_GEN_M_REG(CTU_SV23R, 0x564, 0x100),
+ RSND_GEN_M_REG(CTU_SV24R, 0x568, 0x100),
+ RSND_GEN_M_REG(CTU_SV25R, 0x56c, 0x100),
+ RSND_GEN_M_REG(CTU_SV26R, 0x570, 0x100),
+ RSND_GEN_M_REG(CTU_SV27R, 0x574, 0x100),
+ RSND_GEN_M_REG(CTU_SV30R, 0x578, 0x100),
+ RSND_GEN_M_REG(CTU_SV31R, 0x57c, 0x100),
+ RSND_GEN_M_REG(CTU_SV32R, 0x580, 0x100),
+ RSND_GEN_M_REG(CTU_SV33R, 0x584, 0x100),
+ RSND_GEN_M_REG(CTU_SV34R, 0x588, 0x100),
+ RSND_GEN_M_REG(CTU_SV35R, 0x58c, 0x100),
+ RSND_GEN_M_REG(CTU_SV36R, 0x590, 0x100),
+ RSND_GEN_M_REG(CTU_SV37R, 0x594, 0x100),
+ RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40),
+ RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40),
+ RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40),
+ RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40),
+ RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40),
+ RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40),
+ RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40),
+ RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40),
+ RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40),
+ RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40),
+ RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100),
+ RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100),
+ RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100),
+ RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100),
+ RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100),
+ RSND_GEN_M_REG(DVC_VRCTR, 0xe18, 0x100),
+ RSND_GEN_M_REG(DVC_VRPDR, 0xe1c, 0x100),
+ RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100),
+ RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100),
+ RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100),
+ RSND_GEN_M_REG(DVC_VOL2R, 0xe30, 0x100),
+ RSND_GEN_M_REG(DVC_VOL3R, 0xe34, 0x100),
+ RSND_GEN_M_REG(DVC_VOL4R, 0xe38, 0x100),
+ RSND_GEN_M_REG(DVC_VOL5R, 0xe3c, 0x100),
+ RSND_GEN_M_REG(DVC_VOL6R, 0xe40, 0x100),
+ RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100),
+ RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100),
+};
+
+static const struct rsnd_regmap_field_conf conf_common_adg[] = {
+ RSND_GEN_S_REG(BRRA, 0x00),
+ RSND_GEN_S_REG(BRRB, 0x04),
+ RSND_GEN_S_REG(BRGCKR, 0x08),
+ RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
+ RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
+ RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14),
+ RSND_GEN_S_REG(DIV_EN, 0x30),
+ RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34),
+ RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38),
+ RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c),
+ RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40),
+ RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44),
+ RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48),
+ RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c),
+ RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50),
+ RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54),
+ RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58),
+ RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c),
+};
+
+static const struct rsnd_regmap_field_conf conf_common_ssi[] = {
+ RSND_GEN_M_REG(SSICR, 0x00, 0x40),
+ RSND_GEN_M_REG(SSISR, 0x04, 0x40),
+ RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
+ RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40),
+ RSND_GEN_M_REG(SSIWSR, 0x20, 0x40),
+};
+
+/*
* Gen4
*/
static int rsnd_gen4_probe(struct rsnd_priv *priv)
{
- static const struct rsnd_regmap_field_conf conf_ssiu[] = {
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898),
- RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840),
- RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848),
- RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880),
- RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888),
-
- RSND_GEN_S_REG(SSI_BUSIF0_MODE, 0x0),
- RSND_GEN_S_REG(SSI_BUSIF0_ADINR, 0x4),
- RSND_GEN_S_REG(SSI_BUSIF0_DALIGN, 0x8),
- RSND_GEN_S_REG(SSI_BUSIF1_MODE, 0x20),
- RSND_GEN_S_REG(SSI_BUSIF1_ADINR, 0x24),
- RSND_GEN_S_REG(SSI_BUSIF1_DALIGN, 0x28),
- RSND_GEN_S_REG(SSI_BUSIF2_MODE, 0x40),
- RSND_GEN_S_REG(SSI_BUSIF2_ADINR, 0x44),
- RSND_GEN_S_REG(SSI_BUSIF2_DALIGN, 0x48),
- RSND_GEN_S_REG(SSI_BUSIF3_MODE, 0x60),
- RSND_GEN_S_REG(SSI_BUSIF3_ADINR, 0x64),
- RSND_GEN_S_REG(SSI_BUSIF3_DALIGN, 0x68),
- RSND_GEN_S_REG(SSI_BUSIF4_MODE, 0x500),
- RSND_GEN_S_REG(SSI_BUSIF4_ADINR, 0x504),
- RSND_GEN_S_REG(SSI_BUSIF4_DALIGN, 0x508),
- RSND_GEN_S_REG(SSI_BUSIF5_MODE, 0x520),
- RSND_GEN_S_REG(SSI_BUSIF5_ADINR, 0x524),
- RSND_GEN_S_REG(SSI_BUSIF5_DALIGN, 0x528),
- RSND_GEN_S_REG(SSI_BUSIF6_MODE, 0x540),
- RSND_GEN_S_REG(SSI_BUSIF6_ADINR, 0x544),
- RSND_GEN_S_REG(SSI_BUSIF6_DALIGN, 0x548),
- RSND_GEN_S_REG(SSI_BUSIF7_MODE, 0x560),
- RSND_GEN_S_REG(SSI_BUSIF7_ADINR, 0x564),
- RSND_GEN_S_REG(SSI_BUSIF7_DALIGN, 0x568),
- RSND_GEN_S_REG(SSI_CTRL, 0x010),
- RSND_GEN_S_REG(SSI_INT_ENABLE, 0x018),
- RSND_GEN_S_REG(SSI_MODE, 0x00c),
- RSND_GEN_S_REG(SSI_MODE2, 0xa0c),
- };
- static const struct rsnd_regmap_field_conf conf_adg[] = {
- RSND_GEN_S_REG(BRRA, 0x00),
- RSND_GEN_S_REG(BRRB, 0x04),
- RSND_GEN_S_REG(BRGCKR, 0x08),
- RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
- };
- static const struct rsnd_regmap_field_conf conf_ssi[] = {
- RSND_GEN_S_REG(SSICR, 0x00),
- RSND_GEN_S_REG(SSISR, 0x04),
- RSND_GEN_S_REG(SSITDR, 0x08),
- RSND_GEN_S_REG(SSIRDR, 0x0c),
- RSND_GEN_S_REG(SSIWSR, 0x20),
- };
- static const struct rsnd_regmap_field_conf conf_sdmc[] = {
- RSND_GEN_M_REG(SSI_BUSIF, 0x0, 0x8000),
- };
- int ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_ADG, "adg", conf_adg);
- int ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSIU, "ssiu", conf_ssiu);
- int ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSI, "ssi", conf_ssi);
- int ret_sdmc = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SDMC, "sdmc", conf_sdmc);
+ struct rsnd_regmap_field_conf conf_null[] = { };
+
+ /*
+ * ssiu: SSIU0
+ * ssi : SSI0
+ */
+ int ret_ssiu = rsnd_gen_regmap_init(priv, 1, RSND_BASE_SSIU, "ssiu", conf_common_ssiu);
+ int ret_ssi = rsnd_gen_regmap_init(priv, 1, RSND_BASE_SSI, "ssi", conf_common_ssi);
+ int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_BASE_ADG, "adg", conf_common_adg);
+ int ret_sdmc = rsnd_gen_regmap_init(priv, 1, RSND_BASE_SDMC, "sdmc", conf_null);
return ret_adg | ret_ssiu | ret_ssi | ret_sdmc;
}
@@ -288,215 +436,17 @@ static int rsnd_gen4_probe(struct rsnd_priv *priv)
*/
static int rsnd_gen2_probe(struct rsnd_priv *priv)
{
- static const struct rsnd_regmap_field_conf conf_ssiu[] = {
- RSND_GEN_S_REG(SSI_MODE0, 0x800),
- RSND_GEN_S_REG(SSI_MODE1, 0x804),
- RSND_GEN_S_REG(SSI_MODE2, 0x808),
- RSND_GEN_S_REG(SSI_CONTROL, 0x810),
- RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840),
- RSND_GEN_S_REG(SSI_SYS_STATUS1, 0x844),
- RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848),
- RSND_GEN_S_REG(SSI_SYS_STATUS3, 0x84c),
- RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880),
- RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884),
- RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888),
- RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE1, 0x854),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE3, 0x85c),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE5, 0x894),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE7, 0x89c),
- RSND_GEN_S_REG(HDMI0_SEL, 0x9e0),
- RSND_GEN_S_REG(HDMI1_SEL, 0x9e4),
-
- /* FIXME: it needs SSI_MODE2/3 in the future */
- RSND_GEN_M_REG(SSI_BUSIF0_MODE, 0x0, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF0_ADINR, 0x4, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF0_DALIGN, 0x8, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF1_MODE, 0x20, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF1_ADINR, 0x24, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF1_DALIGN, 0x28, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF2_MODE, 0x40, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF2_ADINR, 0x44, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF2_DALIGN, 0x48, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF3_MODE, 0x60, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF3_ADINR, 0x64, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF3_DALIGN, 0x68, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF4_MODE, 0x500, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF4_ADINR, 0x504, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF4_DALIGN, 0x508, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF5_MODE, 0x520, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF5_ADINR, 0x524, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF5_DALIGN, 0x528, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF6_MODE, 0x540, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF6_ADINR, 0x544, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF6_DALIGN, 0x548, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF7_MODE, 0x560, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF7_ADINR, 0x564, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF7_DALIGN, 0x568, 0x80),
- RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80),
- RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80),
- RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80),
- RSND_GEN_S_REG(SSI9_BUSIF0_MODE, 0x48c),
- RSND_GEN_S_REG(SSI9_BUSIF0_ADINR, 0x484),
- RSND_GEN_S_REG(SSI9_BUSIF0_DALIGN, 0x488),
- RSND_GEN_S_REG(SSI9_BUSIF1_MODE, 0x4a0),
- RSND_GEN_S_REG(SSI9_BUSIF1_ADINR, 0x4a4),
- RSND_GEN_S_REG(SSI9_BUSIF1_DALIGN, 0x4a8),
- RSND_GEN_S_REG(SSI9_BUSIF2_MODE, 0x4c0),
- RSND_GEN_S_REG(SSI9_BUSIF2_ADINR, 0x4c4),
- RSND_GEN_S_REG(SSI9_BUSIF2_DALIGN, 0x4c8),
- RSND_GEN_S_REG(SSI9_BUSIF3_MODE, 0x4e0),
- RSND_GEN_S_REG(SSI9_BUSIF3_ADINR, 0x4e4),
- RSND_GEN_S_REG(SSI9_BUSIF3_DALIGN, 0x4e8),
- RSND_GEN_S_REG(SSI9_BUSIF4_MODE, 0xd80),
- RSND_GEN_S_REG(SSI9_BUSIF4_ADINR, 0xd84),
- RSND_GEN_S_REG(SSI9_BUSIF4_DALIGN, 0xd88),
- RSND_GEN_S_REG(SSI9_BUSIF5_MODE, 0xda0),
- RSND_GEN_S_REG(SSI9_BUSIF5_ADINR, 0xda4),
- RSND_GEN_S_REG(SSI9_BUSIF5_DALIGN, 0xda8),
- RSND_GEN_S_REG(SSI9_BUSIF6_MODE, 0xdc0),
- RSND_GEN_S_REG(SSI9_BUSIF6_ADINR, 0xdc4),
- RSND_GEN_S_REG(SSI9_BUSIF6_DALIGN, 0xdc8),
- RSND_GEN_S_REG(SSI9_BUSIF7_MODE, 0xde0),
- RSND_GEN_S_REG(SSI9_BUSIF7_ADINR, 0xde4),
- RSND_GEN_S_REG(SSI9_BUSIF7_DALIGN, 0xde8),
- };
-
- static const struct rsnd_regmap_field_conf conf_scu[] = {
- RSND_GEN_M_REG(SRC_I_BUSIF_MODE,0x0, 0x20),
- RSND_GEN_M_REG(SRC_O_BUSIF_MODE,0x4, 0x20),
- RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20),
- RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
- RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
- RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20),
- RSND_GEN_M_REG(CMD_BUSIF_MODE, 0x184, 0x20),
- RSND_GEN_M_REG(CMD_BUSIF_DALIGN,0x188, 0x20),
- RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20),
- RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20),
- RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8),
- RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc),
- RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0),
- RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1d4),
- RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40),
- RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40),
- RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40),
- RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40),
- RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40),
- RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40),
- RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40),
- RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40),
- RSND_GEN_M_REG(CTU_SWRSR, 0x500, 0x100),
- RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100),
- RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100),
- RSND_GEN_M_REG(CTU_CPMDR, 0x510, 0x100),
- RSND_GEN_M_REG(CTU_SCMDR, 0x514, 0x100),
- RSND_GEN_M_REG(CTU_SV00R, 0x518, 0x100),
- RSND_GEN_M_REG(CTU_SV01R, 0x51c, 0x100),
- RSND_GEN_M_REG(CTU_SV02R, 0x520, 0x100),
- RSND_GEN_M_REG(CTU_SV03R, 0x524, 0x100),
- RSND_GEN_M_REG(CTU_SV04R, 0x528, 0x100),
- RSND_GEN_M_REG(CTU_SV05R, 0x52c, 0x100),
- RSND_GEN_M_REG(CTU_SV06R, 0x530, 0x100),
- RSND_GEN_M_REG(CTU_SV07R, 0x534, 0x100),
- RSND_GEN_M_REG(CTU_SV10R, 0x538, 0x100),
- RSND_GEN_M_REG(CTU_SV11R, 0x53c, 0x100),
- RSND_GEN_M_REG(CTU_SV12R, 0x540, 0x100),
- RSND_GEN_M_REG(CTU_SV13R, 0x544, 0x100),
- RSND_GEN_M_REG(CTU_SV14R, 0x548, 0x100),
- RSND_GEN_M_REG(CTU_SV15R, 0x54c, 0x100),
- RSND_GEN_M_REG(CTU_SV16R, 0x550, 0x100),
- RSND_GEN_M_REG(CTU_SV17R, 0x554, 0x100),
- RSND_GEN_M_REG(CTU_SV20R, 0x558, 0x100),
- RSND_GEN_M_REG(CTU_SV21R, 0x55c, 0x100),
- RSND_GEN_M_REG(CTU_SV22R, 0x560, 0x100),
- RSND_GEN_M_REG(CTU_SV23R, 0x564, 0x100),
- RSND_GEN_M_REG(CTU_SV24R, 0x568, 0x100),
- RSND_GEN_M_REG(CTU_SV25R, 0x56c, 0x100),
- RSND_GEN_M_REG(CTU_SV26R, 0x570, 0x100),
- RSND_GEN_M_REG(CTU_SV27R, 0x574, 0x100),
- RSND_GEN_M_REG(CTU_SV30R, 0x578, 0x100),
- RSND_GEN_M_REG(CTU_SV31R, 0x57c, 0x100),
- RSND_GEN_M_REG(CTU_SV32R, 0x580, 0x100),
- RSND_GEN_M_REG(CTU_SV33R, 0x584, 0x100),
- RSND_GEN_M_REG(CTU_SV34R, 0x588, 0x100),
- RSND_GEN_M_REG(CTU_SV35R, 0x58c, 0x100),
- RSND_GEN_M_REG(CTU_SV36R, 0x590, 0x100),
- RSND_GEN_M_REG(CTU_SV37R, 0x594, 0x100),
- RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40),
- RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40),
- RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40),
- RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40),
- RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40),
- RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40),
- RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40),
- RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40),
- RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40),
- RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40),
- RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100),
- RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100),
- RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100),
- RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100),
- RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100),
- RSND_GEN_M_REG(DVC_VRCTR, 0xe18, 0x100),
- RSND_GEN_M_REG(DVC_VRPDR, 0xe1c, 0x100),
- RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100),
- RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100),
- RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100),
- RSND_GEN_M_REG(DVC_VOL2R, 0xe30, 0x100),
- RSND_GEN_M_REG(DVC_VOL3R, 0xe34, 0x100),
- RSND_GEN_M_REG(DVC_VOL4R, 0xe38, 0x100),
- RSND_GEN_M_REG(DVC_VOL5R, 0xe3c, 0x100),
- RSND_GEN_M_REG(DVC_VOL6R, 0xe40, 0x100),
- RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100),
- RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100),
- };
- static const struct rsnd_regmap_field_conf conf_adg[] = {
- RSND_GEN_S_REG(BRRA, 0x00),
- RSND_GEN_S_REG(BRRB, 0x04),
- RSND_GEN_S_REG(BRGCKR, 0x08),
- RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
- RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
- RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14),
- RSND_GEN_S_REG(DIV_EN, 0x30),
- RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34),
- RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38),
- RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c),
- RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40),
- RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44),
- RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48),
- RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c),
- RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50),
- RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54),
- RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58),
- RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c),
- };
- static const struct rsnd_regmap_field_conf conf_ssi[] = {
- RSND_GEN_M_REG(SSICR, 0x00, 0x40),
- RSND_GEN_M_REG(SSISR, 0x04, 0x40),
- RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
- RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40),
- RSND_GEN_M_REG(SSIWSR, 0x20, 0x40),
- };
- int ret_ssiu;
- int ret_scu;
- int ret_adg;
- int ret_ssi;
-
- ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, "ssiu", conf_ssiu);
- ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, "scu", conf_scu);
- ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG, "adg", conf_adg);
- ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, "ssi", conf_ssi);
- if (ret_ssiu < 0 ||
- ret_scu < 0 ||
- ret_adg < 0 ||
- ret_ssi < 0)
- return ret_ssiu | ret_scu | ret_adg | ret_ssi;
-
- return 0;
+ /*
+ * ssi : SSI0 - SSI9
+ * ssiu: SSIU0 - SSIU9
+ * scu : SRC0 - SRC9 etc
+ */
+ int ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_BASE_SSI, "ssi", conf_common_ssi);
+ int ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_BASE_SSIU, "ssiu", conf_common_ssiu);
+ int ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_BASE_SCU, "scu", conf_common_scu);
+ int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_BASE_ADG, "adg", conf_common_adg);
+
+ return ret_ssi | ret_ssiu | ret_scu | ret_adg;
}
/*
@@ -505,30 +455,13 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
static int rsnd_gen1_probe(struct rsnd_priv *priv)
{
- static const struct rsnd_regmap_field_conf conf_adg[] = {
- RSND_GEN_S_REG(BRRA, 0x00),
- RSND_GEN_S_REG(BRRB, 0x04),
- RSND_GEN_S_REG(BRGCKR, 0x08),
- RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
- RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
- };
- static const struct rsnd_regmap_field_conf conf_ssi[] = {
- RSND_GEN_M_REG(SSICR, 0x00, 0x40),
- RSND_GEN_M_REG(SSISR, 0x04, 0x40),
- RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
- RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40),
- RSND_GEN_M_REG(SSIWSR, 0x20, 0x40),
- };
- int ret_adg;
- int ret_ssi;
-
- ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, "adg", conf_adg);
- ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, "ssi", conf_ssi);
- if (ret_adg < 0 ||
- ret_ssi < 0)
- return ret_adg | ret_ssi;
+ /*
+ * ssi : SSI0 - SSI8
+ */
+ int ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_BASE_SSI, "ssi", conf_common_ssi);
+ int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_BASE_ADG, "adg", conf_common_adg);
- return 0;
+ return ret_adg | ret_ssi;
}
/*
diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c
index 1de0e085804c..024d91cc8748 100644
--- a/sound/soc/sh/rcar/mix.c
+++ b/sound/soc/sh/rcar/mix.c
@@ -259,7 +259,7 @@ static void rsnd_mix_debug_info(struct seq_file *m,
struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
+ rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU,
0xd00 + rsnd_mod_id(mod) * 0x40, 0x30);
}
#define DEBUG_INFO .debug_info = rsnd_mix_debug_info
@@ -295,10 +295,6 @@ int rsnd_mix_probe(struct rsnd_priv *priv)
char name[MIX_NAME_SIZE];
int i, nr, ret;
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
node = rsnd_mix_of_node(priv);
if (!node)
return 0; /* not used is not error */
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index da716b1f52e4..ff294aa2d640 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -20,20 +20,11 @@
#include <sound/soc.h>
#include <sound/pcm_params.h>
-#define RSND_GEN1_SRU 0
-#define RSND_GEN1_ADG 1
-#define RSND_GEN1_SSI 2
-
-#define RSND_GEN2_SCU 0
-#define RSND_GEN2_ADG 1
-#define RSND_GEN2_SSIU 2
-#define RSND_GEN2_SSI 3
-
-#define RSND_GEN4_ADG 0
-#define RSND_GEN4_SSIU 1
-#define RSND_GEN4_SSI 2
-#define RSND_GEN4_SDMC 3
-
+#define RSND_BASE_ADG 0
+#define RSND_BASE_SSI 1
+#define RSND_BASE_SSIU 2
+#define RSND_BASE_SCU 3 // for Gen2/Gen3
+#define RSND_BASE_SDMC 3 // for Gen4 reuse
#define RSND_BASE_MAX 4
/*
@@ -200,7 +191,6 @@ enum rsnd_reg {
SSI_SYS_INT_ENABLE5,
SSI_SYS_INT_ENABLE6,
SSI_SYS_INT_ENABLE7,
- SSI_BUSIF,
HDMI0_SEL,
HDMI1_SEL,
SSI9_BUSIF0_MODE,
@@ -713,7 +703,7 @@ struct rsnd_priv {
#define rsnd_is_gen2(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN2)
#define rsnd_is_gen3(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN3)
#define rsnd_is_gen4(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN4)
-#define rsnd_is_e3(priv) (((priv)->flags & \
+#define rsnd_is_gen3_e3(priv) (((priv)->flags & \
(RSND_GEN_MASK | RSND_SOC_MASK)) == \
(RSND_GEN3 | RSND_SOC_E))
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 3241a1bdc9ea..e7f86db0d94c 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -310,7 +310,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
/*
* E3 need to overwrite
*/
- if (rsnd_is_e3(priv))
+ if (rsnd_is_gen3_e3(priv))
switch (rsnd_mod_id(mod)) {
case 0:
case 4:
@@ -606,13 +606,13 @@ static void rsnd_src_debug_info(struct seq_file *m,
struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
+ rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU,
rsnd_mod_id(mod) * 0x20, 0x20);
seq_puts(m, "\n");
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
+ rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU,
0x1c0, 0x20);
seq_puts(m, "\n");
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
+ rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU,
0x200 + rsnd_mod_id(mod) * 0x40, 0x40);
}
#define DEBUG_INFO .debug_info = rsnd_src_debug_info
@@ -652,10 +652,6 @@ int rsnd_src_probe(struct rsnd_priv *priv)
char name[RSND_SRC_NAME_SIZE];
int i, nr, ret;
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
node = rsnd_src_of_node(priv);
if (!node)
return 0; /* not used is not error */
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 0a46aa1975fa..8d2a86383ae0 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -1049,7 +1049,7 @@ static void rsnd_ssi_debug_info(struct seq_file *m,
seq_printf(m, "chan: %d\n", ssi->chan);
seq_printf(m, "user: %d\n", ssi->usrcnt);
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SSI,
+ rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SSI,
rsnd_mod_id(mod) * 0x40, 0x40);
}
#define DEBUG_INFO .debug_info = rsnd_ssi_debug_info
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c
index 17bd8cc86dd0..665e8b2db579 100644
--- a/sound/soc/sh/rcar/ssiu.c
+++ b/sound/soc/sh/rcar/ssiu.c
@@ -413,7 +413,7 @@ static void rsnd_ssiu_debug_info(struct seq_file *m,
struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SSIU,
+ rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SSIU,
rsnd_mod_id(mod) * 0x80, 0x80);
}
#define DEBUG_INFO .debug_info = rsnd_ssiu_debug_info
diff --git a/sound/soc/soc-card-test.c b/sound/soc/soc-card-test.c
new file mode 100644
index 000000000000..075c52fe82e5
--- /dev/null
+++ b/sound/soc/soc-card-test.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2024 Cirrus Logic, Inc. and
+// Cirrus Logic International Semiconductor Ltd.
+
+#include <kunit/device.h>
+#include <kunit/test.h>
+#include <linux/module.h>
+#include <sound/control.h>
+#include <sound/soc.h>
+#include <sound/soc-card.h>
+
+struct soc_card_test_priv {
+ struct device *card_dev;
+ struct snd_soc_card *card;
+};
+
+static const struct snd_kcontrol_new test_card_controls[] = {
+ SOC_SINGLE("Fee", SND_SOC_NOPM, 0, 1, 0),
+ SOC_SINGLE("Fi", SND_SOC_NOPM, 1, 1, 0),
+ SOC_SINGLE("Fo", SND_SOC_NOPM, 2, 1, 0),
+ SOC_SINGLE("Fum", SND_SOC_NOPM, 3, 1, 0),
+ SOC_SINGLE("Left Fee", SND_SOC_NOPM, 4, 1, 0),
+ SOC_SINGLE("Right Fee", SND_SOC_NOPM, 5, 1, 0),
+ SOC_SINGLE("Left Fi", SND_SOC_NOPM, 6, 1, 0),
+ SOC_SINGLE("Right Fi", SND_SOC_NOPM, 7, 1, 0),
+ SOC_SINGLE("Left Fo", SND_SOC_NOPM, 8, 1, 0),
+ SOC_SINGLE("Right Fo", SND_SOC_NOPM, 9, 1, 0),
+ SOC_SINGLE("Left Fum", SND_SOC_NOPM, 10, 1, 0),
+ SOC_SINGLE("Right Fum", SND_SOC_NOPM, 11, 1, 0),
+};
+
+static void test_snd_soc_card_get_kcontrol(struct kunit *test)
+{
+ struct soc_card_test_priv *priv = test->priv;
+ struct snd_soc_card *card = priv->card;
+ struct snd_kcontrol *kc;
+ struct soc_mixer_control *mc;
+ int i, ret;
+
+ ret = snd_soc_add_card_controls(card, test_card_controls, ARRAY_SIZE(test_card_controls));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ /* Look up every control */
+ for (i = 0; i < ARRAY_SIZE(test_card_controls); ++i) {
+ kc = snd_soc_card_get_kcontrol(card, test_card_controls[i].name);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, kc, "Failed to find '%s'\n",
+ test_card_controls[i].name);
+ if (!kc)
+ continue;
+
+ /* Test that it is the correct control */
+ mc = (struct soc_mixer_control *)kc->private_value;
+ KUNIT_EXPECT_EQ_MSG(test, mc->shift, i, "For '%s'\n", test_card_controls[i].name);
+ }
+
+ /* Test some names that should not be found */
+ kc = snd_soc_card_get_kcontrol(card, "None");
+ KUNIT_EXPECT_NULL(test, kc);
+
+ kc = snd_soc_card_get_kcontrol(card, "Left None");
+ KUNIT_EXPECT_NULL(test, kc);
+
+ kc = snd_soc_card_get_kcontrol(card, "Left");
+ KUNIT_EXPECT_NULL(test, kc);
+
+ kc = snd_soc_card_get_kcontrol(card, NULL);
+ KUNIT_EXPECT_NULL(test, kc);
+}
+
+static void test_snd_soc_card_get_kcontrol_locked(struct kunit *test)
+{
+ struct soc_card_test_priv *priv = test->priv;
+ struct snd_soc_card *card = priv->card;
+ struct snd_kcontrol *kc, *kcw;
+ struct soc_mixer_control *mc;
+ int i, ret;
+
+ ret = snd_soc_add_card_controls(card, test_card_controls, ARRAY_SIZE(test_card_controls));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ /* Look up every control */
+ for (i = 0; i < ARRAY_SIZE(test_card_controls); ++i) {
+ down_read(&card->snd_card->controls_rwsem);
+ kc = snd_soc_card_get_kcontrol_locked(card, test_card_controls[i].name);
+ up_read(&card->snd_card->controls_rwsem);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, kc, "Failed to find '%s'\n",
+ test_card_controls[i].name);
+ if (!kc)
+ continue;
+
+ /* Test that it is the correct control */
+ mc = (struct soc_mixer_control *)kc->private_value;
+ KUNIT_EXPECT_EQ_MSG(test, mc->shift, i, "For '%s'\n", test_card_controls[i].name);
+
+ down_write(&card->snd_card->controls_rwsem);
+ kcw = snd_soc_card_get_kcontrol_locked(card, test_card_controls[i].name);
+ up_write(&card->snd_card->controls_rwsem);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, kcw, "Failed to find '%s'\n",
+ test_card_controls[i].name);
+
+ KUNIT_EXPECT_PTR_EQ(test, kc, kcw);
+ }
+
+ /* Test some names that should not be found */
+ down_read(&card->snd_card->controls_rwsem);
+ kc = snd_soc_card_get_kcontrol_locked(card, "None");
+ up_read(&card->snd_card->controls_rwsem);
+ KUNIT_EXPECT_NULL(test, kc);
+
+ down_read(&card->snd_card->controls_rwsem);
+ kc = snd_soc_card_get_kcontrol_locked(card, "Left None");
+ up_read(&card->snd_card->controls_rwsem);
+ KUNIT_EXPECT_NULL(test, kc);
+
+ down_read(&card->snd_card->controls_rwsem);
+ kc = snd_soc_card_get_kcontrol_locked(card, "Left");
+ up_read(&card->snd_card->controls_rwsem);
+ KUNIT_EXPECT_NULL(test, kc);
+
+ down_read(&card->snd_card->controls_rwsem);
+ kc = snd_soc_card_get_kcontrol_locked(card, NULL);
+ up_read(&card->snd_card->controls_rwsem);
+ KUNIT_EXPECT_NULL(test, kc);
+}
+
+static int soc_card_test_case_init(struct kunit *test)
+{
+ struct soc_card_test_priv *priv;
+ int ret;
+
+ priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ test->priv = priv;
+
+ priv->card_dev = kunit_device_register(test, "sound-soc-card-test");
+ priv->card_dev = get_device(priv->card_dev);
+ if (!priv->card_dev)
+ return -ENODEV;
+
+ priv->card = kunit_kzalloc(test, sizeof(*priv->card), GFP_KERNEL);
+ if (!priv->card)
+ return -ENOMEM;
+
+ priv->card->name = "soc-card-test";
+ priv->card->dev = priv->card_dev;
+ priv->card->owner = THIS_MODULE;
+
+ ret = snd_soc_register_card(priv->card);
+ if (!ret)
+ return ret;
+
+ return 0;
+}
+
+static void soc_card_test_case_exit(struct kunit *test)
+{
+ struct soc_card_test_priv *priv = test->priv;
+
+ if (priv->card)
+ snd_soc_unregister_card(priv->card);
+
+ if (priv->card_dev)
+ put_device(priv->card_dev);
+}
+
+static struct kunit_case soc_card_test_cases[] = {
+ KUNIT_CASE(test_snd_soc_card_get_kcontrol),
+ KUNIT_CASE(test_snd_soc_card_get_kcontrol_locked),
+ {}
+};
+
+static struct kunit_suite soc_card_test_suite = {
+ .name = "soc-card",
+ .test_cases = soc_card_test_cases,
+ .init = soc_card_test_case_init,
+ .exit = soc_card_test_case_exit,
+};
+
+kunit_test_suites(&soc_card_test_suite);
+
+MODULE_DESCRIPTION("ASoC soc-card KUnit test");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c
index 8a2f163da6bc..0a3104d4ad23 100644
--- a/sound/soc/soc-card.c
+++ b/sound/soc/soc-card.c
@@ -32,33 +32,20 @@ static inline int _soc_card_ret(struct snd_soc_card *card,
struct snd_kcontrol *snd_soc_card_get_kcontrol_locked(struct snd_soc_card *soc_card,
const char *name)
{
- struct snd_card *card = soc_card->snd_card;
- struct snd_kcontrol *kctl;
-
- /* must be held read or write */
- lockdep_assert_held(&card->controls_rwsem);
-
if (unlikely(!name))
return NULL;
- list_for_each_entry(kctl, &card->controls, list)
- if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name)))
- return kctl;
- return NULL;
+ return snd_ctl_find_id_mixer_locked(soc_card->snd_card, name);
}
EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol_locked);
struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
const char *name)
{
- struct snd_card *card = soc_card->snd_card;
- struct snd_kcontrol *kctl;
-
- down_read(&card->controls_rwsem);
- kctl = snd_soc_card_get_kcontrol_locked(soc_card, name);
- up_read(&card->controls_rwsem);
+ if (unlikely(!name))
+ return NULL;
- return kctl;
+ return snd_ctl_find_id_mixer(soc_card->snd_card, name);
}
EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index b2cc13b9c77b..63971396b708 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -8,7 +8,6 @@
#include <sound/jack.h>
#include <sound/soc.h>
-#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
@@ -345,21 +344,9 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
goto undo;
}
} else {
- /* legacy GPIO number */
- if (!gpio_is_valid(gpios[i].gpio)) {
- dev_err(jack->card->dev,
- "ASoC: Invalid gpio %d\n",
- gpios[i].gpio);
- ret = -EINVAL;
- goto undo;
- }
-
- ret = gpio_request_one(gpios[i].gpio, GPIOF_IN,
- gpios[i].name);
- if (ret)
- goto undo;
-
- gpios[i].desc = gpio_to_desc(gpios[i].gpio);
+ dev_err(jack->card->dev, "ASoC: Invalid gpio at index %d\n", i);
+ ret = -EINVAL;
+ goto undo;
}
got_gpio:
INIT_DELAYED_WORK(&gpios[i].work, gpio_work);
@@ -373,7 +360,7 @@ got_gpio:
gpios[i].name,
&gpios[i]);
if (ret < 0)
- goto err;
+ goto undo;
if (gpios[i].wake) {
ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1);
@@ -401,8 +388,6 @@ got_gpio:
devres_add(jack->card->dev, tbl);
return 0;
-err:
- gpio_free(gpios[i].gpio);
undo:
jack_free_gpios(jack, i, gpios);
devres_free(tbl);
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index 2d25748ca706..b27e89ff6a16 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -263,7 +263,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
int max = mc->max;
int min = mc->min;
int sign_bit = mc->sign_bit;
- unsigned int mask = (1 << fls(max)) - 1;
+ unsigned int mask = (1ULL << fls(max)) - 1;
unsigned int invert = mc->invert;
int val;
int ret;
diff --git a/sound/soc/sof/amd/acp-loader.c b/sound/soc/sof/amd/acp-loader.c
index aad904839b81..2d5e58846499 100644
--- a/sound/soc/sof/amd/acp-loader.c
+++ b/sound/soc/sof/amd/acp-loader.c
@@ -289,6 +289,8 @@ int acp_sof_load_signed_firmware(struct snd_sof_dev *sdev)
ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_IRAM, 0,
(void *)sdev->basefw.fw->data,
sdev->basefw.fw->size);
+ if (ret < 0)
+ return ret;
fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
plat_data->fw_filename_prefix,
diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c
index 2b385cddc385..d71bb66b9991 100644
--- a/sound/soc/sof/intel/hda-common-ops.c
+++ b/sound/soc/sof/intel/hda-common-ops.c
@@ -57,6 +57,9 @@ struct snd_sof_dsp_ops sof_hda_common_ops = {
.pcm_pointer = hda_dsp_pcm_pointer,
.pcm_ack = hda_dsp_pcm_ack,
+ .get_dai_frame_counter = hda_dsp_get_stream_llp,
+ .get_host_byte_counter = hda_dsp_get_stream_ldp,
+
/* firmware loading */
.load_firmware = snd_sof_load_firmware_raw,
diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c
index c50ca9e72d37..457144203999 100644
--- a/sound/soc/sof/intel/hda-dai-ops.c
+++ b/sound/soc/sof/intel/hda-dai-ops.c
@@ -7,6 +7,7 @@
#include <sound/pcm_params.h>
#include <sound/hdaudio_ext.h>
+#include <sound/hda_register.h>
#include <sound/hda-mlink.h>
#include <sound/sof/ipc4/header.h>
#include <uapi/sound/sof/header.h>
@@ -145,17 +146,9 @@ static struct hdac_ext_stream *hda_assign_hext_stream(struct snd_sof_dev *sdev,
struct snd_soc_dai *cpu_dai,
struct snd_pcm_substream *substream)
{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *dai;
struct hdac_ext_stream *hext_stream;
- /* only allocate a stream_tag for the first DAI in the dailink */
- dai = snd_soc_rtd_to_cpu(rtd, 0);
- if (dai == cpu_dai)
- hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream);
- else
- hext_stream = snd_soc_dai_get_dma_data(dai, substream);
-
+ hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream);
if (!hext_stream)
return NULL;
@@ -168,14 +161,9 @@ static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai
struct snd_pcm_substream *substream)
{
struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *dai;
- /* only release a stream_tag for the first DAI in the dailink */
- dai = snd_soc_rtd_to_cpu(rtd, 0);
- if (dai == cpu_dai)
- snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
+ snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
}
static void hda_setup_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream,
@@ -362,6 +350,16 @@ static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
snd_hdac_ext_stream_clear(hext_stream);
+
+ /*
+ * Save the LLP registers in case the stream is
+ * restarting due PAUSE_RELEASE, or START without a pcm
+ * close/open since in this case the LLP register is not reset
+ * to 0 and the delay calculation will return with invalid
+ * results.
+ */
+ hext_stream->pplcllpl = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL);
+ hext_stream->pplcllpu = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU);
break;
default:
dev_err(sdev->dev, "unknown trigger command %d\n", cmd);
@@ -435,28 +433,6 @@ out:
return ret;
}
-static struct hdac_ext_stream *sdw_hda_ipc4_get_hext_stream(struct snd_sof_dev *sdev,
- struct snd_soc_dai *cpu_dai,
- struct snd_pcm_substream *substream)
-{
- struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
- struct snd_sof_widget *swidget = w->dobj.private;
- struct snd_sof_dai *dai = swidget->private;
- struct sof_ipc4_copier *ipc4_copier = dai->private;
- struct sof_ipc4_alh_configuration_blob *blob;
-
- blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
-
- /*
- * Starting with ACE_2_0, re-setting the device_count is mandatory to avoid using
- * the multi-gateway firmware configuration. The DMA hardware can take care of
- * multiple links without needing any firmware assistance
- */
- blob->alh_cfg.device_count = 1;
-
- return hda_ipc4_get_hext_stream(sdev, cpu_dai, substream);
-}
-
static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = {
.get_hext_stream = hda_ipc4_get_hext_stream,
.assign_hext_stream = hda_assign_hext_stream,
@@ -498,7 +474,7 @@ static const struct hda_dai_widget_dma_ops dmic_ipc4_dma_ops = {
};
static const struct hda_dai_widget_dma_ops sdw_ipc4_dma_ops = {
- .get_hext_stream = sdw_hda_ipc4_get_hext_stream,
+ .get_hext_stream = hda_ipc4_get_hext_stream,
.assign_hext_stream = hda_assign_hext_stream,
.release_hext_stream = hda_release_hext_stream,
.setup_hext_stream = hda_setup_hext_stream,
diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
index c1682bcdb5a6..3f2fd84907d2 100644
--- a/sound/soc/sof/intel/hda-dai.c
+++ b/sound/soc/sof/intel/hda-dai.c
@@ -29,14 +29,6 @@ static bool hda_use_tplg_nhlt;
module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444);
MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override");
-static struct snd_sof_dev *widget_to_sdev(struct snd_soc_dapm_widget *w)
-{
- struct snd_sof_widget *swidget = w->dobj.private;
- struct snd_soc_component *component = swidget->scomp;
-
- return snd_soc_component_get_drvdata(component);
-}
-
int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
struct snd_sof_dai_config_data *data)
{
@@ -221,15 +213,15 @@ static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream,
return hda_link_dma_cleanup(substream, hext_stream, cpu_dai);
}
-static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+static int __maybe_unused hda_dai_hw_params_data(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai,
+ struct snd_sof_dai_config_data *data,
+ unsigned int flags)
{
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream);
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai);
struct hdac_ext_stream *hext_stream;
- struct snd_sof_dai_config_data data = { 0 };
- unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
struct snd_sof_dev *sdev = widget_to_sdev(w);
int ret;
@@ -249,9 +241,19 @@ static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream,
hext_stream = ops->get_hext_stream(sdev, dai, substream);
flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT;
- data.dai_data = hdac_stream(hext_stream)->stream_tag - 1;
+ data->dai_data = hdac_stream(hext_stream)->stream_tag - 1;
- return hda_dai_config(w, flags, &data);
+ return hda_dai_config(w, flags, data);
+}
+
+static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_sof_dai_config_data data = { 0 };
+ unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
+
+ return hda_dai_hw_params_data(substream, params, dai, &data, flags);
}
/*
@@ -341,11 +343,14 @@ static struct sof_ipc4_copier *widget_to_copier(struct snd_soc_dapm_widget *w)
return ipc4_copier;
}
-static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *cpu_dai)
+static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *cpu_dai,
+ struct snd_sof_dai_config_data *data,
+ unsigned int flags)
{
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sof_ipc4_dma_config_tlv *dma_config_tlv;
const struct hda_dai_widget_dma_ops *ops;
struct sof_ipc4_dma_config *dma_config;
@@ -353,6 +358,8 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
struct hdac_ext_stream *hext_stream;
struct hdac_stream *hstream;
struct snd_sof_dev *sdev;
+ struct snd_soc_dai *dai;
+ int cpu_dai_id;
int stream_id;
int ret;
@@ -363,9 +370,9 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
}
/* use HDaudio stream handling */
- ret = hda_dai_hw_params(substream, params, cpu_dai);
+ ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags);
if (ret < 0) {
- dev_err(cpu_dai->dev, "%s: hda_dai_hw_params failed: %d\n", __func__, ret);
+ dev_err(cpu_dai->dev, "%s: hda_dai_hw_params_data failed: %d\n", __func__, ret);
return ret;
}
@@ -392,7 +399,12 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
/* configure TLV */
ipc4_copier = widget_to_copier(w);
- dma_config_tlv = &ipc4_copier->dma_config_tlv;
+ for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) {
+ if (dai == cpu_dai)
+ break;
+ }
+
+ dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id];
dma_config_tlv->type = SOF_IPC4_GTW_DMA_CONFIG_ID;
/* dma_config_priv_size is zero */
dma_config_tlv->length = sizeof(dma_config_tlv->dma_config);
@@ -403,13 +415,27 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
dma_config->pre_allocated_by_host = 1;
dma_config->dma_channel_id = stream_id - 1;
dma_config->stream_id = stream_id;
- dma_config->dma_stream_channel_map.device_count = 0; /* mapping not used */
+ /*
+ * Currently we use a DMA for each device in ALH blob. The device will
+ * be copied in sof_ipc4_prepare_copier_module.
+ */
+ dma_config->dma_stream_channel_map.device_count = 1;
dma_config->dma_priv_config_size = 0;
skip_tlv:
return 0;
}
+static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct snd_sof_dai_config_data data = { 0 };
+ unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
+
+ return non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags);
+}
+
static int non_hda_dai_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
@@ -436,15 +462,29 @@ static const struct snd_soc_dai_ops dmic_dai_ops = {
int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai,
- int link_id)
+ int link_id,
+ int intel_alh_id)
{
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct sof_ipc4_dma_config_tlv *dma_config_tlv;
+ struct snd_sof_dai_config_data data = { 0 };
+ unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
const struct hda_dai_widget_dma_ops *ops;
+ struct sof_ipc4_dma_config *dma_config;
+ struct sof_ipc4_copier *ipc4_copier;
struct hdac_ext_stream *hext_stream;
+ struct snd_soc_dai *dai;
struct snd_sof_dev *sdev;
+ bool cpu_dai_found = false;
+ int cpu_dai_id;
+ int ch_mask;
int ret;
+ int i;
- ret = non_hda_dai_hw_params(substream, params, cpu_dai);
+ data.dai_index = (link_id << 8) | cpu_dai->id;
+ data.dai_node_id = intel_alh_id;
+ ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags);
if (ret < 0) {
dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_params failed %d\n", __func__, ret);
return ret;
@@ -457,9 +497,25 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
if (!hext_stream)
return -ENODEV;
- /* in the case of SoundWire we need to program the PCMSyCM registers */
+ /*
+ * in the case of SoundWire we need to program the PCMSyCM registers. In case
+ * of aggregated devices, we need to define the channel mask for each sublink
+ * by reconstructing the split done in soc-pcm.c
+ */
+ for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) {
+ if (dai == cpu_dai) {
+ cpu_dai_found = true;
+ break;
+ }
+ }
+
+ if (!cpu_dai_found)
+ return -ENODEV;
+
+ ch_mask = GENMASK(params_channels(params) - 1, 0);
+
ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id,
- GENMASK(params_channels(params) - 1, 0),
+ ch_mask,
hdac_stream(hext_stream)->stream_tag,
substream->stream);
if (ret < 0) {
@@ -468,6 +524,22 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
return ret;
}
+ ipc4_copier = widget_to_copier(w);
+ dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id];
+ dma_config = &dma_config_tlv->dma_config;
+ dma_config->dma_stream_channel_map.mapping[0].device = data.dai_index;
+ dma_config->dma_stream_channel_map.mapping[0].channel_mask = ch_mask;
+
+ /*
+ * copy the dma_config_tlv to all ipc4_copier in the same link. Because only one copier
+ * will be handled in sof_ipc4_prepare_copier_module.
+ */
+ for_each_rtd_cpu_dais(rtd, i, dai) {
+ w = snd_soc_dai_get_widget(dai, substream->stream);
+ ipc4_copier = widget_to_copier(w);
+ memcpy(&ipc4_copier->dma_config_tlv[cpu_dai_id], dma_config_tlv,
+ sizeof(*dma_config_tlv));
+ }
return 0;
}
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index 31ffa1a8f2ac..ef5c915db8ff 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -681,17 +681,27 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc;
struct hdac_bus *bus = sof_to_bus(sdev);
+ bool imr_lost = false;
int ret, j;
/*
- * The memory used for IMR boot loses its content in deeper than S3 state
- * We must not try IMR boot on next power up (as it will fail).
- *
+ * The memory used for IMR boot loses its content in deeper than S3
+ * state on CAVS platforms.
+ * On ACE platforms due to the system architecture the IMR content is
+ * lost at S3 state already, they are tailored for s2idle use.
+ * We must not try IMR boot on next power up in these cases as it will
+ * fail.
+ */
+ if (sdev->system_suspend_target > SOF_SUSPEND_S3 ||
+ (chip->hw_ip_version >= SOF_INTEL_ACE_1_0 &&
+ sdev->system_suspend_target == SOF_SUSPEND_S3))
+ imr_lost = true;
+
+ /*
* In case of firmware crash or boot failure set the skip_imr_boot to true
* as well in order to try to re-load the firmware to do a 'cold' boot.
*/
- if (sdev->system_suspend_target > SOF_SUSPEND_S3 ||
- sdev->fw_state == SOF_FW_CRASHED ||
+ if (imr_lost || sdev->fw_state == SOF_FW_CRASHED ||
sdev->fw_state == SOF_FW_BOOT_FAILED)
hda->skip_imr_boot = true;
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index b81f231abee3..d5b9209beb5a 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -15,6 +15,7 @@
* Hardware interface for HDA DSP code loader
*/
+#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <sound/hdaudio_ext.h>
#include <sound/hda_register.h>
@@ -643,8 +644,12 @@ int hda_dsp_post_fw_run(struct snd_sof_dev *sdev)
/* Check if IMR boot is usable */
if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT) &&
(sdev->fw_ready.flags & SOF_IPC_INFO_D3_PERSISTENT ||
- sdev->pdata->ipc_type == SOF_IPC_TYPE_4))
+ sdev->pdata->ipc_type == SOF_IPC_TYPE_4)) {
hdev->imrboot_supported = true;
+ debugfs_create_bool("skip_imr_boot",
+ 0644, sdev->debugfs_root,
+ &hdev->skip_imr_boot);
+ }
}
hda_sdw_int_enable(sdev, true);
diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
index 18f07364d219..d7b446f3f973 100644
--- a/sound/soc/sof/intel/hda-pcm.c
+++ b/sound/soc/sof/intel/hda-pcm.c
@@ -259,8 +259,37 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT,
SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32);
+ /*
+ * The dsp_max_burst_size_in_ms is the length of the maximum burst size
+ * of the host DMA in the ALSA buffer.
+ *
+ * On playback start the DMA will transfer dsp_max_burst_size_in_ms
+ * amount of data in one initial burst to fill up the host DMA buffer.
+ * Consequent DMA burst sizes are shorter and their length can vary.
+ * To make sure that userspace allocate large enough ALSA buffer we need
+ * to place a constraint on the buffer time.
+ *
+ * On capture the DMA will transfer 1ms chunks.
+ *
+ * Exact dsp_max_burst_size_in_ms constraint is racy, so set the
+ * constraint to a minimum of 2x dsp_max_burst_size_in_ms.
+ */
+ if (spcm->stream[direction].dsp_max_burst_size_in_ms)
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_BUFFER_TIME,
+ spcm->stream[direction].dsp_max_burst_size_in_ms * USEC_PER_MSEC * 2,
+ UINT_MAX);
+
/* binding pcm substream to hda stream */
substream->runtime->private_data = &dsp_stream->hstream;
+
+ /*
+ * Reset the llp cache values (they are used for LLP compensation in
+ * case the counter is not reset)
+ */
+ dsp_stream->pplcllpl = 0;
+ dsp_stream->pplcllpu = 0;
+
return 0;
}
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index b387b1a69d7e..0c189d3b19c1 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -1063,3 +1063,73 @@ snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
return pos;
}
+
+#define merge_u64(u32_u, u32_l) (((u64)(u32_u) << 32) | (u32_l))
+
+/**
+ * hda_dsp_get_stream_llp - Retrieve the LLP (Linear Link Position) of the stream
+ * @sdev: SOF device
+ * @component: ASoC component
+ * @substream: PCM substream
+ *
+ * Returns the raw Linear Link Position value
+ */
+u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
+ struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct hdac_stream *hstream = substream->runtime->private_data;
+ struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
+ u32 llp_l, llp_u;
+
+ /*
+ * The pplc_addr have been calculated during probe in
+ * hda_dsp_stream_init():
+ * pplc_addr = sdev->bar[HDA_DSP_PP_BAR] +
+ * SOF_HDA_PPLC_BASE +
+ * SOF_HDA_PPLC_MULTI * total_stream +
+ * SOF_HDA_PPLC_INTERVAL * stream_index
+ *
+ * Use this pre-calculated address to avoid repeated re-calculation.
+ */
+ llp_l = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL);
+ llp_u = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU);
+
+ /* Compensate the LLP counter with the saved offset */
+ if (hext_stream->pplcllpl || hext_stream->pplcllpu)
+ return merge_u64(llp_u, llp_l) -
+ merge_u64(hext_stream->pplcllpu, hext_stream->pplcllpl);
+
+ return merge_u64(llp_u, llp_l);
+}
+
+/**
+ * hda_dsp_get_stream_ldp - Retrieve the LDP (Linear DMA Position) of the stream
+ * @sdev: SOF device
+ * @component: ASoC component
+ * @substream: PCM substream
+ *
+ * Returns the raw Linear Link Position value
+ */
+u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev,
+ struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct hdac_stream *hstream = substream->runtime->private_data;
+ struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
+ u32 ldp_l, ldp_u;
+
+ /*
+ * The pphc_addr have been calculated during probe in
+ * hda_dsp_stream_init():
+ * pphc_addr = sdev->bar[HDA_DSP_PP_BAR] +
+ * SOF_HDA_PPHC_BASE +
+ * SOF_HDA_PPHC_INTERVAL * stream_index
+ *
+ * Use this pre-calculated address to avoid repeated re-calculation.
+ */
+ ldp_l = readl(hext_stream->pphc_addr + AZX_REG_PPHCLDPL);
+ ldp_u = readl(hext_stream->pphc_addr + AZX_REG_PPHCLDPU);
+
+ return ((u64)ldp_u << 32) | ldp_l;
+}
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 7fe72b065451..2fc10bec7331 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -19,19 +19,23 @@
#include <sound/hda_register.h>
#include <linux/acpi.h>
+#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_intel.h>
#include <sound/intel-dsp-config.h>
#include <sound/intel-nhlt.h>
+#include <sound/soc-acpi-intel-ssp-common.h>
#include <sound/sof.h>
#include <sound/sof/xtensa.h>
#include <sound/hda-mlink.h>
#include "../sof-audio.h"
#include "../sof-pci-dev.h"
#include "../ops.h"
+#include "../ipc4-topology.h"
#include "hda.h"
#include "telemetry.h"
+#include "mtl.h"
#define CREATE_TRACE_POINTS
#include <trace/events/sof_intel.h>
@@ -144,12 +148,37 @@ static int sdw_params_stream(struct device *dev,
data.dai_index = (params_data->link_id << 8) | d->id;
data.dai_data = params_data->alh_stream_id;
+ data.dai_node_id = data.dai_data;
return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_PARAMS, &data);
}
+static int sdw_params_free(struct device *dev, struct sdw_intel_stream_free_data *free_data)
+{
+ struct snd_soc_dai *d = free_data->dai;
+ struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(d, free_data->substream->stream);
+ struct snd_sof_dev *sdev = widget_to_sdev(w);
+
+ if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
+ struct snd_sof_widget *swidget = w->dobj.private;
+ struct snd_sof_dai *dai = swidget->private;
+ struct sof_ipc4_copier_data *copier_data;
+ struct sof_ipc4_copier *ipc4_copier;
+
+ ipc4_copier = dai->private;
+ ipc4_copier->dai_index = 0;
+ copier_data = &ipc4_copier->data;
+
+ /* clear the node ID */
+ copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
+ }
+
+ return 0;
+}
+
struct sdw_intel_ops sdw_callback = {
.params_stream = sdw_params_stream,
+ .free_stream = sdw_params_free,
};
static int sdw_ace2x_params_stream(struct device *dev,
@@ -158,7 +187,8 @@ static int sdw_ace2x_params_stream(struct device *dev,
return sdw_hda_dai_hw_params(params_data->substream,
params_data->hw_params,
params_data->dai,
- params_data->link_id);
+ params_data->link_id,
+ params_data->alh_stream_id);
}
static int sdw_ace2x_free_stream(struct device *dev,
@@ -568,7 +598,7 @@ static const struct hda_dsp_msg_code hda_dsp_rom_fw_error_texts[] = {
};
#define FSR_ROM_STATE_ENTRY(state) {FSR_STATE_ROM_##state, #state}
-static const struct hda_dsp_msg_code fsr_rom_state_names[] = {
+static const struct hda_dsp_msg_code cavs_fsr_rom_state_names[] = {
FSR_ROM_STATE_ENTRY(INIT),
FSR_ROM_STATE_ENTRY(INIT_DONE),
FSR_ROM_STATE_ENTRY(CSE_MANIFEST_LOADED),
@@ -591,6 +621,58 @@ static const struct hda_dsp_msg_code fsr_rom_state_names[] = {
FSR_ROM_STATE_ENTRY(CSE_IPC_DOWN),
};
+static const struct hda_dsp_msg_code ace_fsr_rom_state_names[] = {
+ FSR_ROM_STATE_ENTRY(INIT),
+ FSR_ROM_STATE_ENTRY(INIT_DONE),
+ FSR_ROM_STATE_ENTRY(CSE_MANIFEST_LOADED),
+ FSR_ROM_STATE_ENTRY(FW_MANIFEST_LOADED),
+ FSR_ROM_STATE_ENTRY(FW_FW_LOADED),
+ FSR_ROM_STATE_ENTRY(FW_ENTERED),
+ FSR_ROM_STATE_ENTRY(VERIFY_FEATURE_MASK),
+ FSR_ROM_STATE_ENTRY(GET_LOAD_OFFSET),
+ FSR_ROM_STATE_ENTRY(RESET_VECTOR_DONE),
+ FSR_ROM_STATE_ENTRY(PURGE_BOOT),
+ FSR_ROM_STATE_ENTRY(RESTORE_BOOT),
+ FSR_ROM_STATE_ENTRY(FW_ENTRY_POINT),
+ FSR_ROM_STATE_ENTRY(VALIDATE_PUB_KEY),
+ FSR_ROM_STATE_ENTRY(POWER_DOWN_HPSRAM),
+ FSR_ROM_STATE_ENTRY(POWER_DOWN_ULPSRAM),
+ FSR_ROM_STATE_ENTRY(POWER_UP_ULPSRAM_STACK),
+ FSR_ROM_STATE_ENTRY(POWER_UP_HPSRAM_DMA),
+ FSR_ROM_STATE_ENTRY(BEFORE_EP_POINTER_READ),
+ FSR_ROM_STATE_ENTRY(VALIDATE_MANIFEST),
+ FSR_ROM_STATE_ENTRY(VALIDATE_FW_MODULE),
+ FSR_ROM_STATE_ENTRY(PROTECT_IMR_REGION),
+ FSR_ROM_STATE_ENTRY(PUSH_MODEL_ROUTINE),
+ FSR_ROM_STATE_ENTRY(PULL_MODEL_ROUTINE),
+ FSR_ROM_STATE_ENTRY(VALIDATE_PKG_DIR),
+ FSR_ROM_STATE_ENTRY(VALIDATE_CPD),
+ FSR_ROM_STATE_ENTRY(VALIDATE_CSS_MAN_HEADER),
+ FSR_ROM_STATE_ENTRY(VALIDATE_BLOB_SVN),
+ FSR_ROM_STATE_ENTRY(VERIFY_IFWI_PARTITION),
+ FSR_ROM_STATE_ENTRY(REMOVE_ACCESS_CONTROL),
+ FSR_ROM_STATE_ENTRY(AUTH_BYPASS),
+ FSR_ROM_STATE_ENTRY(AUTH_ENABLED),
+ FSR_ROM_STATE_ENTRY(INIT_DMA),
+ FSR_ROM_STATE_ENTRY(PURGE_FW_ENTRY),
+ FSR_ROM_STATE_ENTRY(PURGE_FW_END),
+ FSR_ROM_STATE_ENTRY(CLEAN_UP_BSS_DONE),
+ FSR_ROM_STATE_ENTRY(IMR_RESTORE_ENTRY),
+ FSR_ROM_STATE_ENTRY(IMR_RESTORE_END),
+ FSR_ROM_STATE_ENTRY(FW_MANIFEST_IN_DMA_BUFF),
+ FSR_ROM_STATE_ENTRY(LOAD_CSE_MAN_TO_IMR),
+ FSR_ROM_STATE_ENTRY(LOAD_FW_MAN_TO_IMR),
+ FSR_ROM_STATE_ENTRY(LOAD_FW_CODE_TO_IMR),
+ FSR_ROM_STATE_ENTRY(FW_LOADING_DONE),
+ FSR_ROM_STATE_ENTRY(FW_CODE_LOADED),
+ FSR_ROM_STATE_ENTRY(VERIFY_IMAGE_TYPE),
+ FSR_ROM_STATE_ENTRY(AUTH_API_INIT),
+ FSR_ROM_STATE_ENTRY(AUTH_API_PROC),
+ FSR_ROM_STATE_ENTRY(AUTH_API_FIRST_BUSY),
+ FSR_ROM_STATE_ENTRY(AUTH_API_FIRST_RESULT),
+ FSR_ROM_STATE_ENTRY(AUTH_API_CLEANUP),
+};
+
#define FSR_BRINGUP_STATE_ENTRY(state) {FSR_STATE_BRINGUP_##state, #state}
static const struct hda_dsp_msg_code fsr_bringup_state_names[] = {
FSR_BRINGUP_STATE_ENTRY(INIT),
@@ -635,7 +717,7 @@ hda_dsp_get_state_text(u32 code, const struct hda_dsp_msg_code *msg_code,
return NULL;
}
-static void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level)
+void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level)
{
const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata);
const char *state_text, *error_text, *module_text;
@@ -651,12 +733,19 @@ static void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level)
else
module_text = fsr_module_names[module];
- if (module == FSR_MOD_BRNGUP)
+ if (module == FSR_MOD_BRNGUP) {
state_text = hda_dsp_get_state_text(state, fsr_bringup_state_names,
ARRAY_SIZE(fsr_bringup_state_names));
- else
- state_text = hda_dsp_get_state_text(state, fsr_rom_state_names,
- ARRAY_SIZE(fsr_rom_state_names));
+ } else {
+ if (chip->hw_ip_version < SOF_INTEL_ACE_1_0)
+ state_text = hda_dsp_get_state_text(state,
+ cavs_fsr_rom_state_names,
+ ARRAY_SIZE(cavs_fsr_rom_state_names));
+ else
+ state_text = hda_dsp_get_state_text(state,
+ ace_fsr_rom_state_names,
+ ARRAY_SIZE(ace_fsr_rom_state_names));
+ }
/* not for us, must be generic sof message */
if (!state_text) {
@@ -1676,13 +1765,36 @@ void hda_set_mach_params(struct snd_soc_acpi_mach *mach,
mach_params->dai_drivers = desc->ops->drv;
}
+static int check_tplg_quirk_mask(struct snd_soc_acpi_mach *mach)
+{
+ u32 dmic_ssp_quirk;
+ u32 codec_amp_name_quirk;
+
+ /*
+ * In current implementation dmic and ssp quirks are designed for es8336
+ * machine driver and could not be mixed with codec name and amp name
+ * quirks.
+ */
+ dmic_ssp_quirk = mach->tplg_quirk_mask &
+ (SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER | SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER);
+ codec_amp_name_quirk = mach->tplg_quirk_mask &
+ (SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME);
+
+ if (dmic_ssp_quirk && codec_amp_name_quirk)
+ return -EINVAL;
+
+ return 0;
+}
+
struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
{
u32 interface_mask = hda_get_interface_mask(sdev);
struct snd_sof_pdata *sof_pdata = sdev->pdata;
const struct sof_dev_desc *desc = sof_pdata->desc;
struct snd_soc_acpi_mach *mach = NULL;
+ enum snd_soc_acpi_intel_codec codec_type;
const char *tplg_filename;
+ const char *tplg_suffix;
/* Try I2S or DMIC if it is supported */
if (interface_mask & (BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC)))
@@ -1701,6 +1813,17 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
tplg_fixup = true;
}
+ /*
+ * Checking quirk mask integrity; some quirk flags could not be
+ * set concurrently.
+ */
+ if (tplg_fixup &&
+ check_tplg_quirk_mask(mach)) {
+ dev_err(sdev->dev, "Invalid tplg quirk mask 0x%x\n",
+ mach->tplg_quirk_mask);
+ return NULL;
+ }
+
/* report to machine driver if any DMICs are found */
mach->mach_params.dmic_num = check_dmic_num(sdev);
@@ -1775,6 +1898,52 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
}
}
+ codec_type = snd_soc_acpi_intel_detect_amp_type(sdev->dev);
+
+ if (tplg_fixup &&
+ mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_AMP_NAME &&
+ codec_type != CODEC_NONE) {
+ tplg_suffix = snd_soc_acpi_intel_get_amp_tplg_suffix(codec_type);
+ if (!tplg_suffix) {
+ dev_err(sdev->dev, "no tplg suffix found, amp %d\n",
+ codec_type);
+ return NULL;
+ }
+
+ tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
+ "%s-%s",
+ sof_pdata->tplg_filename,
+ tplg_suffix);
+ if (!tplg_filename)
+ return NULL;
+
+ sof_pdata->tplg_filename = tplg_filename;
+ add_extension = true;
+ }
+
+ codec_type = snd_soc_acpi_intel_detect_codec_type(sdev->dev);
+
+ if (tplg_fixup &&
+ mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME &&
+ codec_type != CODEC_NONE) {
+ tplg_suffix = snd_soc_acpi_intel_get_codec_tplg_suffix(codec_type);
+ if (!tplg_suffix) {
+ dev_err(sdev->dev, "no tplg suffix found, codec %d\n",
+ codec_type);
+ return NULL;
+ }
+
+ tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
+ "%s-%s",
+ sof_pdata->tplg_filename,
+ tplg_suffix);
+ if (!tplg_filename)
+ return NULL;
+
+ sof_pdata->tplg_filename = tplg_filename;
+ add_extension = true;
+ }
+
if (tplg_fixup && add_extension) {
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s%s",
@@ -1842,3 +2011,4 @@ MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI);
MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT);
MODULE_IMPORT_NS(SOUNDWIRE_INTEL);
MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK);
+MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH);
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index b36eb7c78913..16140ae22c90 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -662,6 +662,12 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev);
snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
int direction, bool can_sleep);
+u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
+ struct snd_soc_component *component,
+ struct snd_pcm_substream *substream);
+u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev,
+ struct snd_soc_component *component,
+ struct snd_pcm_substream *substream);
struct hdac_ext_stream *
hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags);
@@ -689,6 +695,8 @@ int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id);
irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context);
int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir);
+void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level);
+
/*
* DSP Code loader.
*/
@@ -844,7 +852,8 @@ static inline bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev)
int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai,
- int link_id);
+ int link_id,
+ int intel_alh_id);
int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai,
@@ -999,4 +1008,12 @@ int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream,
struct snd_soc_dai *cpu_dai);
+static inline struct snd_sof_dev *widget_to_sdev(struct snd_soc_dapm_widget *w)
+{
+ struct snd_sof_widget *swidget = w->dobj.private;
+ struct snd_soc_component *component = swidget->scomp;
+
+ return snd_soc_component_get_drvdata(component);
+}
+
#endif
diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c
index 7ae017a00184..8e7193344341 100644
--- a/sound/soc/sof/intel/lnl.c
+++ b/sound/soc/sof/intel/lnl.c
@@ -6,6 +6,7 @@
* Hardware interface for audio DSP on LunarLake.
*/
+#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <sound/hda_register.h>
#include <sound/sof/ipc4/header.h>
@@ -16,6 +17,7 @@
#include "hda-ipc.h"
#include "../sof-audio.h"
#include "mtl.h"
+#include "lnl.h"
#include <sound/hda-mlink.h>
/* LunarLake ops */
@@ -83,8 +85,12 @@ static int lnl_dsp_post_fw_run(struct snd_sof_dev *sdev)
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
/* Check if IMR boot is usable */
- if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT))
+ if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) {
hda->imrboot_supported = true;
+ debugfs_create_bool("skip_imr_boot",
+ 0644, sdev->debugfs_root,
+ &hda->skip_imr_boot);
+ }
}
return 0;
@@ -134,8 +140,6 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev)
sof_lnl_ops.runtime_resume = lnl_hda_dsp_runtime_resume;
}
- sof_lnl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position;
-
/* dsp core get/put */
sof_lnl_ops.core_get = mtl_dsp_core_get;
sof_lnl_ops.core_put = mtl_dsp_core_put;
@@ -194,7 +198,7 @@ const struct sof_intel_dsp_desc lnl_chip_info = {
.ipc_ack = MTL_DSP_REG_HFIPCXIDA,
.ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
.ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
- .rom_status_reg = MTL_DSP_ROM_STS,
+ .rom_status_reg = LNL_DSP_REG_HFDSC,
.rom_init_timeout = 300,
.ssp_count = MTL_SSP_COUNT,
.d0i3_offset = MTL_HDA_VS_D0I3C,
diff --git a/sound/soc/sof/intel/lnl.h b/sound/soc/sof/intel/lnl.h
new file mode 100644
index 000000000000..4f4734fe7e08
--- /dev/null
+++ b/sound/soc/sof/intel/lnl.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Copyright(c) 2024 Intel Corporation. All rights reserved.
+ */
+
+#ifndef __SOF_INTEL_LNL_H
+#define __SOF_INTEL_LNL_H
+
+#define LNL_DSP_REG_HFDSC 0x160200 /* DSP core0 status */
+#define LNL_DSP_REG_HFDEC 0x160204 /* DSP core0 error */
+
+#endif /* __SOF_INTEL_LNL_H */
diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c
index df05dc77b8d5..dc203505536c 100644
--- a/sound/soc/sof/intel/mtl.c
+++ b/sound/soc/sof/intel/mtl.c
@@ -9,6 +9,7 @@
* Hardware interface for audio DSP on Meteorlake.
*/
+#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <sound/sof/ipc4/header.h>
#include <trace/events/sof_intel.h>
@@ -294,8 +295,12 @@ int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev)
}
/* Check if IMR boot is usable */
- if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT))
+ if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) {
hdev->imrboot_supported = true;
+ debugfs_create_bool("skip_imr_boot",
+ 0644, sdev->debugfs_root,
+ &hdev->skip_imr_boot);
+ }
}
hda_sdw_int_enable(sdev, true);
@@ -305,22 +310,16 @@ int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev)
void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
{
char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR;
- u32 romdbgsts;
- u32 romdbgerr;
u32 fwsts;
u32 fwlec;
+ hda_dsp_get_state(sdev, level);
fwsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_STS);
fwlec = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_ERROR);
- romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY);
- romdbgerr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY_ERROR);
- dev_err(sdev->dev, "ROM status: %#x, ROM error: %#x\n", fwsts, fwlec);
- dev_err(sdev->dev, "ROM debug status: %#x, ROM debug error: %#x\n", romdbgsts,
- romdbgerr);
- romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY + 0x8 * 3);
- dev_printk(level, sdev->dev, "ROM feature bit%s enabled\n",
- romdbgsts & BIT(24) ? "" : " not");
+ if (fwsts != 0xffffffff)
+ dev_err(sdev->dev, "Firmware state: %#x, status/error code: %#x\n",
+ fwsts, fwlec);
sof_ipc4_intel_dump_telemetry_state(sdev, flags);
}
@@ -439,7 +438,7 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
{
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc;
- unsigned int status;
+ unsigned int status, target_status;
u32 ipc_hdr, flags;
char *dump_msg;
int ret;
@@ -485,13 +484,40 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
mtl_enable_ipc_interrupts(sdev);
+ if (chip->rom_status_reg == MTL_DSP_ROM_STS) {
+ /*
+ * Workaround: when the ROM status register is pointing to
+ * the SRAM window (MTL_DSP_ROM_STS) the platform cannot catch
+ * ROM_INIT_DONE because of a very short timing window.
+ * Follow the recommendations and skip target state waiting.
+ */
+ return 0;
+ }
+
/*
- * ACE workaround: don't wait for ROM INIT.
- * The platform cannot catch ROM_INIT_DONE because of a very short
- * timing window. Follow the recommendations and skip this part.
+ * step 7:
+ * - Cold/Full boot: wait for ROM init to proceed to download the firmware
+ * - IMR boot: wait for ROM firmware entered (firmware booted up from IMR)
*/
+ if (imr_boot)
+ target_status = FSR_STATE_FW_ENTERED;
+ else
+ target_status = FSR_STATE_INIT_DONE;
- return 0;
+ ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
+ chip->rom_status_reg, status,
+ (FSR_TO_STATE_CODE(status) == target_status),
+ HDA_DSP_REG_POLL_INTERVAL_US,
+ chip->rom_init_timeout *
+ USEC_PER_MSEC);
+
+ if (!ret)
+ return 0;
+
+ if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
+ dev_err(sdev->dev,
+ "%s: timeout with rom_status_reg (%#x) read\n",
+ __func__, chip->rom_status_reg);
err:
flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX | SOF_DBG_DUMP_OPTIONAL;
@@ -503,6 +529,7 @@ err:
dump_msg = kasprintf(GFP_KERNEL, "Boot iteration failed: %d/%d",
hda->boot_iteration, HDA_FW_BOOT_ATTEMPTS);
snd_sof_dsp_dbg_dump(sdev, dump_msg, flags);
+ mtl_enable_interrupts(sdev, false);
mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE);
kfree(dump_msg);
@@ -626,18 +653,6 @@ static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
return mtl_enable_interrupts(sdev, false);
}
-u64 mtl_dsp_get_stream_hda_link_position(struct snd_sof_dev *sdev,
- struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct hdac_stream *hstream = substream->runtime->private_data;
- u32 llp_l, llp_u;
-
- llp_l = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, MTL_PPLCLLPL(hstream->index));
- llp_u = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, MTL_PPLCLLPU(hstream->index));
- return ((u64)llp_u << 32) | llp_l;
-}
-
int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core)
{
const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm;
@@ -707,8 +722,6 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev)
sof_mtl_ops.core_get = mtl_dsp_core_get;
sof_mtl_ops.core_put = mtl_dsp_core_put;
- sof_mtl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position;
-
sdev->private = kzalloc(sizeof(struct sof_ipc4_fw_data), GFP_KERNEL);
if (!sdev->private)
return -ENOMEM;
@@ -741,7 +754,7 @@ const struct sof_intel_dsp_desc mtl_chip_info = {
.ipc_ack = MTL_DSP_REG_HFIPCXIDA,
.ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
.ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
- .rom_status_reg = MTL_DSP_ROM_STS,
+ .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY,
.rom_init_timeout = 300,
.ssp_count = MTL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
@@ -769,7 +782,7 @@ const struct sof_intel_dsp_desc arl_s_chip_info = {
.ipc_ack = MTL_DSP_REG_HFIPCXIDA,
.ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
.ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
- .rom_status_reg = MTL_DSP_ROM_STS,
+ .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY,
.rom_init_timeout = 300,
.ssp_count = MTL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h
index cc5a1f46fd09..d2d709fb4f06 100644
--- a/sound/soc/sof/intel/mtl.h
+++ b/sound/soc/sof/intel/mtl.h
@@ -6,12 +6,6 @@
* Copyright(c) 2020-2022 Intel Corporation. All rights reserved.
*/
-/* HDA Registers */
-#define MTL_PPLCLLPL_BASE 0x948
-#define MTL_PPLCLLPU_STRIDE 0x10
-#define MTL_PPLCLLPL(x) (MTL_PPLCLLPL_BASE + (x) * MTL_PPLCLLPU_STRIDE)
-#define MTL_PPLCLLPU(x) (MTL_PPLCLLPL_BASE + 0x4 + (x) * MTL_PPLCLLPU_STRIDE)
-
/* DSP Registers */
#define MTL_HFDSSCS 0x1000
#define MTL_HFDSSCS_SPA_MASK BIT(16)
@@ -76,8 +70,52 @@
#define MTL_DSP_ROM_STS MTL_SRAM_WINDOW_OFFSET(0) /* ROM status */
#define MTL_DSP_ROM_ERROR (MTL_SRAM_WINDOW_OFFSET(0) + 0x4) /* ROM error code */
-#define MTL_DSP_REG_HFFLGPXQWY 0x163200 /* ROM debug status */
-#define MTL_DSP_REG_HFFLGPXQWY_ERROR 0x163204 /* ROM debug error code */
+#define MTL_DSP_REG_HFFLGPXQWY 0x163200 /* DSP core0 status */
+#define MTL_DSP_REG_HFFLGPXQWY_ERROR 0x163204 /* DSP core0 error */
+
+/* FSR status codes */
+#define FSR_STATE_ROM_RESET_VECTOR_DONE 0x8
+#define FSR_STATE_ROM_PURGE_BOOT 0x9
+#define FSR_STATE_ROM_RESTORE_BOOT 0xA
+#define FSR_STATE_ROM_FW_ENTRY_POINT 0xB
+#define FSR_STATE_ROM_VALIDATE_PUB_KEY 0xC
+#define FSR_STATE_ROM_POWER_DOWN_HPSRAM 0xD
+#define FSR_STATE_ROM_POWER_DOWN_ULPSRAM 0xE
+#define FSR_STATE_ROM_POWER_UP_ULPSRAM_STACK 0xF
+#define FSR_STATE_ROM_POWER_UP_HPSRAM_DMA 0x10
+#define FSR_STATE_ROM_BEFORE_EP_POINTER_READ 0x11
+#define FSR_STATE_ROM_VALIDATE_MANIFEST 0x12
+#define FSR_STATE_ROM_VALIDATE_FW_MODULE 0x13
+#define FSR_STATE_ROM_PROTECT_IMR_REGION 0x14
+#define FSR_STATE_ROM_PUSH_MODEL_ROUTINE 0x15
+#define FSR_STATE_ROM_PULL_MODEL_ROUTINE 0x16
+#define FSR_STATE_ROM_VALIDATE_PKG_DIR 0x17
+#define FSR_STATE_ROM_VALIDATE_CPD 0x18
+#define FSR_STATE_ROM_VALIDATE_CSS_MAN_HEADER 0x19
+#define FSR_STATE_ROM_VALIDATE_BLOB_SVN 0x1A
+#define FSR_STATE_ROM_VERIFY_IFWI_PARTITION 0x1B
+#define FSR_STATE_ROM_REMOVE_ACCESS_CONTROL 0x1C
+#define FSR_STATE_ROM_AUTH_BYPASS 0x1D
+#define FSR_STATE_ROM_AUTH_ENABLED 0x1E
+#define FSR_STATE_ROM_INIT_DMA 0x1F
+#define FSR_STATE_ROM_PURGE_FW_ENTRY 0x20
+#define FSR_STATE_ROM_PURGE_FW_END 0x21
+#define FSR_STATE_ROM_CLEAN_UP_BSS_DONE 0x22
+#define FSR_STATE_ROM_IMR_RESTORE_ENTRY 0x23
+#define FSR_STATE_ROM_IMR_RESTORE_END 0x24
+#define FSR_STATE_ROM_FW_MANIFEST_IN_DMA_BUFF 0x25
+#define FSR_STATE_ROM_LOAD_CSE_MAN_TO_IMR 0x26
+#define FSR_STATE_ROM_LOAD_FW_MAN_TO_IMR 0x27
+#define FSR_STATE_ROM_LOAD_FW_CODE_TO_IMR 0x28
+#define FSR_STATE_ROM_FW_LOADING_DONE 0x29
+#define FSR_STATE_ROM_FW_CODE_LOADED 0x2A
+#define FSR_STATE_ROM_VERIFY_IMAGE_TYPE 0x2B
+#define FSR_STATE_ROM_AUTH_API_INIT 0x2C
+#define FSR_STATE_ROM_AUTH_API_PROC 0x2D
+#define FSR_STATE_ROM_AUTH_API_FIRST_BUSY 0x2E
+#define FSR_STATE_ROM_AUTH_API_FIRST_RESULT 0x2F
+#define FSR_STATE_ROM_AUTH_API_CLEANUP 0x30
+
#define MTL_DSP_REG_HfIMRIS1 0x162088
#define MTL_DSP_REG_HfIMRIS1_IU_MASK BIT(0)
@@ -103,9 +141,5 @@ int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id);
void mtl_ipc_dump(struct snd_sof_dev *sdev);
-u64 mtl_dsp_get_stream_hda_link_position(struct snd_sof_dev *sdev,
- struct snd_soc_component *component,
- struct snd_pcm_substream *substream);
-
int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core);
int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core);
diff --git a/sound/soc/sof/ipc4-loader.c b/sound/soc/sof/ipc4-loader.c
index c79479afa8d0..641c4f24cca9 100644
--- a/sound/soc/sof/ipc4-loader.c
+++ b/sound/soc/sof/ipc4-loader.c
@@ -80,6 +80,14 @@ static ssize_t sof_ipc4_fw_parse_ext_man(struct snd_sof_dev *sdev,
dev_dbg(sdev->dev, "Header length: %u, module count: %u\n",
fw_header->len, fw_header->num_module_entries);
+ /* copy the fw_version of basefw into debugfs at first boot */
+ if (fw == sdev->basefw.fw) {
+ sdev->fw_version.major = fw_header->major_version;
+ sdev->fw_version.minor = fw_header->minor_version;
+ sdev->fw_version.micro = fw_header->hotfix_version;
+ sdev->fw_version.build = fw_header->build_version;
+ }
+
fw_lib->modules = devm_kmalloc_array(sdev->dev, fw_header->num_module_entries,
sizeof(*fw_module), GFP_KERNEL);
if (!fw_lib->modules)
diff --git a/sound/soc/sof/ipc4-mtrace.c b/sound/soc/sof/ipc4-mtrace.c
index 9f1e33ee8826..0e04bea9432d 100644
--- a/sound/soc/sof/ipc4-mtrace.c
+++ b/sound/soc/sof/ipc4-mtrace.c
@@ -4,6 +4,7 @@
#include <linux/debugfs.h>
#include <linux/sched/signal.h>
+#include <linux/sched/clock.h>
#include <sound/sof/ipc4/header.h>
#include "sof-priv.h"
#include "ipc4-priv.h"
@@ -412,7 +413,6 @@ static int ipc4_mtrace_enable(struct snd_sof_dev *sdev)
const struct sof_ipc_ops *iops = sdev->ipc->ops;
struct sof_ipc4_msg msg;
u64 system_time;
- ktime_t kt;
int ret;
if (priv->mtrace_state != SOF_MTRACE_DISABLED)
@@ -424,9 +424,12 @@ static int ipc4_mtrace_enable(struct snd_sof_dev *sdev)
msg.primary |= SOF_IPC4_MOD_INSTANCE(SOF_IPC4_MOD_INIT_BASEFW_INSTANCE_ID);
msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_FW_PARAM_SYSTEM_TIME);
- /* The system time is in usec, UTC, epoch is 1601-01-01 00:00:00 */
- kt = ktime_add_us(ktime_get_real(), FW_EPOCH_DELTA * USEC_PER_SEC);
- system_time = ktime_to_us(kt);
+ /*
+ * local_clock() is used to align with dmesg, so both kernel and firmware logs have
+ * the same base and a minor delta due to the IPC. system time is in us format but
+ * local_clock() returns the time in ns, so convert to ns.
+ */
+ system_time = div64_u64(local_clock(), NSEC_PER_USEC);
msg.data_size = sizeof(system_time);
msg.data_ptr = &system_time;
ret = iops->set_get_data(sdev, &msg, msg.data_size, true);
diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c
index 0f332c8cdbe6..e915f9f87a6c 100644
--- a/sound/soc/sof/ipc4-pcm.c
+++ b/sound/soc/sof/ipc4-pcm.c
@@ -15,6 +15,28 @@
#include "ipc4-topology.h"
#include "ipc4-fw-reg.h"
+/**
+ * struct sof_ipc4_timestamp_info - IPC4 timestamp info
+ * @host_copier: the host copier of the pcm stream
+ * @dai_copier: the dai copier of the pcm stream
+ * @stream_start_offset: reported by fw in memory window (converted to frames)
+ * @stream_end_offset: reported by fw in memory window (converted to frames)
+ * @llp_offset: llp offset in memory window
+ * @boundary: wrap boundary should be used for the LLP frame counter
+ * @delay: Calculated and stored in pointer callback. The stored value is
+ * returned in the delay callback.
+ */
+struct sof_ipc4_timestamp_info {
+ struct sof_ipc4_copier *host_copier;
+ struct sof_ipc4_copier *dai_copier;
+ u64 stream_start_offset;
+ u64 stream_end_offset;
+ u32 llp_offset;
+
+ u64 boundary;
+ snd_pcm_sframes_t delay;
+};
+
static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state,
struct ipc4_pipeline_set_state_data *trigger_list)
{
@@ -423,8 +445,19 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
}
/* return if this is the final state */
- if (state == SOF_IPC4_PIPE_PAUSED)
+ if (state == SOF_IPC4_PIPE_PAUSED) {
+ struct sof_ipc4_timestamp_info *time_info;
+
+ /*
+ * Invalidate the stream_start_offset to make sure that it is
+ * going to be updated if the stream resumes
+ */
+ time_info = spcm->stream[substream->stream].private;
+ if (time_info)
+ time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION;
+
goto free;
+ }
skip_pause_transition:
/* else set the RUNNING/RESET state in the DSP */
ret = sof_ipc4_set_multi_pipeline_state(sdev, state, trigger_list);
@@ -464,14 +497,12 @@ static int sof_ipc4_pcm_trigger(struct snd_soc_component *component,
/* determine the pipeline state */
switch (cmd) {
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- state = SOF_IPC4_PIPE_PAUSED;
- break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_START:
state = SOF_IPC4_PIPE_RUNNING;
break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
state = SOF_IPC4_PIPE_PAUSED;
@@ -703,6 +734,10 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
if (abi_version < SOF_IPC4_FW_REGS_ABI_VER)
support_info = false;
+ /* For delay reporting the get_host_byte_counter callback is needed */
+ if (!sof_ops(sdev) || !sof_ops(sdev)->get_host_byte_counter)
+ support_info = false;
+
for_each_pcm_streams(stream) {
pipeline_list = &spcm->stream[stream].pipeline_list;
@@ -835,7 +870,6 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
struct sof_ipc4_copier *host_copier = time_info->host_copier;
struct sof_ipc4_copier *dai_copier = time_info->dai_copier;
struct sof_ipc4_pipeline_registers ppl_reg;
- u64 stream_start_position;
u32 dai_sample_size;
u32 ch, node_index;
u32 offset;
@@ -852,38 +886,51 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
if (ppl_reg.stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION)
return -EINVAL;
- stream_start_position = ppl_reg.stream_start_offset;
ch = dai_copier->data.out_format.fmt_cfg;
ch = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(ch);
dai_sample_size = (dai_copier->data.out_format.bit_depth >> 3) * ch;
- /* convert offset to sample count */
- do_div(stream_start_position, dai_sample_size);
- time_info->stream_start_offset = stream_start_position;
+
+ /* convert offsets to frame count */
+ time_info->stream_start_offset = ppl_reg.stream_start_offset;
+ do_div(time_info->stream_start_offset, dai_sample_size);
+ time_info->stream_end_offset = ppl_reg.stream_end_offset;
+ do_div(time_info->stream_end_offset, dai_sample_size);
+
+ /*
+ * Calculate the wrap boundary need to be used for delay calculation
+ * The host counter is in bytes, it will wrap earlier than the frames
+ * based link counter.
+ */
+ time_info->boundary = div64_u64(~((u64)0),
+ frames_to_bytes(substream->runtime, 1));
+ /* Initialize the delay value to 0 (no delay) */
+ time_info->delay = 0;
return 0;
}
-static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
+static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t *pointer)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sof_ipc4_timestamp_info *time_info;
struct sof_ipc4_llp_reading_slot llp;
- snd_pcm_uframes_t head_ptr, tail_ptr;
+ snd_pcm_uframes_t head_cnt, tail_cnt;
struct snd_sof_pcm_stream *stream;
+ u64 dai_cnt, host_cnt, host_ptr;
struct snd_sof_pcm *spcm;
- u64 tmp_ptr;
int ret;
spcm = snd_sof_find_spcm_dai(component, rtd);
if (!spcm)
- return 0;
+ return -EOPNOTSUPP;
stream = &spcm->stream[substream->stream];
time_info = stream->private;
if (!time_info)
- return 0;
+ return -EOPNOTSUPP;
/*
* stream_start_offset is updated to memory window by FW based on
@@ -893,45 +940,116 @@ static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
if (time_info->stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION) {
ret = sof_ipc4_get_stream_start_offset(sdev, substream, stream, time_info);
if (ret < 0)
- return 0;
+ return -EOPNOTSUPP;
}
+ /* For delay calculation we need the host counter */
+ host_cnt = snd_sof_pcm_get_host_byte_counter(sdev, component, substream);
+ host_ptr = host_cnt;
+
+ /* convert the host_cnt to frames */
+ host_cnt = div64_u64(host_cnt, frames_to_bytes(substream->runtime, 1));
+
/*
- * HDaudio links don't support the LLP counter reported by firmware
- * the link position is read directly from hardware registers.
+ * If the LLP counter is not reported by firmware in the SRAM window
+ * then read the dai (link) counter via host accessible means if
+ * available.
*/
if (!time_info->llp_offset) {
- tmp_ptr = snd_sof_pcm_get_stream_position(sdev, component, substream);
- if (!tmp_ptr)
- return 0;
+ dai_cnt = snd_sof_pcm_get_dai_frame_counter(sdev, component, substream);
+ if (!dai_cnt)
+ return -EOPNOTSUPP;
} else {
sof_mailbox_read(sdev, time_info->llp_offset, &llp, sizeof(llp));
- tmp_ptr = ((u64)llp.reading.llp_u << 32) | llp.reading.llp_l;
+ dai_cnt = ((u64)llp.reading.llp_u << 32) | llp.reading.llp_l;
}
+ dai_cnt += time_info->stream_end_offset;
- /* In two cases dai dma position is not accurate
+ /* In two cases dai dma counter is not accurate
* (1) dai pipeline is started before host pipeline
- * (2) multiple streams mixed into one. Each stream has the same dai dma position
+ * (2) multiple streams mixed into one. Each stream has the same dai dma
+ * counter
*
- * Firmware calculates correct stream_start_offset for all cases including above two.
- * Driver subtracts stream_start_offset from dai dma position to get accurate one
+ * Firmware calculates correct stream_start_offset for all cases
+ * including above two.
+ * Driver subtracts stream_start_offset from dai dma counter to get
+ * accurate one
*/
- tmp_ptr -= time_info->stream_start_offset;
- /* Calculate the delay taking into account that both pointer can wrap */
- div64_u64_rem(tmp_ptr, substream->runtime->boundary, &tmp_ptr);
+ /*
+ * On stream start the dai counter might not yet have reached the
+ * stream_start_offset value which means that no frames have left the
+ * DSP yet from the audio stream (on playback, capture streams have
+ * offset of 0 as we start capturing right away).
+ * In this case we need to adjust the distance between the counters by
+ * increasing the host counter by (offset - dai_counter).
+ * Otherwise the dai_counter needs to be adjusted to reflect the number
+ * of valid frames passed on the DAI side.
+ *
+ * The delay is the difference between the counters on the two
+ * sides of the DSP.
+ */
+ if (dai_cnt < time_info->stream_start_offset) {
+ host_cnt += time_info->stream_start_offset - dai_cnt;
+ dai_cnt = 0;
+ } else {
+ dai_cnt -= time_info->stream_start_offset;
+ }
+
+ /* Wrap the dai counter at the boundary where the host counter wraps */
+ div64_u64_rem(dai_cnt, time_info->boundary, &dai_cnt);
+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- head_ptr = substream->runtime->status->hw_ptr;
- tail_ptr = tmp_ptr;
+ head_cnt = host_cnt;
+ tail_cnt = dai_cnt;
} else {
- head_ptr = tmp_ptr;
- tail_ptr = substream->runtime->status->hw_ptr;
+ head_cnt = dai_cnt;
+ tail_cnt = host_cnt;
+ }
+
+ if (head_cnt < tail_cnt) {
+ time_info->delay = time_info->boundary - tail_cnt + head_cnt;
+ goto out;
}
- if (head_ptr < tail_ptr)
- return substream->runtime->boundary - tail_ptr + head_ptr;
+ time_info->delay = head_cnt - tail_cnt;
+
+out:
+ /*
+ * Convert the host byte counter to PCM pointer which wraps in buffer
+ * and it is in frames
+ */
+ div64_u64_rem(host_ptr, snd_pcm_lib_buffer_bytes(substream), &host_ptr);
+ *pointer = bytes_to_frames(substream->runtime, host_ptr);
+
+ return 0;
+}
+
+static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct sof_ipc4_timestamp_info *time_info;
+ struct snd_sof_pcm_stream *stream;
+ struct snd_sof_pcm *spcm;
+
+ spcm = snd_sof_find_spcm_dai(component, rtd);
+ if (!spcm)
+ return 0;
+
+ stream = &spcm->stream[substream->stream];
+ time_info = stream->private;
+ /*
+ * Report the stored delay value calculated in the pointer callback.
+ * In the unlikely event that the calculation was skipped/aborted, the
+ * default 0 delay returned.
+ */
+ if (time_info)
+ return time_info->delay;
+
+ /* No delay information available, report 0 as delay */
+ return 0;
- return head_ptr - tail_ptr;
}
const struct sof_ipc_pcm_ops ipc4_pcm_ops = {
@@ -941,6 +1059,7 @@ const struct sof_ipc_pcm_ops ipc4_pcm_ops = {
.dai_link_fixup = sof_ipc4_pcm_dai_link_fixup,
.pcm_setup = sof_ipc4_pcm_setup,
.pcm_free = sof_ipc4_pcm_free,
+ .pointer = sof_ipc4_pcm_pointer,
.delay = sof_ipc4_pcm_delay,
.ipc_first_on_start = true,
.platform_stop_during_hw_free = true,
diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h
index f3b908b093f9..e157ab80a103 100644
--- a/sound/soc/sof/ipc4-priv.h
+++ b/sound/soc/sof/ipc4-priv.h
@@ -92,27 +92,13 @@ struct sof_ipc4_fw_data {
struct mutex pipeline_state_mutex; /* protect pipeline triggers, ref counts and states */
};
-/**
- * struct sof_ipc4_timestamp_info - IPC4 timestamp info
- * @host_copier: the host copier of the pcm stream
- * @dai_copier: the dai copier of the pcm stream
- * @stream_start_offset: reported by fw in memory window
- * @llp_offset: llp offset in memory window
- */
-struct sof_ipc4_timestamp_info {
- struct sof_ipc4_copier *host_copier;
- struct sof_ipc4_copier *dai_copier;
- u64 stream_start_offset;
- u32 llp_offset;
-};
-
extern const struct sof_ipc_fw_loader_ops ipc4_loader_ops;
extern const struct sof_ipc_tplg_ops ipc4_tplg_ops;
extern const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops;
extern const struct sof_ipc_pcm_ops ipc4_pcm_ops;
extern const struct sof_ipc_fw_tracing_ops ipc4_mtrace_ops;
-int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 id, u32 state);
+int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 instance_id, u32 state);
int sof_ipc4_mtrace_update_pos(struct snd_sof_dev *sdev, int core);
int sof_ipc4_query_fw_configuration(struct snd_sof_dev *sdev);
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index da4a83afb87a..34ec27cf0d94 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -412,8 +412,9 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
struct sof_ipc4_available_audio_format *available_fmt;
struct snd_soc_component *scomp = swidget->scomp;
struct sof_ipc4_copier *ipc4_copier;
+ struct snd_sof_pcm *spcm;
int node_type = 0;
- int ret;
+ int ret, dir;
ipc4_copier = kzalloc(sizeof(*ipc4_copier), GFP_KERNEL);
if (!ipc4_copier)
@@ -447,6 +448,25 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
}
dev_dbg(scomp->dev, "host copier '%s' node_type %u\n", swidget->widget->name, node_type);
+ spcm = snd_sof_find_spcm_comp(scomp, swidget->comp_id, &dir);
+ if (!spcm)
+ goto skip_gtw_cfg;
+
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+ struct snd_sof_pcm_stream *sps = &spcm->stream[dir];
+
+ sof_update_ipc_object(scomp, &sps->dsp_max_burst_size_in_ms,
+ SOF_COPIER_DEEP_BUFFER_TOKENS,
+ swidget->tuples,
+ swidget->num_tuples, sizeof(u32), 1);
+ /* Set default DMA buffer size if it is not specified in topology */
+ if (!sps->dsp_max_burst_size_in_ms)
+ sps->dsp_max_burst_size_in_ms = SOF_IPC4_MIN_DMA_BUFFER_SIZE;
+ } else {
+ /* Capture data is copied from DSP to host in 1ms bursts */
+ spcm->stream[dir].dsp_max_burst_size_in_ms = 1;
+ }
+
skip_gtw_cfg:
ipc4_copier->gtw_attr = kzalloc(sizeof(*ipc4_copier->gtw_attr), GFP_KERNEL);
if (!ipc4_copier->gtw_attr) {
@@ -566,7 +586,6 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget)
switch (ipc4_copier->dai_type) {
case SOF_DAI_INTEL_ALH:
{
- struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc4_alh_configuration_blob *blob;
struct snd_soc_dapm_path *p;
struct snd_sof_widget *w;
@@ -1277,7 +1296,6 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
}
if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) {
- struct sof_ipc4_copier_data *copier_data = &ipc4_copier->data;
struct sof_ipc4_alh_configuration_blob *blob;
unsigned int group_id;
@@ -1287,9 +1305,6 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
ALH_MULTI_GTW_BASE;
ida_free(&alh_group_ida, group_id);
}
-
- /* clear the node ID */
- copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
}
}
@@ -1454,6 +1469,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
u32 deep_buffer_dma_ms = 0;
int output_fmt_index;
bool single_output_format;
+ int i;
dev_dbg(sdev->dev, "copier %s, type %d", swidget->widget->name, swidget->id);
@@ -1671,6 +1687,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
*/
if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) {
struct sof_ipc4_alh_configuration_blob *blob;
+ struct sof_ipc4_dma_config *dma_config;
struct sof_ipc4_copier_data *alh_data;
struct sof_ipc4_copier *alh_copier;
struct snd_sof_widget *w;
@@ -1679,7 +1696,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
u32 ch_map;
u32 step;
u32 mask;
- int i;
blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
@@ -1703,6 +1719,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
*/
i = 0;
list_for_each_entry(w, &sdev->widget_list, list) {
+ u32 node_type;
+
if (w->widget->sname &&
strcmp(w->widget->sname, swidget->widget->sname))
continue;
@@ -1710,7 +1728,22 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
dai = w->private;
alh_copier = (struct sof_ipc4_copier *)dai->private;
alh_data = &alh_copier->data;
- blob->alh_cfg.mapping[i].device = alh_data->gtw_cfg.node_id;
+ node_type = SOF_IPC4_GET_NODE_TYPE(alh_data->gtw_cfg.node_id);
+ blob->alh_cfg.mapping[i].device = SOF_IPC4_NODE_TYPE(node_type);
+ blob->alh_cfg.mapping[i].device |=
+ SOF_IPC4_NODE_INDEX(alh_copier->dai_index);
+
+ /*
+ * The mapping[i] device in ALH blob should be the same as the
+ * dma_config_tlv[i] mapping device if a dma_config_tlv is present.
+ * The device id will be used for DMA tlv mapping purposes.
+ */
+ if (ipc4_copier->dma_config_tlv[i].length) {
+ dma_config = &ipc4_copier->dma_config_tlv[i].dma_config;
+ blob->alh_cfg.mapping[i].device =
+ dma_config->dma_stream_channel_map.mapping[0].device;
+ }
+
/*
* Set the same channel mask for playback as the audio data is
* duplicated for all speakers. For capture, split the channels
@@ -1789,19 +1822,18 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
gtw_cfg_config_length = copier_data->gtw_cfg.config_length * 4;
ipc_size = sizeof(*copier_data) + gtw_cfg_config_length;
- if (ipc4_copier->dma_config_tlv.type == SOF_IPC4_GTW_DMA_CONFIG_ID &&
- ipc4_copier->dma_config_tlv.length) {
- dma_config_tlv_size = sizeof(ipc4_copier->dma_config_tlv) +
- ipc4_copier->dma_config_tlv.dma_config.dma_priv_config_size;
-
- /* paranoia check on TLV size/length */
- if (dma_config_tlv_size != ipc4_copier->dma_config_tlv.length +
- sizeof(uint32_t) * 2) {
- dev_err(sdev->dev, "Invalid configuration, TLV size %d length %d\n",
- dma_config_tlv_size, ipc4_copier->dma_config_tlv.length);
- return -EINVAL;
- }
+ dma_config_tlv_size = 0;
+ for (i = 0; i < SOF_IPC4_DMA_DEVICE_MAX_COUNT; i++) {
+ if (ipc4_copier->dma_config_tlv[i].type != SOF_IPC4_GTW_DMA_CONFIG_ID)
+ continue;
+ dma_config_tlv_size += ipc4_copier->dma_config_tlv[i].length;
+ dma_config_tlv_size +=
+ ipc4_copier->dma_config_tlv[i].dma_config.dma_priv_config_size;
+ dma_config_tlv_size += (sizeof(ipc4_copier->dma_config_tlv[i]) -
+ sizeof(ipc4_copier->dma_config_tlv[i].dma_config));
+ }
+ if (dma_config_tlv_size) {
ipc_size += dma_config_tlv_size;
/* we also need to increase the size at the gtw level */
@@ -2813,17 +2845,24 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
case SOF_DAI_INTEL_HDA:
gtw_attr = ipc4_copier->gtw_attr;
gtw_attr->lp_buffer_alloc = pipeline->lp_mode;
- fallthrough;
+ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
+ copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
+ copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data);
+ }
+ break;
case SOF_DAI_INTEL_ALH:
/*
* Do not clear the node ID when this op is invoked with
* SOF_DAI_CONFIG_FLAGS_HW_FREE. It is needed to free the group_ida during
- * unprepare.
+ * unprepare. The node_id for multi-gateway DAI's will be overwritten with the
+ * group_id during copier's ipc_prepare op.
*/
if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
+ ipc4_copier->dai_index = data->dai_node_id;
copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
- copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data);
+ copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_node_id);
}
+
break;
case SOF_DAI_INTEL_DMIC:
case SOF_DAI_INTEL_SSP:
diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h
index dce174a190dd..6e33208a357f 100644
--- a/sound/soc/sof/ipc4-topology.h
+++ b/sound/soc/sof/ipc4-topology.h
@@ -45,6 +45,7 @@
#define SOF_IPC4_NODE_INDEX_MASK 0xFF
#define SOF_IPC4_NODE_INDEX(x) ((x) & SOF_IPC4_NODE_INDEX_MASK)
#define SOF_IPC4_NODE_TYPE(x) ((x) << 8)
+#define SOF_IPC4_GET_NODE_TYPE(node_id) ((node_id) >> 8)
/* Node ID for SSP type DAI copiers */
#define SOF_IPC4_NODE_INDEX_INTEL_SSP(x) (((x) & 0xf) << 4)
@@ -313,7 +314,7 @@ struct sof_ipc4_copier {
struct sof_ipc4_gtw_attributes *gtw_attr;
u32 dai_type;
int dai_index;
- struct sof_ipc4_dma_config_tlv dma_config_tlv;
+ struct sof_ipc4_dma_config_tlv dma_config_tlv[SOF_IPC4_DMA_DEVICE_MAX_COUNT];
};
/**
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index 6cf21e829e07..3cd748e13460 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -523,12 +523,26 @@ static inline int snd_sof_pcm_platform_ack(struct snd_sof_dev *sdev,
return 0;
}
-static inline u64 snd_sof_pcm_get_stream_position(struct snd_sof_dev *sdev,
- struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
+static inline u64
+snd_sof_pcm_get_dai_frame_counter(struct snd_sof_dev *sdev,
+ struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
{
- if (sof_ops(sdev) && sof_ops(sdev)->get_stream_position)
- return sof_ops(sdev)->get_stream_position(sdev, component, substream);
+ if (sof_ops(sdev) && sof_ops(sdev)->get_dai_frame_counter)
+ return sof_ops(sdev)->get_dai_frame_counter(sdev, component,
+ substream);
+
+ return 0;
+}
+
+static inline u64
+snd_sof_pcm_get_host_byte_counter(struct snd_sof_dev *sdev,
+ struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->get_host_byte_counter)
+ return sof_ops(sdev)->get_host_byte_counter(sdev, component,
+ substream);
return 0;
}
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index 33d576b17647..4e11df6b4823 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -196,9 +196,8 @@ static int sof_pcm_hw_free(struct snd_soc_component *component,
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
- const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
struct snd_sof_pcm *spcm;
- int ret, err = 0;
+ int ret;
/* nothing to do for BE */
if (rtd->dai_link->no_pcm)
@@ -211,42 +210,18 @@ static int sof_pcm_hw_free(struct snd_soc_component *component,
dev_dbg(component->dev, "pcm: free stream %d dir %d\n",
spcm->pcm.pcm_id, substream->stream);
- if (spcm->prepared[substream->stream]) {
- /* stop DMA first if needed */
- if (pcm_ops && pcm_ops->platform_stop_during_hw_free)
- snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP);
-
- /* free PCM in the DSP */
- if (pcm_ops && pcm_ops->hw_free) {
- ret = pcm_ops->hw_free(component, substream);
- if (ret < 0)
- err = ret;
- }
-
- spcm->prepared[substream->stream] = false;
- }
-
- /* reset DMA */
- ret = snd_sof_pcm_platform_hw_free(sdev, substream);
- if (ret < 0) {
- dev_err(component->dev, "error: platform hw free failed\n");
- err = ret;
- }
-
- /* free the DAPM widget list */
- ret = sof_widget_list_free(sdev, spcm, substream->stream);
- if (ret < 0)
- err = ret;
+ ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true);
cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
- return err;
+ return ret;
}
static int sof_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct snd_sof_pcm *spcm;
int ret;
@@ -258,8 +233,18 @@ static int sof_pcm_prepare(struct snd_soc_component *component,
if (!spcm)
return -EINVAL;
- if (spcm->prepared[substream->stream])
- return 0;
+ if (spcm->prepared[substream->stream]) {
+ if (!spcm->pending_stop[substream->stream])
+ return 0;
+
+ /*
+ * this case should be reached in case of xruns where we absolutely
+ * want to free-up and reset all PCM/DMA resources
+ */
+ ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true);
+ if (ret < 0)
+ return ret;
+ }
dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n",
spcm->pcm.pcm_id, substream->stream);
@@ -302,6 +287,8 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n",
spcm->pcm.pcm_id, substream->stream, cmd);
+ spcm->pending_stop[substream->stream] = false;
+
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ipc_first = true;
@@ -371,6 +358,15 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
/* invoke platform trigger to stop DMA even if pcm_ops isn't set or if it failed */
if (!pcm_ops || !pcm_ops->platform_stop_during_hw_free)
snd_sof_pcm_platform_trigger(sdev, substream, cmd);
+
+ /*
+ * set the pending_stop flag to indicate that pipeline stop has been delayed.
+ * This will be used later to stop the pipelines during prepare when recovering
+ * from xruns.
+ */
+ if (pcm_ops && pcm_ops->platform_stop_during_hw_free &&
+ cmd == SNDRV_PCM_TRIGGER_STOP)
+ spcm->pending_stop[substream->stream] = true;
break;
default:
break;
@@ -388,13 +384,21 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component,
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
+ const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
struct snd_sof_pcm *spcm;
snd_pcm_uframes_t host, dai;
+ int ret = -EOPNOTSUPP;
/* nothing to do for BE */
if (rtd->dai_link->no_pcm)
return 0;
+ if (pcm_ops && pcm_ops->pointer)
+ ret = pcm_ops->pointer(component, substream, &host);
+
+ if (ret != -EOPNOTSUPP)
+ return ret ? ret : host;
+
/* use dsp ops pointer callback directly if set */
if (sof_ops(sdev)->pcm_pointer)
return sof_ops(sdev)->pcm_pointer(sdev, substream);
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index e693dcb475e4..32fef64ef10d 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -834,35 +834,48 @@ int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *subs
{
const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
int ret;
+ int err = 0;
if (spcm->prepared[substream->stream]) {
/* stop DMA first if needed */
if (pcm_ops && pcm_ops->platform_stop_during_hw_free)
snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP);
- /* Send PCM_FREE IPC to reset pipeline */
+ /* free PCM in the DSP */
if (pcm_ops && pcm_ops->hw_free) {
ret = pcm_ops->hw_free(sdev->component, substream);
- if (ret < 0)
- return ret;
+ if (ret < 0) {
+ dev_err(sdev->dev, "%s: pcm_ops hw_free failed %d\n",
+ __func__, ret);
+ err = ret;
+ }
}
spcm->prepared[substream->stream] = false;
+ spcm->pending_stop[substream->stream] = false;
}
/* reset the DMA */
ret = snd_sof_pcm_platform_hw_free(sdev, substream);
- if (ret < 0)
- return ret;
+ if (ret < 0) {
+ dev_err(sdev->dev, "%s: platform hw free failed %d\n",
+ __func__, ret);
+ if (!err)
+ err = ret;
+ }
/* free widget list */
if (free_widget_list) {
ret = sof_widget_list_free(sdev, spcm, dir);
- if (ret < 0)
- dev_err(sdev->dev, "failed to free widgets during suspend\n");
+ if (ret < 0) {
+ dev_err(sdev->dev, "%s: sof_widget_list_free failed %d\n",
+ __func__, ret);
+ if (!err)
+ err = ret;
+ }
}
- return ret;
+ return err;
}
/*
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index 9ea2ac5adac7..f4134257789e 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -91,6 +91,7 @@ struct snd_sof_pcm;
struct snd_sof_dai_config_data {
int dai_index;
int dai_data; /* contains DAI-specific information */
+ int dai_node_id; /* contains DAI-specific information for Gateway configuration */
};
/**
@@ -103,7 +104,10 @@ struct snd_sof_dai_config_data {
* additional memory in the SOF PCM stream structure
* @pcm_free: Function pointer for PCM free that can be used for freeing any
* additional memory in the SOF PCM stream structure
- * @delay: Function pointer for pcm delay calculation
+ * @pointer: Function pointer for pcm pointer
+ * Note: the @pointer callback may return -EOPNOTSUPP which should be
+ * handled in a same way as if the callback is not provided
+ * @delay: Function pointer for pcm delay reporting
* @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the
* STOP pcm trigger
* @ipc_first_on_start: Send IPC before invoking platform trigger during
@@ -124,6 +128,9 @@ struct sof_ipc_pcm_ops {
int (*dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params);
int (*pcm_setup)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm);
void (*pcm_free)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm);
+ int (*pointer)(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t *pointer);
snd_pcm_sframes_t (*delay)(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
bool reset_hw_params_during_stop;
@@ -322,6 +329,7 @@ struct snd_sof_pcm_stream {
struct work_struct period_elapsed_work;
struct snd_soc_dapm_widget_list *list; /* list of connected DAPM widgets */
bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */
+ unsigned int dsp_max_burst_size_in_ms; /* The maximum size of the host DMA burst in ms */
/*
* flag to indicate that the DSP pipelines should be kept
* active or not while suspending the stream
@@ -341,6 +349,7 @@ struct snd_sof_pcm {
struct list_head list; /* list in sdev pcm list */
struct snd_pcm_hw_params params[2];
bool prepared[2]; /* PCM_PARAMS set successfully */
+ bool pending_stop[2]; /* only used if (!pcm_ops->platform_stop_during_hw_free) */
};
struct snd_sof_led_control {
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index d453a4ce3b21..d3c436f82604 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -262,13 +262,25 @@ struct snd_sof_dsp_ops {
int (*pcm_ack)(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); /* optional */
/*
- * optional callback to retrieve the link DMA position for the substream
- * when the position is not reported in the shared SRAM windows but
- * instead from a host-accessible hardware counter.
+ * optional callback to retrieve the number of frames left/arrived from/to
+ * the DSP on the DAI side (link/codec/DMIC/etc).
+ *
+ * The callback is used when the firmware does not provide this information
+ * via the shared SRAM window and it can be retrieved by host.
*/
- u64 (*get_stream_position)(struct snd_sof_dev *sdev,
- struct snd_soc_component *component,
- struct snd_pcm_substream *substream); /* optional */
+ u64 (*get_dai_frame_counter)(struct snd_sof_dev *sdev,
+ struct snd_soc_component *component,
+ struct snd_pcm_substream *substream); /* optional */
+
+ /*
+ * Optional callback to retrieve the number of bytes left/arrived from/to
+ * the DSP on the host side (bytes between host ALSA buffer and DSP).
+ *
+ * The callback is needed for ALSA delay reporting.
+ */
+ u64 (*get_host_byte_counter)(struct snd_sof_dev *sdev,
+ struct snd_soc_component *component,
+ struct snd_pcm_substream *substream); /* optional */
/* host read DSP stream data */
int (*ipc_msg_data)(struct snd_sof_dev *sdev,
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 43795362fed0..b5dafb749c3f 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -232,6 +232,7 @@ struct sun8i_codec {
struct delayed_work jack_work;
int jack_irq;
int jack_status;
+ int jack_type;
int jack_last_sample;
ktime_t jack_hbias_ready;
struct mutex jack_mutex;
@@ -1352,7 +1353,6 @@ static void sun8i_codec_jack_work(struct work_struct *work)
struct sun8i_codec *scodec = container_of(work, struct sun8i_codec,
jack_work.work);
unsigned int mdata;
- int type_mask = scodec->jack->jack->type;
int type;
guard(mutex)(&scodec->jack_mutex);
@@ -1363,7 +1363,7 @@ static void sun8i_codec_jack_work(struct work_struct *work)
scodec->jack_last_sample = -1;
- if (type_mask & SND_JACK_MICROPHONE) {
+ if (scodec->jack_type & SND_JACK_MICROPHONE) {
/*
* If we were in disconnected state, we enable HBIAS and
* wait 600ms before reading initial HDATA value.
@@ -1376,7 +1376,7 @@ static void sun8i_codec_jack_work(struct work_struct *work)
scodec->jack_status = SUN8I_JACK_STATUS_WAITING_HBIAS;
} else {
snd_soc_jack_report(scodec->jack, SND_JACK_HEADPHONE,
- type_mask);
+ scodec->jack_type);
scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED;
}
} else if (scodec->jack_status == SUN8I_JACK_STATUS_WAITING_HBIAS) {
@@ -1417,17 +1417,17 @@ static void sun8i_codec_jack_work(struct work_struct *work)
if (type == SND_JACK_HEADPHONE)
sun8i_codec_set_hmic_bias(scodec, false);
- snd_soc_jack_report(scodec->jack, type, type_mask);
+ snd_soc_jack_report(scodec->jack, type, scodec->jack_type);
scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED;
} else if (scodec->jack_status == SUN8I_JACK_STATUS_CONNECTED) {
if (scodec->last_hmic_irq != SUN8I_HMIC_STS_JACK_OUT_IRQ_ST)
return;
scodec->jack_status = SUN8I_JACK_STATUS_DISCONNECTED;
- if (type_mask & SND_JACK_MICROPHONE)
+ if (scodec->jack_type & SND_JACK_MICROPHONE)
sun8i_codec_set_hmic_bias(scodec, false);
- snd_soc_jack_report(scodec->jack, 0, type_mask);
+ snd_soc_jack_report(scodec->jack, 0, scodec->jack_type);
}
}
@@ -1491,7 +1491,7 @@ static irqreturn_t sun8i_codec_jack_irq(int irq, void *dev_id)
if (scodec->jack_last_sample >= 0 &&
scodec->jack_last_sample == value)
snd_soc_jack_report(scodec->jack, type,
- scodec->jack->jack->type);
+ scodec->jack_type);
scodec->jack_last_sample = value;
}