forked from Minki/linux
ASoC: More updates for v5.20
More updates that came in since the last pull request I sent, a series of driver specific changes: - Support for AMD RPL, some Intel platforms and Mediatek MT8186. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmLnvRYACgkQJNaLcl1U h9CAVwf/UU9J1cHE064hgfmkMXPFlP1jPs/e9cY8MJhcAZa2fhm4y0UqEg/uZu2A 0ipufYtJeUWXRtj6ToQj79lWxB28NVNugQxh6wEfqXcHaY81tRgdiX5kxEjmQmf7 dpQ92so5Bn/r1TRNqYVvfjkvFefvF1DlzQgBRX61cvB5ZOTdvah7UNxq4T7+j1Rs +84347X0fDgcl3dbbpuTPz3G1b7D20BYfoUWzAyc/ciYuehQxdDb9sxhX7KgwupW li1WPYymPx5eSKm7niPVOMsORjKKceV3Zu1nlZJISCBQacdbvtQDAaXV3UtGSWne 29lvYPTFu6a2Zz09r2LYIj7Uy3L5sg== =5iYn -----END PGP SIGNATURE----- Merge tag 'asoc-v5.20-2' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus ASoC: More updates for v5.20 More updates that came in since the last pull request I sent, a series of driver specific changes: - Support for AMD RPL, some Intel platforms and Mediatek MT8186.
This commit is contained in:
commit
a3b5d4715f
@ -32,8 +32,6 @@ properties:
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency: true
|
||||
|
||||
AVDD-supply:
|
||||
description: Analog power support for the device.
|
||||
|
||||
@ -52,7 +50,10 @@ required:
|
||||
- compatible
|
||||
- AVDD-supply
|
||||
|
||||
additionalProperties: false
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -0,0 +1,100 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
# Copyright (C) 2022 Microchip Technology, Inc. and its subsidiaries
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/atmel,sama5d2-classd.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Atmel ClassD Amplifier
|
||||
|
||||
maintainers:
|
||||
- Nicolas Ferre <nicolas.ferre@microchip.com>
|
||||
- Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||
- Claudiu Beznea <claudiu.beznea@microchip.com>
|
||||
|
||||
description:
|
||||
The Audio Class D Amplifier (CLASSD) is a digital input, Pulse Width
|
||||
Modulated (PWM) output stereo Class D amplifier.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: atmel,sama5d2-classd
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
maxItems: 1
|
||||
|
||||
dma-names:
|
||||
const: tx
|
||||
|
||||
clocks:
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: gclk
|
||||
|
||||
atmel,model:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
default: CLASSD
|
||||
description: The user-visible name of this sound complex.
|
||||
|
||||
atmel,pwm-type:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum:
|
||||
- single
|
||||
- diff
|
||||
default: single
|
||||
description: PWM modulation type.
|
||||
|
||||
atmel,non-overlap-time:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 5
|
||||
- 10
|
||||
- 15
|
||||
- 20
|
||||
default: 10
|
||||
description:
|
||||
Set non-overlapping time, the unit is nanosecond(ns).
|
||||
Non-overlapping will be disabled if not specified.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- dmas
|
||||
- dma-names
|
||||
- clock-names
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/dma/at91.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
classd: sound@fc048000 {
|
||||
compatible = "atmel,sama5d2-classd";
|
||||
reg = <0xfc048000 0x100>;
|
||||
interrupts = <59 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
dmas = <&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)
|
||||
| AT91_XDMAC_DT_PERID(47))>;
|
||||
dma-names = "tx";
|
||||
clocks = <&classd_clk>, <&classd_gclk>;
|
||||
clock-names = "pclk", "gclk";
|
||||
assigned-clocks = <&classd_gclk>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_classd_default>;
|
||||
atmel,model = "classd @ SAMA5D2-Xplained";
|
||||
atmel,pwm-type = "diff";
|
||||
atmel,non-overlap-time = <10>;
|
||||
};
|
@ -0,0 +1,85 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
# Copyright (C) 2022 Microchip Technology, Inc. and its subsidiaries
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/atmel,sama5d2-i2s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Atmel I2S controller
|
||||
|
||||
maintainers:
|
||||
- Nicolas Ferre <nicolas.ferre@microchip.com>
|
||||
- Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||
- Claudiu Beznea <claudiu.beznea@microchip.com>
|
||||
|
||||
description:
|
||||
Atmel I2S (Inter-IC Sound Controller) bus is the standard
|
||||
interface for connecting audio devices, such as audio codecs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: atmel,sama5d2-i2s
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Peripheral clock
|
||||
- description: Generated clock (Optional)
|
||||
- description: I2S mux clock (Optional). Set
|
||||
with gclk when Master Mode is required.
|
||||
minItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: gclk
|
||||
- const: muxclk
|
||||
minItems: 1
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: TX DMA Channel
|
||||
- description: RX DMA Channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- dmas
|
||||
- dma-names
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/dma/at91.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
i2s@f8050000 {
|
||||
compatible = "atmel,sama5d2-i2s";
|
||||
reg = <0xf8050000 0x300>;
|
||||
interrupts = <54 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
dmas = <&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
|
||||
AT91_XDMAC_DT_PERID(31))>,
|
||||
<&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
|
||||
AT91_XDMAC_DT_PERID(32))>;
|
||||
dma-names = "tx", "rx";
|
||||
clocks = <&i2s0_clk>, <&i2s0_gclk>, <&i2s0muxck>;
|
||||
clock-names = "pclk", "gclk", "muxclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_i2s0_default>;
|
||||
};
|
@ -0,0 +1,98 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
# Copyright (C) 2022 Microchip Technology, Inc. and its subsidiaries
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/atmel,sama5d2-pdmic.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Atmel PDMIC decoder
|
||||
|
||||
maintainers:
|
||||
- Claudiu Beznea <claudiu.beznea@microchip.com>
|
||||
|
||||
description:
|
||||
Atmel Pulse Density Modulation Interface Controller
|
||||
(PDMIC) peripheral is a mono PDM decoder module
|
||||
that decodes an incoming PDM sample stream.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: atmel,sama5d2-pdmic
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: peripheral clock
|
||||
- description: generated clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: gclk
|
||||
|
||||
dmas:
|
||||
maxItems: 1
|
||||
|
||||
dma-names:
|
||||
const: rx
|
||||
|
||||
atmel,mic-min-freq:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
The minimal frequency that the microphone supports.
|
||||
|
||||
atmel,mic-max-freq:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
The maximal frequency that the microphone supports.
|
||||
|
||||
atmel,model:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
default: PDMIC
|
||||
description: The user-visible name of this sound card.
|
||||
|
||||
atmel,mic-offset:
|
||||
$ref: /schemas/types.yaml#/definitions/int32
|
||||
default: 0
|
||||
description: The offset that should be added.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- dmas
|
||||
- dma-names
|
||||
- clock-names
|
||||
- clocks
|
||||
- atmel,mic-min-freq
|
||||
- atmel,mic-max-freq
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/dma/at91.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
pdmic: sound@f8018000 {
|
||||
compatible = "atmel,sama5d2-pdmic";
|
||||
reg = <0xf8018000 0x124>;
|
||||
interrupts = <48 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
dmas = <&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)
|
||||
| AT91_XDMAC_DT_PERID(50))>;
|
||||
dma-names = "rx";
|
||||
clocks = <&pdmic_clk>, <&pdmic_gclk>;
|
||||
clock-names = "pclk", "gclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_pdmic_default>;
|
||||
atmel,model = "PDMIC@sama5d2_xplained";
|
||||
atmel,mic-min-freq = <1000000>;
|
||||
atmel,mic-max-freq = <3246000>;
|
||||
atmel,mic-offset = <0x0>;
|
||||
};
|
@ -1,55 +0,0 @@
|
||||
* Atmel ClassD driver under ALSA SoC architecture
|
||||
|
||||
Required properties:
|
||||
- compatible
|
||||
Should be "atmel,sama5d2-classd".
|
||||
- reg
|
||||
Should contain ClassD registers location and length.
|
||||
- interrupts
|
||||
Should contain the IRQ line for the ClassD.
|
||||
- dmas
|
||||
One DMA specifiers as described in atmel-dma.txt and dma.txt files.
|
||||
- dma-names
|
||||
Must be "tx".
|
||||
- clock-names
|
||||
Tuple listing input clock names.
|
||||
Required elements: "pclk" and "gclk".
|
||||
- clocks
|
||||
Please refer to clock-bindings.txt.
|
||||
- assigned-clocks
|
||||
Should be <&classd_gclk>.
|
||||
|
||||
Optional properties:
|
||||
- pinctrl-names, pinctrl-0
|
||||
Please refer to pinctrl-bindings.txt.
|
||||
- atmel,model
|
||||
The user-visible name of this sound complex.
|
||||
The default value is "CLASSD".
|
||||
- atmel,pwm-type
|
||||
PWM modulation type, "single" or "diff".
|
||||
The default value is "single".
|
||||
- atmel,non-overlap-time
|
||||
Set non-overlapping time, the unit is nanosecond(ns).
|
||||
There are four values,
|
||||
<5>, <10>, <15>, <20>, the default value is <10>.
|
||||
Non-overlapping will be disabled if not specified.
|
||||
|
||||
Example:
|
||||
classd: classd@fc048000 {
|
||||
compatible = "atmel,sama5d2-classd";
|
||||
reg = <0xfc048000 0x100>;
|
||||
interrupts = <59 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
dmas = <&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)
|
||||
| AT91_XDMAC_DT_PERID(47))>;
|
||||
dma-names = "tx";
|
||||
clocks = <&classd_clk>, <&classd_gclk>;
|
||||
clock-names = "pclk", "gclk";
|
||||
assigned-clocks = <&classd_gclk>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_classd_default>;
|
||||
atmel,model = "classd @ SAMA5D2-Xplained";
|
||||
atmel,pwm-type = "diff";
|
||||
atmel,non-overlap-time = <10>;
|
||||
};
|
@ -1,46 +0,0 @@
|
||||
* Atmel I2S controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "atmel,sama5d2-i2s".
|
||||
- reg: Should be the physical base address of the controller and the
|
||||
length of memory mapped region.
|
||||
- interrupts: Should contain the interrupt for the controller.
|
||||
- dmas: Should be one per channel name listed in the dma-names property,
|
||||
as described in atmel-dma.txt and dma.txt files.
|
||||
- dma-names: Two dmas have to be defined, "tx" and "rx".
|
||||
This IP also supports one shared channel for both rx and tx;
|
||||
if this mode is used, one "rx-tx" name must be used.
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
Please refer to clock-bindings.txt.
|
||||
- clock-names: Should be one of each entry matching the clocks phandles list:
|
||||
- "pclk" (peripheral clock) Required.
|
||||
- "gclk" (generated clock) Optional (1).
|
||||
- "muxclk" (I2S mux clock) Optional (1).
|
||||
|
||||
Optional properties:
|
||||
- pinctrl-0: Should specify pin control groups used for this controller.
|
||||
- princtrl-names: Should contain only one value - "default".
|
||||
|
||||
|
||||
(1) : Only the peripheral clock is required. The generated clock and the I2S
|
||||
mux clock are optional and should only be set together, when Master Mode
|
||||
is required.
|
||||
|
||||
Example:
|
||||
|
||||
i2s@f8050000 {
|
||||
compatible = "atmel,sama5d2-i2s";
|
||||
reg = <0xf8050000 0x300>;
|
||||
interrupts = <54 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
dmas = <&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
|
||||
AT91_XDMAC_DT_PERID(31))>,
|
||||
<&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
|
||||
AT91_XDMAC_DT_PERID(32))>;
|
||||
dma-names = "tx", "rx";
|
||||
clocks = <&i2s0_clk>, <&i2s0_gclk>, <&i2s0muxck>;
|
||||
clock-names = "pclk", "gclk", "muxclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_i2s0_default>;
|
||||
};
|
@ -1,55 +0,0 @@
|
||||
* Atmel PDMIC driver under ALSA SoC architecture
|
||||
|
||||
Required properties:
|
||||
- compatible
|
||||
Should be "atmel,sama5d2-pdmic".
|
||||
- reg
|
||||
Should contain PDMIC registers location and length.
|
||||
- interrupts
|
||||
Should contain the IRQ line for the PDMIC.
|
||||
- dmas
|
||||
One DMA specifiers as described in atmel-dma.txt and dma.txt files.
|
||||
- dma-names
|
||||
Must be "rx".
|
||||
- clock-names
|
||||
Required elements:
|
||||
- "pclk" peripheral clock
|
||||
- "gclk" generated clock
|
||||
- clocks
|
||||
Must contain an entry for each required entry in clock-names.
|
||||
Please refer to clock-bindings.txt.
|
||||
- atmel,mic-min-freq
|
||||
The minimal frequency that the micphone supports.
|
||||
- atmel,mic-max-freq
|
||||
The maximal frequency that the micphone supports.
|
||||
|
||||
Optional properties:
|
||||
- pinctrl-names, pinctrl-0
|
||||
Please refer to pinctrl-bindings.txt.
|
||||
- atmel,model
|
||||
The user-visible name of this sound card.
|
||||
The default value is "PDMIC".
|
||||
- atmel,mic-offset
|
||||
The offset that should be added.
|
||||
The range is from -32768 to 32767.
|
||||
The default value is 0.
|
||||
|
||||
Example:
|
||||
pdmic@f8018000 {
|
||||
compatible = "atmel,sama5d2-pdmic";
|
||||
reg = <0xf8018000 0x124>;
|
||||
interrupts = <48 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
dmas = <&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)
|
||||
| AT91_XDMAC_DT_PERID(50))>;
|
||||
dma-names = "rx";
|
||||
clocks = <&pdmic_clk>, <&pdmic_gclk>;
|
||||
clock-names = "pclk", "gclk";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_pdmic_default>;
|
||||
atmel,model = "PDMIC @ sama5d2_xplained";
|
||||
atmel,mic-min-freq = <1000000>;
|
||||
atmel,mic-max-freq = <3246000>;
|
||||
atmel,mic-offset = <0x0>;
|
||||
};
|
@ -7,7 +7,9 @@ Must be a child node of PMIC wrapper.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "mediatek,mt6358-sound".
|
||||
- compatible - "string" - One of:
|
||||
"mediatek,mt6358-sound"
|
||||
"mediatek,mt6366-sound"
|
||||
- Avdd-supply : power source of AVDD
|
||||
|
||||
Optional properties:
|
||||
|
175
Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml
Normal file
175
Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml
Normal file
@ -0,0 +1,175 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mt8186-afe-pcm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Mediatek AFE PCM controller for mt8186
|
||||
|
||||
maintainers:
|
||||
- Jiaxin Yu <jiaxin.yu@mediatek.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt8186-sound
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
reset-names:
|
||||
const: audiosys
|
||||
|
||||
mediatek,apmixedsys:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
description: The phandle of the mediatek apmixedsys controller
|
||||
|
||||
mediatek,infracfg:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
description: The phandle of the mediatek infracfg controller
|
||||
|
||||
mediatek,topckgen:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
description: The phandle of the mediatek topckgen controller
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: audio infra sys clock
|
||||
- description: audio infra 26M clock
|
||||
- description: audio top mux
|
||||
- description: audio intbus mux
|
||||
- description: mainpll 136.5M clock
|
||||
- description: faud1 mux
|
||||
- description: apll1 clock
|
||||
- description: faud2 mux
|
||||
- description: apll2 clock
|
||||
- description: audio engen1 mux
|
||||
- description: apll1_d8 22.5792M clock
|
||||
- description: audio engen2 mux
|
||||
- description: apll2_d8 24.576M clock
|
||||
- description: i2s0 mclk mux
|
||||
- description: i2s1 mclk mux
|
||||
- description: i2s2 mclk mux
|
||||
- description: i2s4 mclk mux
|
||||
- description: tdm mclk mux
|
||||
- description: i2s0_mck divider
|
||||
- description: i2s1_mck divider
|
||||
- description: i2s2_mck divider
|
||||
- description: i2s4_mck divider
|
||||
- description: tdm_mck divider
|
||||
- description: audio hires mux
|
||||
- description: 26M clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: aud_infra_clk
|
||||
- const: mtkaif_26m_clk
|
||||
- const: top_mux_audio
|
||||
- const: top_mux_audio_int
|
||||
- const: top_mainpll_d2_d4
|
||||
- const: top_mux_aud_1
|
||||
- const: top_apll1_ck
|
||||
- const: top_mux_aud_2
|
||||
- const: top_apll2_ck
|
||||
- const: top_mux_aud_eng1
|
||||
- const: top_apll1_d8
|
||||
- const: top_mux_aud_eng2
|
||||
- const: top_apll2_d8
|
||||
- const: top_i2s0_m_sel
|
||||
- const: top_i2s1_m_sel
|
||||
- const: top_i2s2_m_sel
|
||||
- const: top_i2s4_m_sel
|
||||
- const: top_tdm_m_sel
|
||||
- const: top_apll12_div0
|
||||
- const: top_apll12_div1
|
||||
- const: top_apll12_div2
|
||||
- const: top_apll12_div4
|
||||
- const: top_apll12_div_tdm
|
||||
- const: top_mux_audio_h
|
||||
- const: top_clk26m_clk
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- interrupts
|
||||
- resets
|
||||
- reset-names
|
||||
- mediatek,apmixedsys
|
||||
- mediatek,infracfg
|
||||
- mediatek,topckgen
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
afe: mt8186-afe-pcm@11210000 {
|
||||
compatible = "mediatek,mt8186-sound";
|
||||
reg = <0x11210000 0x2000>;
|
||||
interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
|
||||
resets = <&watchdog 17>; //MT8186_TOPRGU_AUDIO_SW_RST
|
||||
reset-names = "audiosys";
|
||||
mediatek,apmixedsys = <&apmixedsys>;
|
||||
mediatek,infracfg = <&infracfg>;
|
||||
mediatek,topckgen = <&topckgen>;
|
||||
clocks = <&infracfg_ao 44>, //CLK_INFRA_AO_AUDIO
|
||||
<&infracfg_ao 54>, //CLK_INFRA_AO_AUDIO_26M_BCLK
|
||||
<&topckgen 15>, //CLK_TOP_AUDIO
|
||||
<&topckgen 16>, //CLK_TOP_AUD_INTBUS
|
||||
<&topckgen 70>, //CLK_TOP_MAINPLL_D2_D4
|
||||
<&topckgen 17>, //CLK_TOP_AUD_1
|
||||
<&apmixedsys 12>, //CLK_APMIXED_APLL1
|
||||
<&topckgen 18>, //CLK_TOP_AUD_2
|
||||
<&apmixedsys 13>, //CLK_APMIXED_APLL2
|
||||
<&topckgen 19>, //CLK_TOP_AUD_ENGEN1
|
||||
<&topckgen 101>, //CLK_TOP_APLL1_D8
|
||||
<&topckgen 20>, //CLK_TOP_AUD_ENGEN2
|
||||
<&topckgen 104>, //CLK_TOP_APLL2_D8
|
||||
<&topckgen 63>, //CLK_TOP_APLL_I2S0_MCK_SEL
|
||||
<&topckgen 64>, //CLK_TOP_APLL_I2S1_MCK_SEL
|
||||
<&topckgen 65>, //CLK_TOP_APLL_I2S2_MCK_SEL
|
||||
<&topckgen 66>, //CLK_TOP_APLL_I2S4_MCK_SEL
|
||||
<&topckgen 67>, //CLK_TOP_APLL_TDMOUT_MCK_SEL
|
||||
<&topckgen 131>, //CLK_TOP_APLL12_CK_DIV0
|
||||
<&topckgen 132>, //CLK_TOP_APLL12_CK_DIV1
|
||||
<&topckgen 133>, //CLK_TOP_APLL12_CK_DIV2
|
||||
<&topckgen 134>, //CLK_TOP_APLL12_CK_DIV4
|
||||
<&topckgen 135>, //CLK_TOP_APLL12_CK_DIV_TDMOUT_M
|
||||
<&topckgen 44>, //CLK_TOP_AUDIO_H
|
||||
<&clk26m>;
|
||||
clock-names = "aud_infra_clk",
|
||||
"mtkaif_26m_clk",
|
||||
"top_mux_audio",
|
||||
"top_mux_audio_int",
|
||||
"top_mainpll_d2_d4",
|
||||
"top_mux_aud_1",
|
||||
"top_apll1_ck",
|
||||
"top_mux_aud_2",
|
||||
"top_apll2_ck",
|
||||
"top_mux_aud_eng1",
|
||||
"top_apll1_d8",
|
||||
"top_mux_aud_eng2",
|
||||
"top_apll2_d8",
|
||||
"top_i2s0_m_sel",
|
||||
"top_i2s1_m_sel",
|
||||
"top_i2s2_m_sel",
|
||||
"top_i2s4_m_sel",
|
||||
"top_tdm_m_sel",
|
||||
"top_apll12_div0",
|
||||
"top_apll12_div1",
|
||||
"top_apll12_div2",
|
||||
"top_apll12_div4",
|
||||
"top_apll12_div_tdm",
|
||||
"top_mux_audio_h",
|
||||
"top_clk26m_clk";
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,75 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mt8186-mt6366-da7219-max98357.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Mediatek MT8186 with MT6366, DA7219 and MAX98357 ASoC sound card driver
|
||||
|
||||
maintainers:
|
||||
- Jiaxin Yu <jiaxin.yu@mediatek.com>
|
||||
|
||||
description:
|
||||
This binding describes the MT8186 sound card.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt8186-mt6366-da7219-max98357-sound
|
||||
|
||||
mediatek,platform:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
description: The phandle of MT8186 ASoC platform.
|
||||
|
||||
headset-codec:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
sound-dai:
|
||||
maxItems: 1
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
playback-codecs:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
sound-dai:
|
||||
items:
|
||||
- description: phandle of dp codec
|
||||
- description: phandle of l channel speaker codec
|
||||
- description: phandle of r channel speaker codec
|
||||
minItems: 2
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- mediatek,platform
|
||||
- headset-codec
|
||||
- playback-codecs
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
sound: mt8186-sound {
|
||||
compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound";
|
||||
mediatek,platform = <&afe>;
|
||||
pinctrl-names = "aud_clk_mosi_off",
|
||||
"aud_clk_mosi_on";
|
||||
pinctrl-0 = <&aud_clk_mosi_off>;
|
||||
pinctrl-1 = <&aud_clk_mosi_on>;
|
||||
|
||||
headset-codec {
|
||||
sound-dai = <&da7219>;
|
||||
};
|
||||
|
||||
playback-codecs {
|
||||
sound-dai = <&anx_bridge_dp>,
|
||||
<&max98357a>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,75 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mt8186-mt6366-rt1019-rt5682s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Mediatek MT8186 with MT6366, RT1019 and RT5682S ASoC sound card driver
|
||||
|
||||
maintainers:
|
||||
- Jiaxin Yu <jiaxin.yu@mediatek.com>
|
||||
|
||||
description:
|
||||
This binding describes the MT8186 sound card.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt8186-mt6366-rt1019-rt5682s-sound
|
||||
|
||||
mediatek,platform:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
description: The phandle of MT8186 ASoC platform.
|
||||
|
||||
headset-codec:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
sound-dai:
|
||||
maxItems: 1
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
playback-codecs:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
sound-dai:
|
||||
items:
|
||||
- description: phandle of dp codec
|
||||
- description: phandle of l channel speaker codec
|
||||
- description: phandle of r channel speaker codec
|
||||
minItems: 2
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- mediatek,platform
|
||||
- headset-codec
|
||||
- playback-codecs
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
sound: mt8186-sound {
|
||||
compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound";
|
||||
mediatek,platform = <&afe>;
|
||||
pinctrl-names = "aud_clk_mosi_off",
|
||||
"aud_clk_mosi_on";
|
||||
pinctrl-0 = <&aud_clk_mosi_off>;
|
||||
pinctrl-1 = <&aud_clk_mosi_on>;
|
||||
|
||||
headset-codec {
|
||||
sound-dai = <&rt5682s>;
|
||||
};
|
||||
|
||||
playback-codecs {
|
||||
sound-dai = <&it6505dptx>,
|
||||
<&rt1019p>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -127,7 +127,7 @@ properties:
|
||||
|
||||
gpio@42:
|
||||
type: object
|
||||
$ref: ../gpio/qcom,wcd934x-gpio.yaml#
|
||||
$ref: /schemas/gpio/qcom,wcd934x-gpio.yaml#
|
||||
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
|
@ -47,6 +47,7 @@ properties:
|
||||
description: The bias voltage to be used in mVolts. The voltage can take
|
||||
values from 1.25V to 3V by 250mV steps. If this node is not mentioned
|
||||
or the value is unknown, then the value is set to 1.25V.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
enum: [ 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000 ]
|
||||
|
||||
lrclk-strength:
|
||||
|
@ -1,72 +0,0 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2020-2022 Texas Instruments Incorporated
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/sound/tas2780.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Texas Instruments TAS2780 Smart PA
|
||||
|
||||
maintainers:
|
||||
- Raphael Xu <raphael-xu@ti.com>
|
||||
|
||||
description: |
|
||||
The TAS2780 is a mono, digital input Class-D audio amplifier optimized for
|
||||
efficiently driving high peak power into small loudspeakers.
|
||||
Integrated speaker voltage and current sense provides for
|
||||
real time monitoring of loudspeaker behavior.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,tas2780
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: |
|
||||
I2C address of the device can be between 0x38 to 0x45.
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO used to reset the device.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
ti,imon-slot-no:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: TDM TX current sense time slot.
|
||||
|
||||
ti,vmon-slot-no:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: TDM TX voltage sense time slot.
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
codec: codec@38 {
|
||||
compatible = "ti,tas2780";
|
||||
reg = <0x38>;
|
||||
#sound-dai-cells = <1>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <14>;
|
||||
reset-gpios = <&gpio1 15 0>;
|
||||
shutdown-gpios = <&gpio1 15 0>;
|
||||
ti,imon-slot-no = <0>;
|
||||
ti,vmon-slot-no = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -52,10 +52,6 @@ properties:
|
||||
DCVDD-supply:
|
||||
description: Digital core supply regulator for the DCVDD pin.
|
||||
|
||||
spi-max-frequency: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- reg
|
||||
- compatible
|
||||
@ -64,6 +60,11 @@ required:
|
||||
- DBVDD-supply
|
||||
- DCVDD-supply
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
|
@ -291,6 +291,44 @@ int acpi_get_local_address(acpi_handle handle, u32 *addr)
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_get_local_address);
|
||||
|
||||
#define ACPI_MAX_SUB_BUF_SIZE 9
|
||||
|
||||
const char *acpi_get_subsystem_id(acpi_handle handle)
|
||||
{
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *obj;
|
||||
acpi_status status;
|
||||
const char *sub;
|
||||
size_t len;
|
||||
|
||||
status = acpi_evaluate_object(handle, METHOD_NAME__SUB, NULL, &buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_handle_debug(handle, "Reading ACPI _SUB failed: %#x\n", status);
|
||||
return ERR_PTR(-ENODATA);
|
||||
}
|
||||
|
||||
obj = buffer.pointer;
|
||||
if (obj->type == ACPI_TYPE_STRING) {
|
||||
len = strlen(obj->string.pointer);
|
||||
if (len < ACPI_MAX_SUB_BUF_SIZE && len > 0) {
|
||||
sub = kstrdup(obj->string.pointer, GFP_KERNEL);
|
||||
if (!sub)
|
||||
sub = ERR_PTR(-ENOMEM);
|
||||
} else {
|
||||
acpi_handle_err(handle, "ACPI _SUB Length %zu is Invalid\n", len);
|
||||
sub = ERR_PTR(-ENODATA);
|
||||
}
|
||||
} else {
|
||||
acpi_handle_warn(handle, "Warning ACPI _SUB did not return a string\n");
|
||||
sub = ERR_PTR(-ENODATA);
|
||||
}
|
||||
|
||||
acpi_os_free(buffer.pointer);
|
||||
|
||||
return sub;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_get_subsystem_id);
|
||||
|
||||
acpi_status
|
||||
acpi_evaluate_reference(acpi_handle handle,
|
||||
acpi_string pathname,
|
||||
|
@ -2725,6 +2725,9 @@ void cs_dsp_stop(struct cs_dsp *dsp)
|
||||
|
||||
mutex_lock(&dsp->pwr_lock);
|
||||
|
||||
if (dsp->client_ops->pre_stop)
|
||||
dsp->client_ops->pre_stop(dsp);
|
||||
|
||||
dsp->running = false;
|
||||
|
||||
if (dsp->ops->stop_core)
|
||||
@ -3177,6 +3180,110 @@ static const struct cs_dsp_ops cs_dsp_halo_ops = {
|
||||
.stop_core = cs_dsp_halo_stop_core,
|
||||
};
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk_write() - Format data to a DSP memory chunk
|
||||
* @ch: Pointer to the chunk structure
|
||||
* @nbits: Number of bits to write
|
||||
* @val: Value to write
|
||||
*
|
||||
* This function sequentially writes values into the format required for DSP
|
||||
* memory, it handles both inserting of the padding bytes and converting to
|
||||
* big endian. Note that data is only committed to the chunk when a whole DSP
|
||||
* words worth of data is available.
|
||||
*
|
||||
* Return: Zero for success, a negative number on error.
|
||||
*/
|
||||
int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val)
|
||||
{
|
||||
int nwrite, i;
|
||||
|
||||
nwrite = min(CS_DSP_DATA_WORD_BITS - ch->cachebits, nbits);
|
||||
|
||||
ch->cache <<= nwrite;
|
||||
ch->cache |= val >> (nbits - nwrite);
|
||||
ch->cachebits += nwrite;
|
||||
nbits -= nwrite;
|
||||
|
||||
if (ch->cachebits == CS_DSP_DATA_WORD_BITS) {
|
||||
if (cs_dsp_chunk_end(ch))
|
||||
return -ENOSPC;
|
||||
|
||||
ch->cache &= 0xFFFFFF;
|
||||
for (i = 0; i < sizeof(ch->cache); i++, ch->cache <<= BITS_PER_BYTE)
|
||||
*ch->data++ = (ch->cache & 0xFF000000) >> CS_DSP_DATA_WORD_BITS;
|
||||
|
||||
ch->bytes += sizeof(ch->cache);
|
||||
ch->cachebits = 0;
|
||||
}
|
||||
|
||||
if (nbits)
|
||||
return cs_dsp_chunk_write(ch, nbits, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs_dsp_chunk_write);
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk_flush() - Pad remaining data with zero and commit to chunk
|
||||
* @ch: Pointer to the chunk structure
|
||||
*
|
||||
* As cs_dsp_chunk_write only writes data when a whole DSP word is ready to
|
||||
* be written out it is possible that some data will remain in the cache, this
|
||||
* function will pad that data with zeros upto a whole DSP word and write out.
|
||||
*
|
||||
* Return: Zero for success, a negative number on error.
|
||||
*/
|
||||
int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch)
|
||||
{
|
||||
if (!ch->cachebits)
|
||||
return 0;
|
||||
|
||||
return cs_dsp_chunk_write(ch, CS_DSP_DATA_WORD_BITS - ch->cachebits, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs_dsp_chunk_flush);
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk_read() - Parse data from a DSP memory chunk
|
||||
* @ch: Pointer to the chunk structure
|
||||
* @nbits: Number of bits to read
|
||||
*
|
||||
* This function sequentially reads values from a DSP memory formatted buffer,
|
||||
* it handles both removing of the padding bytes and converting from big endian.
|
||||
*
|
||||
* Return: A negative number is returned on error, otherwise the read value.
|
||||
*/
|
||||
int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits)
|
||||
{
|
||||
int nread, i;
|
||||
u32 result;
|
||||
|
||||
if (!ch->cachebits) {
|
||||
if (cs_dsp_chunk_end(ch))
|
||||
return -ENOSPC;
|
||||
|
||||
ch->cache = 0;
|
||||
ch->cachebits = CS_DSP_DATA_WORD_BITS;
|
||||
|
||||
for (i = 0; i < sizeof(ch->cache); i++, ch->cache <<= BITS_PER_BYTE)
|
||||
ch->cache |= *ch->data++;
|
||||
|
||||
ch->bytes += sizeof(ch->cache);
|
||||
}
|
||||
|
||||
nread = min(ch->cachebits, nbits);
|
||||
nbits -= nread;
|
||||
|
||||
result = ch->cache >> ((sizeof(ch->cache) * BITS_PER_BYTE) - nread);
|
||||
ch->cache <<= nread;
|
||||
ch->cachebits -= nread;
|
||||
|
||||
if (nbits)
|
||||
result = (result << nbits) | cs_dsp_chunk_read(ch, nbits);
|
||||
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs_dsp_chunk_read);
|
||||
|
||||
MODULE_DESCRIPTION("Cirrus Logic DSP Support");
|
||||
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -762,6 +762,7 @@ static inline u64 acpi_arch_get_root_pointer(void)
|
||||
#endif
|
||||
|
||||
int acpi_get_local_address(acpi_handle handle, u32 *addr);
|
||||
const char *acpi_get_subsystem_id(acpi_handle handle);
|
||||
|
||||
#else /* !CONFIG_ACPI */
|
||||
|
||||
@ -1023,6 +1024,11 @@ static inline int acpi_get_local_address(acpi_handle handle, u32 *addr)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline const char *acpi_get_subsystem_id(acpi_handle handle)
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline int acpi_register_wakeup_handler(int wake_irq,
|
||||
bool (*wakeup)(void *context), void *context)
|
||||
{
|
||||
|
@ -11,6 +11,7 @@
|
||||
#ifndef __CS_DSP_H
|
||||
#define __CS_DSP_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/list.h>
|
||||
@ -34,6 +35,7 @@
|
||||
#define CS_ADSP2_REGION_ALL (CS_ADSP2_REGION_0 | CS_ADSP2_REGION_1_9)
|
||||
|
||||
#define CS_DSP_DATA_WORD_SIZE 3
|
||||
#define CS_DSP_DATA_WORD_BITS (3 * BITS_PER_BYTE)
|
||||
|
||||
#define CS_DSP_ACKED_CTL_TIMEOUT_MS 100
|
||||
#define CS_DSP_ACKED_CTL_N_QUICKPOLLS 10
|
||||
@ -189,7 +191,8 @@ struct cs_dsp {
|
||||
* @control_remove: Called under the pwr_lock when a control is destroyed
|
||||
* @pre_run: Called under the pwr_lock by cs_dsp_run() before the core is started
|
||||
* @post_run: Called under the pwr_lock by cs_dsp_run() after the core is started
|
||||
* @post_stop: Called under the pwr_lock by cs_dsp_stop()
|
||||
* @pre_stop: Called under the pwr_lock by cs_dsp_stop() before the core is stopped
|
||||
* @post_stop: Called under the pwr_lock by cs_dsp_stop() after the core is stopped
|
||||
* @watchdog_expired: Called when a watchdog expiry is detected
|
||||
*
|
||||
* These callbacks give the cs_dsp client an opportunity to respond to events
|
||||
@ -200,6 +203,7 @@ struct cs_dsp_client_ops {
|
||||
void (*control_remove)(struct cs_dsp_coeff_ctl *ctl);
|
||||
int (*pre_run)(struct cs_dsp *dsp);
|
||||
int (*post_run)(struct cs_dsp *dsp);
|
||||
void (*pre_stop)(struct cs_dsp *dsp);
|
||||
void (*post_stop)(struct cs_dsp *dsp);
|
||||
void (*watchdog_expired)(struct cs_dsp *dsp);
|
||||
};
|
||||
@ -250,4 +254,75 @@ struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
|
||||
|
||||
const char *cs_dsp_mem_region_name(unsigned int type);
|
||||
|
||||
/**
|
||||
* struct cs_dsp_chunk - Describes a buffer holding data formatted for the DSP
|
||||
* @data: Pointer to underlying buffer memory
|
||||
* @max: Pointer to end of the buffer memory
|
||||
* @bytes: Number of bytes read/written into the memory chunk
|
||||
* @cache: Temporary holding data as it is formatted
|
||||
* @cachebits: Number of bits of data currently in cache
|
||||
*/
|
||||
struct cs_dsp_chunk {
|
||||
u8 *data;
|
||||
u8 *max;
|
||||
int bytes;
|
||||
|
||||
u32 cache;
|
||||
int cachebits;
|
||||
};
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk() - Create a DSP memory chunk
|
||||
* @data: Pointer to the buffer that will be used to store data
|
||||
* @size: Size of the buffer in bytes
|
||||
*
|
||||
* Return: A cs_dsp_chunk structure
|
||||
*/
|
||||
static inline struct cs_dsp_chunk cs_dsp_chunk(void *data, int size)
|
||||
{
|
||||
struct cs_dsp_chunk ch = {
|
||||
.data = data,
|
||||
.max = data + size,
|
||||
};
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk_end() - Check if a DSP memory chunk is full
|
||||
* @ch: Pointer to the chunk structure
|
||||
*
|
||||
* Return: True if the whole buffer has been read/written
|
||||
*/
|
||||
static inline bool cs_dsp_chunk_end(struct cs_dsp_chunk *ch)
|
||||
{
|
||||
return ch->data == ch->max;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk_bytes() - Number of bytes written/read from a DSP memory chunk
|
||||
* @ch: Pointer to the chunk structure
|
||||
*
|
||||
* Return: Number of bytes read/written to the buffer
|
||||
*/
|
||||
static inline int cs_dsp_chunk_bytes(struct cs_dsp_chunk *ch)
|
||||
{
|
||||
return ch->bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk_valid_addr() - Check if an address is in a DSP memory chunk
|
||||
* @ch: Pointer to the chunk structure
|
||||
*
|
||||
* Return: True if the given address is within the buffer
|
||||
*/
|
||||
static inline bool cs_dsp_chunk_valid_addr(struct cs_dsp_chunk *ch, void *addr)
|
||||
{
|
||||
return (u8 *)addr >= ch->data && (u8 *)addr < ch->max;
|
||||
}
|
||||
|
||||
int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val);
|
||||
int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch);
|
||||
int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits);
|
||||
|
||||
#endif
|
||||
|
@ -52,6 +52,8 @@
|
||||
#define SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_ES BIT(6)
|
||||
/* bclk early start */
|
||||
#define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_ES BIT(7)
|
||||
/* mclk always on */
|
||||
#define SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_AON BIT(8)
|
||||
|
||||
/* DMIC max. four controllers for eight microphone channels */
|
||||
#define SOF_DAI_INTEL_DMIC_NUM_CTRL 4
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
/* SOF ABI version major, minor and patch numbers */
|
||||
#define SOF_ABI_MAJOR 3
|
||||
#define SOF_ABI_MINOR 22
|
||||
#define SOF_ABI_MINOR 23
|
||||
#define SOF_ABI_PATCH 0
|
||||
|
||||
/* SOF ABI version number. Format within 32bit word is MMmmmppp */
|
||||
|
@ -413,6 +413,11 @@ static const struct config_entry config_table[] = {
|
||||
.device = 0x7a50,
|
||||
},
|
||||
/* Alderlake-P */
|
||||
{
|
||||
.flags = FLAG_SOF,
|
||||
.device = 0x51c8,
|
||||
.codec_hid = &essx_83x6,
|
||||
},
|
||||
{
|
||||
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
|
||||
.device = 0x51c8,
|
||||
|
@ -9,12 +9,12 @@ endif
|
||||
|
||||
ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST),)
|
||||
# snd-soc-test-objs := soc-topology-test.o
|
||||
obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST) := soc-topology-test.o
|
||||
obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST) += soc-topology-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
|
||||
obj-$(CONFIG_SND_SOC_UTILS_KUNIT_TEST) += soc-utils-test.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
|
||||
|
@ -117,3 +117,13 @@ config SND_AMD_ACP_CONFIG
|
||||
driver modules to use
|
||||
|
||||
source "sound/soc/amd/acp/Kconfig"
|
||||
|
||||
config SND_SOC_AMD_RPL_ACP6x
|
||||
tristate "AMD Audio Coprocessor-v6.2 RPL support"
|
||||
depends on X86 && PCI
|
||||
help
|
||||
This option enables Audio Coprocessor i.e ACP v6.2 support on
|
||||
AMD RPL platform. By enabling this flag build will be
|
||||
triggered for ACP PCI driver.
|
||||
Say m if you have such a device.
|
||||
If unsure select "N".
|
||||
|
@ -17,3 +17,4 @@ obj-$(CONFIG_SND_SOC_AMD_ACP5x) += vangogh/
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP6x) += yc/
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP_COMMON) += acp/
|
||||
obj-$(CONFIG_SND_AMD_ACP_CONFIG) += snd-acp-config.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_RPL_ACP6x) += rpl/
|
||||
|
@ -29,7 +29,7 @@
|
||||
static struct platform_device *dmic_dev;
|
||||
static struct platform_device *pdev;
|
||||
|
||||
static const struct resource acp3x_res[] = {
|
||||
static const struct resource acp_res[] = {
|
||||
{
|
||||
.start = 0,
|
||||
.end = ACP3x_REG_END - ACP3x_REG_START,
|
||||
@ -70,42 +70,49 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
|
||||
ret = pci_request_regions(pci, "AMD ACP3x audio");
|
||||
if (ret < 0) {
|
||||
dev_err(&pci->dev, "pci_request_regions failed\n");
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto disable_pci;
|
||||
}
|
||||
|
||||
pci_set_master(pci);
|
||||
|
||||
res_acp = acp_res;
|
||||
num_res = ARRAY_SIZE(acp_res);
|
||||
|
||||
switch (pci->revision) {
|
||||
case 0x01:
|
||||
res_acp = acp3x_res;
|
||||
num_res = ARRAY_SIZE(acp3x_res);
|
||||
chip->name = "acp_asoc_renoir";
|
||||
chip->acp_rev = ACP3X_DEV;
|
||||
break;
|
||||
case 0x6f:
|
||||
res_acp = acp3x_res;
|
||||
num_res = ARRAY_SIZE(acp3x_res);
|
||||
chip->name = "acp_asoc_rembrandt";
|
||||
chip->acp_rev = ACP6X_DEV;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto release_regions;
|
||||
}
|
||||
|
||||
dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
|
||||
if (IS_ERR(dmic_dev)) {
|
||||
dev_err(dev, "failed to create DMIC device\n");
|
||||
return PTR_ERR(dmic_dev);
|
||||
ret = PTR_ERR(dmic_dev);
|
||||
goto release_regions;
|
||||
}
|
||||
|
||||
addr = pci_resource_start(pci, 0);
|
||||
chip->base = devm_ioremap(&pci->dev, addr, pci_resource_len(pci, 0));
|
||||
if (!chip->base) {
|
||||
ret = -ENOMEM;
|
||||
goto release_regions;
|
||||
}
|
||||
|
||||
res = devm_kzalloc(&pci->dev, sizeof(struct resource) * num_res, GFP_KERNEL);
|
||||
if (!res) {
|
||||
platform_device_unregister(dmic_dev);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto release_regions;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_res; i++, res_acp++) {
|
||||
@ -134,8 +141,16 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
|
||||
dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name);
|
||||
platform_device_unregister(dmic_dev);
|
||||
ret = PTR_ERR(pdev);
|
||||
goto release_regions;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
release_regions:
|
||||
pci_release_regions(pci);
|
||||
disable_pci:
|
||||
pci_disable_device(pci);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
@ -94,19 +94,19 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
|
||||
struct acp_resource *rsrc = adata->rsrc;
|
||||
struct acp_stream *stream;
|
||||
u16 i2s_flag = 0;
|
||||
u32 val, val1, i;
|
||||
u32 ext_intr_stat, ext_intr_stat1, i;
|
||||
|
||||
if (!adata)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (adata->rsrc->no_of_ctrls == 2)
|
||||
val1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));
|
||||
ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));
|
||||
|
||||
val = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
|
||||
ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
|
||||
|
||||
for (i = 0; i < ACP_MAX_STREAM; i++) {
|
||||
stream = adata->stream[i];
|
||||
if (stream && (val & stream->irq_bit)) {
|
||||
if (stream && (ext_intr_stat & stream->irq_bit)) {
|
||||
writel(stream->irq_bit,
|
||||
ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
|
||||
snd_pcm_period_elapsed(stream->substream);
|
||||
@ -114,7 +114,7 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
|
||||
break;
|
||||
}
|
||||
if (adata->rsrc->no_of_ctrls == 2) {
|
||||
if (stream && (val1 & stream->irq_bit)) {
|
||||
if (stream && (ext_intr_stat1 & stream->irq_bit)) {
|
||||
writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(adata,
|
||||
(rsrc->irqp_used - 1)));
|
||||
snd_pcm_period_elapsed(stream->substream);
|
||||
@ -258,13 +258,6 @@ static int acp_dma_new(struct snd_soc_component *component,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acp_dma_mmap(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
return snd_pcm_lib_default_mmap(substream, vma);
|
||||
}
|
||||
|
||||
static int acp_dma_close(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
@ -288,7 +281,6 @@ static const struct snd_soc_component_driver acp_pcm_component = {
|
||||
.close = acp_dma_close,
|
||||
.hw_params = acp_dma_hw_params,
|
||||
.pointer = acp_dma_pointer,
|
||||
.mmap = acp_dma_mmap,
|
||||
.pcm_construct = acp_dma_new,
|
||||
.legacy_dai_naming = 1,
|
||||
};
|
||||
|
5
sound/soc/amd/rpl/Makefile
Normal file
5
sound/soc/amd/rpl/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# RPL platform Support
|
||||
snd-rpl-pci-acp6x-objs := rpl-pci-acp6x.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_AMD_RPL_ACP6x) += snd-rpl-pci-acp6x.o
|
227
sound/soc/amd/rpl/rpl-pci-acp6x.c
Normal file
227
sound/soc/amd/rpl/rpl-pci-acp6x.c
Normal file
@ -0,0 +1,227 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* AMD RPL ACP PCI Driver
|
||||
*
|
||||
* Copyright 2022 Advanced Micro Devices, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "rpl_acp6x.h"
|
||||
|
||||
struct rpl_dev_data {
|
||||
void __iomem *acp6x_base;
|
||||
};
|
||||
|
||||
static int rpl_power_on(void __iomem *acp_base)
|
||||
{
|
||||
u32 val;
|
||||
int timeout;
|
||||
|
||||
val = rpl_acp_readl(acp_base + ACP_PGFSM_STATUS);
|
||||
|
||||
if (!val)
|
||||
return val;
|
||||
|
||||
if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS)
|
||||
rpl_acp_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
|
||||
timeout = 0;
|
||||
while (++timeout < 500) {
|
||||
val = rpl_acp_readl(acp_base + ACP_PGFSM_STATUS);
|
||||
if (!val)
|
||||
return 0;
|
||||
udelay(1);
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int rpl_reset(void __iomem *acp_base)
|
||||
{
|
||||
u32 val;
|
||||
int timeout;
|
||||
|
||||
rpl_acp_writel(1, acp_base + ACP_SOFT_RESET);
|
||||
timeout = 0;
|
||||
while (++timeout < 500) {
|
||||
val = rpl_acp_readl(acp_base + ACP_SOFT_RESET);
|
||||
if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK)
|
||||
break;
|
||||
cpu_relax();
|
||||
}
|
||||
rpl_acp_writel(0, acp_base + ACP_SOFT_RESET);
|
||||
timeout = 0;
|
||||
while (++timeout < 500) {
|
||||
val = rpl_acp_readl(acp_base + ACP_SOFT_RESET);
|
||||
if (!val)
|
||||
return 0;
|
||||
cpu_relax();
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int rpl_init(void __iomem *acp_base)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* power on */
|
||||
ret = rpl_power_on(acp_base);
|
||||
if (ret) {
|
||||
pr_err("ACP power on failed\n");
|
||||
return ret;
|
||||
}
|
||||
rpl_acp_writel(0x01, acp_base + ACP_CONTROL);
|
||||
/* Reset */
|
||||
ret = rpl_reset(acp_base);
|
||||
if (ret) {
|
||||
pr_err("ACP reset failed\n");
|
||||
return ret;
|
||||
}
|
||||
rpl_acp_writel(0x03, acp_base + ACP_CLKMUX_SEL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpl_deinit(void __iomem *acp_base)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Reset */
|
||||
ret = rpl_reset(acp_base);
|
||||
if (ret) {
|
||||
pr_err("ACP reset failed\n");
|
||||
return ret;
|
||||
}
|
||||
rpl_acp_writel(0x00, acp_base + ACP_CLKMUX_SEL);
|
||||
rpl_acp_writel(0x00, acp_base + ACP_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_rpl_probe(struct pci_dev *pci,
|
||||
const struct pci_device_id *pci_id)
|
||||
{
|
||||
struct rpl_dev_data *adata;
|
||||
u32 addr;
|
||||
int ret;
|
||||
|
||||
/* RPL device check */
|
||||
switch (pci->revision) {
|
||||
case 0x62:
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&pci->dev, "acp6x pci device not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (pci_enable_device(pci)) {
|
||||
dev_err(&pci->dev, "pci_enable_device failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = pci_request_regions(pci, "AMD ACP6x audio");
|
||||
if (ret < 0) {
|
||||
dev_err(&pci->dev, "pci_request_regions failed\n");
|
||||
goto disable_pci;
|
||||
}
|
||||
|
||||
adata = devm_kzalloc(&pci->dev, sizeof(struct rpl_dev_data),
|
||||
GFP_KERNEL);
|
||||
if (!adata) {
|
||||
ret = -ENOMEM;
|
||||
goto release_regions;
|
||||
}
|
||||
|
||||
addr = pci_resource_start(pci, 0);
|
||||
adata->acp6x_base = devm_ioremap(&pci->dev, addr,
|
||||
pci_resource_len(pci, 0));
|
||||
if (!adata->acp6x_base) {
|
||||
ret = -ENOMEM;
|
||||
goto release_regions;
|
||||
}
|
||||
pci_set_master(pci);
|
||||
pci_set_drvdata(pci, adata);
|
||||
ret = rpl_init(adata->acp6x_base);
|
||||
if (ret)
|
||||
goto release_regions;
|
||||
pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS);
|
||||
pm_runtime_use_autosuspend(&pci->dev);
|
||||
pm_runtime_put_noidle(&pci->dev);
|
||||
pm_runtime_allow(&pci->dev);
|
||||
|
||||
return 0;
|
||||
release_regions:
|
||||
pci_release_regions(pci);
|
||||
disable_pci:
|
||||
pci_disable_device(pci);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused snd_rpl_suspend(struct device *dev)
|
||||
{
|
||||
struct rpl_dev_data *adata;
|
||||
int ret;
|
||||
|
||||
adata = dev_get_drvdata(dev);
|
||||
ret = rpl_deinit(adata->acp6x_base);
|
||||
if (ret)
|
||||
dev_err(dev, "ACP de-init failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused snd_rpl_resume(struct device *dev)
|
||||
{
|
||||
struct rpl_dev_data *adata;
|
||||
int ret;
|
||||
|
||||
adata = dev_get_drvdata(dev);
|
||||
ret = rpl_init(adata->acp6x_base);
|
||||
if (ret)
|
||||
dev_err(dev, "ACP init failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rpl_pm = {
|
||||
SET_RUNTIME_PM_OPS(snd_rpl_suspend, snd_rpl_resume, NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(snd_rpl_suspend, snd_rpl_resume)
|
||||
};
|
||||
|
||||
static void snd_rpl_remove(struct pci_dev *pci)
|
||||
{
|
||||
struct rpl_dev_data *adata;
|
||||
int ret;
|
||||
|
||||
adata = pci_get_drvdata(pci);
|
||||
ret = rpl_deinit(adata->acp6x_base);
|
||||
if (ret)
|
||||
dev_err(&pci->dev, "ACP de-init failed\n");
|
||||
pm_runtime_forbid(&pci->dev);
|
||||
pm_runtime_get_noresume(&pci->dev);
|
||||
pci_release_regions(pci);
|
||||
pci_disable_device(pci);
|
||||
}
|
||||
|
||||
static const struct pci_device_id snd_rpl_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID),
|
||||
.class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
|
||||
.class_mask = 0xffffff },
|
||||
{ 0, },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, snd_rpl_ids);
|
||||
|
||||
static struct pci_driver rpl_acp6x_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = snd_rpl_ids,
|
||||
.probe = snd_rpl_probe,
|
||||
.remove = snd_rpl_remove,
|
||||
.driver = {
|
||||
.pm = &rpl_pm,
|
||||
}
|
||||
};
|
||||
|
||||
module_pci_driver(rpl_acp6x_driver);
|
||||
|
||||
MODULE_DESCRIPTION("AMD ACP RPL PCI driver");
|
||||
MODULE_LICENSE("GPL v2");
|
36
sound/soc/amd/rpl/rpl_acp6x.h
Normal file
36
sound/soc/amd/rpl/rpl_acp6x.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* AMD ACP Driver
|
||||
*
|
||||
* Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "rpl_acp6x_chip_offset_byte.h"
|
||||
|
||||
#define ACP_DEVICE_ID 0x15E2
|
||||
#define ACP6x_PHY_BASE_ADDRESS 0x1240000
|
||||
|
||||
#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001
|
||||
#define ACP_PGFSM_CNTL_POWER_ON_MASK 1
|
||||
#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0
|
||||
#define ACP_PGFSM_STATUS_MASK 3
|
||||
#define ACP_POWERED_ON 0
|
||||
#define ACP_POWER_ON_IN_PROGRESS 1
|
||||
#define ACP_POWERED_OFF 2
|
||||
#define ACP_POWER_OFF_IN_PROGRESS 3
|
||||
|
||||
#define DELAY_US 5
|
||||
#define ACP_COUNTER 20000
|
||||
|
||||
/* time in ms for runtime suspend delay */
|
||||
#define ACP_SUSPEND_DELAY_MS 2000
|
||||
|
||||
static inline u32 rpl_acp_readl(void __iomem *base_addr)
|
||||
{
|
||||
return readl(base_addr - ACP6x_PHY_BASE_ADDRESS);
|
||||
}
|
||||
|
||||
static inline void rpl_acp_writel(u32 val, void __iomem *base_addr)
|
||||
{
|
||||
writel(val, base_addr - ACP6x_PHY_BASE_ADDRESS);
|
||||
}
|
30
sound/soc/amd/rpl/rpl_acp6x_chip_offset_byte.h
Normal file
30
sound/soc/amd/rpl/rpl_acp6x_chip_offset_byte.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* AMD ACP 6.2 Register Documentation
|
||||
*
|
||||
* Copyright 2022 Advanced Micro Devices, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _rpl_acp6x_OFFSET_HEADER
|
||||
#define _rpl_acp6x_OFFSET_HEADER
|
||||
|
||||
/* Registers from ACP_CLKRST block */
|
||||
#define ACP_SOFT_RESET 0x1241000
|
||||
#define ACP_CONTROL 0x1241004
|
||||
#define ACP_STATUS 0x1241008
|
||||
#define ACP_DYNAMIC_CG_MASTER_CONTROL 0x1241010
|
||||
#define ACP_PGFSM_CONTROL 0x124101C
|
||||
#define ACP_PGFSM_STATUS 0x1241020
|
||||
#define ACP_CLKMUX_SEL 0x1241024
|
||||
|
||||
/* Registers from ACP_AON block */
|
||||
#define ACP_PME_EN 0x1241400
|
||||
#define ACP_DEVICE_STATE 0x1241404
|
||||
#define AZ_DEVICE_STATE 0x1241408
|
||||
#define ACP_PIN_CONFIG 0x1241440
|
||||
#define ACP_PAD_PULLUP_CTRL 0x1241444
|
||||
#define ACP_PAD_PULLDOWN_CTRL 0x1241448
|
||||
#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x124144C
|
||||
#define ACP_PAD_SCHMEN_CTRL 0x1241450
|
||||
|
||||
#endif
|
@ -178,8 +178,7 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream,
|
||||
ret = 0;
|
||||
for (i = 0; i < num_codecs; i++) {
|
||||
codec_dai = asoc_rtd_to_codec(rtd, i);
|
||||
if ((strcmp(codec_dai->name, "spi-VLV1776:00") == 0) ||
|
||||
(strcmp(codec_dai->name, "spi-VLV1776:01") == 0)) {
|
||||
if (strcmp(codec_dai->name, "cs35l41-pcm") == 0) {
|
||||
switch (params_rate(params)) {
|
||||
case 48000:
|
||||
bclk_val = 1536000;
|
||||
|
@ -105,28 +105,14 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21AW"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21CM"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21AX"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21BN"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21BQ"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21CN"),
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -157,20 +143,6 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21CL"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21D8"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21D9"),
|
||||
}
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -159,7 +159,7 @@ static int snd_acp6x_probe(struct pci_dev *pci,
|
||||
case 0x6f:
|
||||
break;
|
||||
default:
|
||||
dev_err(&pci->dev, "acp6x pci device not found\n");
|
||||
dev_dbg(&pci->dev, "acp6x pci device not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (pci_enable_device(pci)) {
|
||||
|
@ -762,7 +762,6 @@ static int atmel_ssc_trigger(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int atmel_ssc_suspend(struct snd_soc_component *component)
|
||||
{
|
||||
struct atmel_ssc_info *ssc_p;
|
||||
@ -821,10 +820,6 @@ static int atmel_ssc_resume(struct snd_soc_component *component)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_PM */
|
||||
# define atmel_ssc_suspend NULL
|
||||
# define atmel_ssc_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
|
||||
@ -859,8 +854,8 @@ static struct snd_soc_dai_driver atmel_ssc_dai = {
|
||||
|
||||
static const struct snd_soc_component_driver atmel_ssc_component = {
|
||||
.name = "atmel-ssc",
|
||||
.suspend = atmel_ssc_suspend,
|
||||
.resume = atmel_ssc_resume,
|
||||
.suspend = pm_ptr(atmel_ssc_suspend),
|
||||
.resume = pm_ptr(atmel_ssc_resume),
|
||||
.legacy_dai_naming = 1,
|
||||
};
|
||||
|
||||
|
@ -221,11 +221,11 @@ struct mchp_spdifrx_user_data {
|
||||
};
|
||||
|
||||
struct mchp_spdifrx_mixer_control {
|
||||
struct mchp_spdifrx_ch_stat ch_stat[SPDIFRX_CHANNELS];
|
||||
struct mchp_spdifrx_user_data user_data[SPDIFRX_CHANNELS];
|
||||
bool ulock;
|
||||
bool badf;
|
||||
bool signal;
|
||||
struct mchp_spdifrx_ch_stat ch_stat[SPDIFRX_CHANNELS];
|
||||
struct mchp_spdifrx_user_data user_data[SPDIFRX_CHANNELS];
|
||||
bool ulock;
|
||||
bool badf;
|
||||
bool signal;
|
||||
};
|
||||
|
||||
struct mchp_spdifrx_dev {
|
||||
@ -288,15 +288,17 @@ static void mchp_spdifrx_isr_blockend_en(struct mchp_spdifrx_dev *dev)
|
||||
spin_unlock_irqrestore(&dev->blockend_lock, flags);
|
||||
}
|
||||
|
||||
/* called from atomic context only */
|
||||
/* called from atomic/non-atomic context */
|
||||
static void mchp_spdifrx_isr_blockend_dis(struct mchp_spdifrx_dev *dev)
|
||||
{
|
||||
spin_lock(&dev->blockend_lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->blockend_lock, flags);
|
||||
dev->blockend_refcount--;
|
||||
/* don't enable BLOCKEND interrupt if it's already enabled */
|
||||
if (dev->blockend_refcount == 0)
|
||||
regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_BLOCKEND);
|
||||
spin_unlock(&dev->blockend_lock);
|
||||
spin_unlock_irqrestore(&dev->blockend_lock, flags);
|
||||
}
|
||||
|
||||
static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id)
|
||||
@ -575,6 +577,7 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,
|
||||
if (ret <= 0) {
|
||||
dev_dbg(dev->dev, "user data for channel %d timeout\n",
|
||||
channel);
|
||||
mchp_spdifrx_isr_blockend_dis(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,6 @@ struct mchp_spdiftx_dev {
|
||||
struct clk *pclk;
|
||||
struct clk *gclk;
|
||||
unsigned int fmt;
|
||||
const struct mchp_i2s_caps *caps;
|
||||
int gclk_enabled:1;
|
||||
};
|
||||
|
||||
@ -341,12 +340,10 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
|
||||
ret = regmap_write(dev->regmap, SPDIFTX_MR, mr);
|
||||
spin_unlock(&ctrl->lock);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
dev_err(dev->dev, "unable to disable TX: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mchp_spdiftx_hw_params(struct snd_pcm_substream *substream,
|
||||
@ -763,12 +760,10 @@ static const struct of_device_id mchp_spdiftx_dt_ids[] = {
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, mchp_spdiftx_dt_ids);
|
||||
|
||||
static int mchp_spdiftx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *match;
|
||||
struct mchp_spdiftx_dev *dev;
|
||||
struct resource *mem;
|
||||
struct regmap *regmap;
|
||||
@ -782,11 +777,6 @@ static int mchp_spdiftx_probe(struct platform_device *pdev)
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Get hardware capabilities. */
|
||||
match = of_match_node(mchp_spdiftx_dt_ids, np);
|
||||
if (match)
|
||||
dev->caps = match->data;
|
||||
|
||||
/* Map I/O registers. */
|
||||
base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
|
||||
if (IS_ERR(base))
|
||||
@ -848,12 +838,10 @@ static int mchp_spdiftx_probe(struct platform_device *pdev)
|
||||
err = devm_snd_soc_register_component(&pdev->dev,
|
||||
&mchp_spdiftx_component,
|
||||
&mchp_spdiftx_dai, 1);
|
||||
if (err) {
|
||||
if (err)
|
||||
dev_err(&pdev->dev, "failed to register component: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct platform_driver mchp_spdiftx_driver = {
|
||||
|
@ -6,6 +6,7 @@
|
||||
//
|
||||
// Author: David Rhodes <david.rhodes@cirrus.com>
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
@ -1142,6 +1143,30 @@ err_dsp:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs35l41_acpi_get_name(struct cs35l41_private *cs35l41)
|
||||
{
|
||||
acpi_handle handle = ACPI_HANDLE(cs35l41->dev);
|
||||
const char *sub;
|
||||
|
||||
/* If there is no ACPI_HANDLE, there is no ACPI for this system, return 0 */
|
||||
if (!handle)
|
||||
return 0;
|
||||
|
||||
sub = acpi_get_subsystem_id(handle);
|
||||
if (IS_ERR(sub)) {
|
||||
/* If bad ACPI, return 0 and fallback to legacy firmware path, otherwise fail */
|
||||
if (PTR_ERR(sub) == -ENODATA)
|
||||
return 0;
|
||||
else
|
||||
return PTR_ERR(sub);
|
||||
}
|
||||
|
||||
cs35l41->dsp.system_name = sub;
|
||||
dev_dbg(cs35l41->dev, "Subsystem ID: %s\n", cs35l41->dsp.system_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg)
|
||||
{
|
||||
u32 regid, reg_revid, i, mtl_revid, int_status, chipid_match;
|
||||
@ -1270,6 +1295,10 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = cs35l41_acpi_get_name(cs35l41);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = cs35l41_dsp_init(cs35l41);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
@ -1316,6 +1345,7 @@ void cs35l41_remove(struct cs35l41_private *cs35l41)
|
||||
pm_runtime_disable(cs35l41->dev);
|
||||
|
||||
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
|
||||
kfree(cs35l41->dsp.system_name);
|
||||
wm_adsp2_remove(&cs35l41->dsp);
|
||||
cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
static int nau8821_configure_sysclk(struct nau8821 *nau8821,
|
||||
int clk_id, unsigned int freq);
|
||||
static bool nau8821_is_jack_inserted(struct regmap *regmap);
|
||||
|
||||
struct nau8821_fll {
|
||||
int mclk_src;
|
||||
@ -495,7 +496,33 @@ static int nau8821_output_dac_event(struct snd_soc_dapm_widget *w,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int system_clock_control(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *k, int event)
|
||||
{
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_dapm_to_component(w->dapm);
|
||||
struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_OFF(event)) {
|
||||
dev_dbg(nau8821->dev, "system clock control : POWER OFF\n");
|
||||
/* Set clock source to disable or internal clock before the
|
||||
* playback or capture end. Codec needs clock for Jack
|
||||
* detection and button press if jack inserted; otherwise,
|
||||
* the clock should be closed.
|
||||
*/
|
||||
if (nau8821_is_jack_inserted(nau8821->regmap)) {
|
||||
nau8821_configure_sysclk(nau8821,
|
||||
NAU8821_CLK_INTERNAL, 0);
|
||||
} else {
|
||||
nau8821_configure_sysclk(nau8821, NAU8821_CLK_DIS, 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget nau8821_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_SUPPLY("System Clock", SND_SOC_NOPM, 0, 0,
|
||||
system_clock_control, SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_SUPPLY("MICBIAS", NAU8821_R74_MIC_BIAS,
|
||||
NAU8821_MICBIAS_POWERUP_SFT, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY("DMIC Clock", SND_SOC_NOPM, 0, 0,
|
||||
@ -607,6 +634,9 @@ static const struct snd_soc_dapm_route nau8821_dapm_routes[] = {
|
||||
{"AIFTX", NULL, "ADCL Digital path"},
|
||||
{"AIFTX", NULL, "ADCR Digital path"},
|
||||
|
||||
{"AIFTX", NULL, "System Clock"},
|
||||
{"AIFRX", NULL, "System Clock"},
|
||||
|
||||
{"DDACL", NULL, "AIFRX"},
|
||||
{"DDACR", NULL, "AIFRX"},
|
||||
|
||||
@ -1699,15 +1729,6 @@ static int nau8821_i2c_probe(struct i2c_client *i2c)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nau8821_i2c_remove(struct i2c_client *i2c_client)
|
||||
{
|
||||
struct nau8821 *nau8821 = i2c_get_clientdata(i2c_client);
|
||||
|
||||
devm_free_irq(nau8821->dev, nau8821->irq, nau8821);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id nau8821_i2c_ids[] = {
|
||||
{ "nau8821", 0 },
|
||||
{ }
|
||||
@ -1737,7 +1758,6 @@ static struct i2c_driver nau8821_driver = {
|
||||
.acpi_match_table = ACPI_PTR(nau8821_acpi_match),
|
||||
},
|
||||
.probe_new = nau8821_i2c_probe,
|
||||
.remove = nau8821_i2c_remove,
|
||||
.id_table = nau8821_i2c_ids,
|
||||
};
|
||||
module_i2c_driver(nau8821_driver);
|
||||
|
@ -537,6 +537,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
|
||||
struct device *codec_dev = NULL;
|
||||
const char *codec_dai_name;
|
||||
const char *codec_dev_name;
|
||||
u32 asrc_fmt = 0;
|
||||
u32 width;
|
||||
int ret;
|
||||
|
||||
@ -829,8 +830,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
|
||||
goto asrc_fail;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(asrc_np, "fsl,asrc-format",
|
||||
&priv->asrc_format);
|
||||
ret = of_property_read_u32(asrc_np, "fsl,asrc-format", &asrc_fmt);
|
||||
priv->asrc_format = (__force snd_pcm_format_t)asrc_fmt;
|
||||
if (ret) {
|
||||
/* Fallback to old binding; translate to asrc_format */
|
||||
ret = of_property_read_u32(asrc_np, "fsl,asrc-width",
|
||||
|
@ -1066,6 +1066,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
|
||||
struct resource *res;
|
||||
void __iomem *regs;
|
||||
int irq, ret, i;
|
||||
u32 asrc_fmt = 0;
|
||||
u32 map_idx;
|
||||
char tmp[16];
|
||||
u32 width;
|
||||
@ -1174,7 +1175,8 @@ static int fsl_asrc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "fsl,asrc-format", &asrc->asrc_format);
|
||||
ret = of_property_read_u32(np, "fsl,asrc-format", &asrc_fmt);
|
||||
asrc->asrc_format = (__force snd_pcm_format_t)asrc_fmt;
|
||||
if (ret) {
|
||||
ret = of_property_read_u32(np, "fsl,asrc-width", &width);
|
||||
if (ret) {
|
||||
@ -1197,7 +1199,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
if (!(FSL_ASRC_FORMATS & (1ULL << asrc->asrc_format))) {
|
||||
if (!(FSL_ASRC_FORMATS & pcm_format_to_bits(asrc->asrc_format))) {
|
||||
dev_warn(&pdev->dev, "unsupported width, use default S24_LE\n");
|
||||
asrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
|
||||
}
|
||||
|
@ -476,7 +476,8 @@ static int fsl_easrc_prefilter_config(struct fsl_asrc *easrc,
|
||||
struct fsl_asrc_pair *ctx;
|
||||
struct device *dev;
|
||||
u32 inrate, outrate, offset = 0;
|
||||
u32 in_s_rate, out_s_rate, in_s_fmt, out_s_fmt;
|
||||
u32 in_s_rate, out_s_rate;
|
||||
snd_pcm_format_t in_s_fmt, out_s_fmt;
|
||||
int ret, i;
|
||||
|
||||
if (!easrc)
|
||||
@ -1874,6 +1875,7 @@ static int fsl_easrc_probe(struct platform_device *pdev)
|
||||
struct resource *res;
|
||||
struct device_node *np;
|
||||
void __iomem *regs;
|
||||
u32 asrc_fmt = 0;
|
||||
int ret, irq;
|
||||
|
||||
easrc = devm_kzalloc(dev, sizeof(*easrc), GFP_KERNEL);
|
||||
@ -1934,13 +1936,14 @@ static int fsl_easrc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "fsl,asrc-format", &easrc->asrc_format);
|
||||
ret = of_property_read_u32(np, "fsl,asrc-format", &asrc_fmt);
|
||||
easrc->asrc_format = (__force snd_pcm_format_t)asrc_fmt;
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to asrc format\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!(FSL_EASRC_FORMATS & (1ULL << easrc->asrc_format))) {
|
||||
if (!(FSL_EASRC_FORMATS & (pcm_format_to_bits(easrc->asrc_format)))) {
|
||||
dev_warn(dev, "unsupported format, switching to S24_LE\n");
|
||||
easrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
|
||||
}
|
||||
|
@ -569,7 +569,7 @@ struct fsl_easrc_io_params {
|
||||
unsigned int access_len;
|
||||
unsigned int fifo_wtmk;
|
||||
unsigned int sample_rate;
|
||||
unsigned int sample_format;
|
||||
snd_pcm_format_t sample_format;
|
||||
unsigned int norm_rate;
|
||||
};
|
||||
|
||||
|
@ -61,7 +61,7 @@ static inline bool fsl_sai_dir_is_synced(struct fsl_sai *sai, int dir)
|
||||
|
||||
static struct pinctrl_state *fsl_sai_get_pins_state(struct fsl_sai *sai, u32 bclk)
|
||||
{
|
||||
struct pinctrl_state *state = 0;
|
||||
struct pinctrl_state *state = NULL;
|
||||
|
||||
if (sai->is_pdm_mode) {
|
||||
/* DSD512@44.1kHz, DSD512@48kHz */
|
||||
|
@ -118,7 +118,7 @@ struct imx_card_data {
|
||||
struct snd_soc_card card;
|
||||
int num_dapm_routes;
|
||||
u32 asrc_rate;
|
||||
u32 asrc_format;
|
||||
snd_pcm_format_t asrc_format;
|
||||
};
|
||||
|
||||
static struct imx_akcodec_fs_mul ak4458_fs_mul[] = {
|
||||
@ -474,7 +474,7 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
|
||||
mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
snd_mask_none(mask);
|
||||
snd_mask_set(mask, data->asrc_format);
|
||||
snd_mask_set(mask, (__force unsigned int)data->asrc_format);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -493,6 +493,7 @@ static int imx_card_parse_of(struct imx_card_data *data)
|
||||
struct dai_link_data *link_data;
|
||||
struct of_phandle_args args;
|
||||
int ret, num_links;
|
||||
u32 asrc_fmt = 0;
|
||||
u32 width;
|
||||
|
||||
ret = snd_soc_of_parse_card_name(card, "model");
|
||||
@ -639,7 +640,8 @@ static int imx_card_parse_of(struct imx_card_data *data)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(args.np, "fsl,asrc-format", &data->asrc_format);
|
||||
ret = of_property_read_u32(args.np, "fsl,asrc-format", &asrc_fmt);
|
||||
data->asrc_format = (__force snd_pcm_format_t)asrc_fmt;
|
||||
if (ret) {
|
||||
/* Fallback to old binding; translate to asrc_format */
|
||||
ret = of_property_read_u32(args.np, "fsl,asrc-width", &width);
|
||||
|
@ -158,8 +158,10 @@ static int asoc_simple_parse_dai(struct device_node *ep,
|
||||
* if he unbinded CPU or Codec.
|
||||
*/
|
||||
ret = snd_soc_get_dai_name(&args, &dlc->dai_name);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
of_node_put(node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dlc->of_node = node;
|
||||
|
||||
|
@ -445,8 +445,10 @@ static int asoc_simple_parse_dai(struct device_node *ep,
|
||||
* if he unbinded CPU or Codec.
|
||||
*/
|
||||
ret = snd_soc_get_dai_name(&args, &dlc->dai_name);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
of_node_put(node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dlc->of_node = node;
|
||||
|
||||
|
@ -449,35 +449,39 @@ static int avs_modext_create(struct avs_dev *adev, struct avs_path_module *mod)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int avs_probe_create(struct avs_dev *adev, struct avs_path_module *mod)
|
||||
{
|
||||
dev_err(adev->dev, "Probe module can't be instantiated by topology");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct avs_module_create {
|
||||
guid_t *guid;
|
||||
int (*create)(struct avs_dev *adev, struct avs_path_module *mod);
|
||||
};
|
||||
|
||||
static struct avs_module_create avs_module_create[] = {
|
||||
{ &AVS_MIXIN_MOD_UUID, avs_modbase_create },
|
||||
{ &AVS_MIXOUT_MOD_UUID, avs_modbase_create },
|
||||
{ &AVS_KPBUFF_MOD_UUID, avs_modbase_create },
|
||||
{ &AVS_COPIER_MOD_UUID, avs_copier_create },
|
||||
{ &AVS_MICSEL_MOD_UUID, avs_micsel_create },
|
||||
{ &AVS_MUX_MOD_UUID, avs_mux_create },
|
||||
{ &AVS_UPDWMIX_MOD_UUID, avs_updown_mix_create },
|
||||
{ &AVS_SRCINTC_MOD_UUID, avs_src_create },
|
||||
{ &AVS_AEC_MOD_UUID, avs_aec_create },
|
||||
{ &AVS_ASRC_MOD_UUID, avs_asrc_create },
|
||||
{ &AVS_INTELWOV_MOD_UUID, avs_wov_create },
|
||||
{ &AVS_PROBE_MOD_UUID, avs_probe_create },
|
||||
};
|
||||
|
||||
static int avs_path_module_type_create(struct avs_dev *adev, struct avs_path_module *mod)
|
||||
{
|
||||
const guid_t *type = &mod->template->cfg_ext->type;
|
||||
|
||||
if (guid_equal(type, &AVS_MIXIN_MOD_UUID) ||
|
||||
guid_equal(type, &AVS_MIXOUT_MOD_UUID) ||
|
||||
guid_equal(type, &AVS_KPBUFF_MOD_UUID))
|
||||
return avs_modbase_create(adev, mod);
|
||||
if (guid_equal(type, &AVS_COPIER_MOD_UUID))
|
||||
return avs_copier_create(adev, mod);
|
||||
if (guid_equal(type, &AVS_MICSEL_MOD_UUID))
|
||||
return avs_micsel_create(adev, mod);
|
||||
if (guid_equal(type, &AVS_MUX_MOD_UUID))
|
||||
return avs_mux_create(adev, mod);
|
||||
if (guid_equal(type, &AVS_UPDWMIX_MOD_UUID))
|
||||
return avs_updown_mix_create(adev, mod);
|
||||
if (guid_equal(type, &AVS_SRCINTC_MOD_UUID))
|
||||
return avs_src_create(adev, mod);
|
||||
if (guid_equal(type, &AVS_AEC_MOD_UUID))
|
||||
return avs_aec_create(adev, mod);
|
||||
if (guid_equal(type, &AVS_ASRC_MOD_UUID))
|
||||
return avs_asrc_create(adev, mod);
|
||||
if (guid_equal(type, &AVS_INTELWOV_MOD_UUID))
|
||||
return avs_wov_create(adev, mod);
|
||||
|
||||
if (guid_equal(type, &AVS_PROBE_MOD_UUID)) {
|
||||
dev_err(adev->dev, "Probe module can't be instantiated by topology");
|
||||
return -EINVAL;
|
||||
}
|
||||
for (int i = 0; i < ARRAY_SIZE(avs_module_create); i++)
|
||||
if (guid_equal(type, avs_module_create[i].guid))
|
||||
return avs_module_create[i].create(adev, mod);
|
||||
|
||||
return avs_modext_create(adev, mod);
|
||||
}
|
||||
|
@ -249,6 +249,7 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = {
|
||||
/* SSP0 - Codec */
|
||||
.name = "Codec",
|
||||
.id = 0,
|
||||
.nonatomic = 1,
|
||||
.no_pcm = 1,
|
||||
.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBC_CFC,
|
||||
|
@ -349,6 +349,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = {
|
||||
/* SSP0 - Codec */
|
||||
.name = "Codec",
|
||||
.id = 0,
|
||||
.nonatomic = 1,
|
||||
.no_pcm = 1,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBC_CFC,
|
||||
|
@ -162,6 +162,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
|
||||
/* SSP0 - Codec */
|
||||
.name = "Codec",
|
||||
.id = 0,
|
||||
.nonatomic = 1,
|
||||
.no_pcm = 1,
|
||||
.init = codec_link_init,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC,
|
||||
|
@ -121,6 +121,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
|
||||
/* SSP0 - Codec */
|
||||
.name = "Codec",
|
||||
.id = 0,
|
||||
.nonatomic = 1,
|
||||
.no_pcm = 1,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC,
|
||||
.ignore_pmdown_time = 1,
|
||||
|
@ -28,6 +28,24 @@
|
||||
#define SOF_ES8336_SSP_CODEC_MASK (GENMASK(3, 0))
|
||||
|
||||
#define SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK BIT(4)
|
||||
|
||||
/* HDMI capture*/
|
||||
#define SOF_SSP_HDMI_CAPTURE_PRESENT BIT(14)
|
||||
#define SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT 15
|
||||
#define SOF_NO_OF_HDMI_CAPTURE_SSP_MASK (GENMASK(16, 15))
|
||||
#define SOF_NO_OF_HDMI_CAPTURE_SSP(quirk) \
|
||||
(((quirk) << SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT) & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK)
|
||||
|
||||
#define SOF_HDMI_CAPTURE_1_SSP_SHIFT 7
|
||||
#define SOF_HDMI_CAPTURE_1_SSP_MASK (GENMASK(9, 7))
|
||||
#define SOF_HDMI_CAPTURE_1_SSP(quirk) \
|
||||
(((quirk) << SOF_HDMI_CAPTURE_1_SSP_SHIFT) & SOF_HDMI_CAPTURE_1_SSP_MASK)
|
||||
|
||||
#define SOF_HDMI_CAPTURE_2_SSP_SHIFT 10
|
||||
#define SOF_HDMI_CAPTURE_2_SSP_MASK (GENMASK(12, 10))
|
||||
#define SOF_HDMI_CAPTURE_2_SSP(quirk) \
|
||||
(((quirk) << SOF_HDMI_CAPTURE_2_SSP_SHIFT) & SOF_HDMI_CAPTURE_2_SSP_MASK)
|
||||
|
||||
#define SOF_ES8336_ENABLE_DMIC BIT(5)
|
||||
#define SOF_ES8336_JD_INVERTED BIT(6)
|
||||
#define SOF_ES8336_HEADPHONE_GPIO BIT(7)
|
||||
@ -57,28 +75,26 @@ static const struct acpi_gpio_params enable_gpio0 = { 0, 0, true };
|
||||
static const struct acpi_gpio_params enable_gpio1 = { 1, 0, true };
|
||||
|
||||
static const struct acpi_gpio_mapping acpi_speakers_enable_gpio0[] = {
|
||||
{ "speakers-enable-gpios", &enable_gpio0, 1 },
|
||||
{ "speakers-enable-gpios", &enable_gpio0, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct acpi_gpio_mapping acpi_speakers_enable_gpio1[] = {
|
||||
{ "speakers-enable-gpios", &enable_gpio1, 1 },
|
||||
{ "speakers-enable-gpios", &enable_gpio1, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
|
||||
};
|
||||
|
||||
static const struct acpi_gpio_mapping acpi_enable_both_gpios[] = {
|
||||
{ "speakers-enable-gpios", &enable_gpio0, 1 },
|
||||
{ "headphone-enable-gpios", &enable_gpio1, 1 },
|
||||
{ "speakers-enable-gpios", &enable_gpio0, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
|
||||
{ "headphone-enable-gpios", &enable_gpio1, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct acpi_gpio_mapping acpi_enable_both_gpios_rev_order[] = {
|
||||
{ "speakers-enable-gpios", &enable_gpio1, 1 },
|
||||
{ "headphone-enable-gpios", &enable_gpio0, 1 },
|
||||
{ "speakers-enable-gpios", &enable_gpio1, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
|
||||
{ "headphone-enable-gpios", &enable_gpio0, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct acpi_gpio_mapping *gpio_mapping = acpi_speakers_enable_gpio0;
|
||||
|
||||
static void log_quirks(struct device *dev)
|
||||
{
|
||||
dev_info(dev, "quirk mask %#lx\n", quirk);
|
||||
@ -272,15 +288,6 @@ static int sof_es8336_quirk_cb(const struct dmi_system_id *id)
|
||||
{
|
||||
quirk = (unsigned long)id->driver_data;
|
||||
|
||||
if (quirk & SOF_ES8336_HEADPHONE_GPIO) {
|
||||
if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK)
|
||||
gpio_mapping = acpi_enable_both_gpios;
|
||||
else
|
||||
gpio_mapping = acpi_enable_both_gpios_rev_order;
|
||||
} else if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK) {
|
||||
gpio_mapping = acpi_speakers_enable_gpio1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -356,6 +363,13 @@ static struct snd_soc_dai_link_component dmic_component[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link_component dummy_component[] = {
|
||||
{
|
||||
.name = "snd-soc-dummy",
|
||||
.dai_name = "snd-soc-dummy-dai",
|
||||
}
|
||||
};
|
||||
|
||||
static int sof_es8336_late_probe(struct snd_soc_card *card)
|
||||
{
|
||||
struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
|
||||
@ -507,6 +521,37 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
|
||||
id++;
|
||||
}
|
||||
|
||||
/* HDMI-In SSP */
|
||||
if (quirk & SOF_SSP_HDMI_CAPTURE_PRESENT) {
|
||||
int num_of_hdmi_ssp = (quirk & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) >>
|
||||
SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT;
|
||||
|
||||
for (i = 1; i <= num_of_hdmi_ssp; i++) {
|
||||
int port = (i == 1 ? (quirk & SOF_HDMI_CAPTURE_1_SSP_MASK) >>
|
||||
SOF_HDMI_CAPTURE_1_SSP_SHIFT :
|
||||
(quirk & SOF_HDMI_CAPTURE_2_SSP_MASK) >>
|
||||
SOF_HDMI_CAPTURE_2_SSP_SHIFT);
|
||||
|
||||
links[id].cpus = &cpus[id];
|
||||
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"SSP%d Pin", port);
|
||||
if (!links[id].cpus->dai_name)
|
||||
return NULL;
|
||||
links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", port);
|
||||
if (!links[id].name)
|
||||
return NULL;
|
||||
links[id].id = id + hdmi_id_offset;
|
||||
links[id].codecs = dummy_component;
|
||||
links[id].num_codecs = ARRAY_SIZE(dummy_component);
|
||||
links[id].platforms = platform_component;
|
||||
links[id].num_platforms = ARRAY_SIZE(platform_component);
|
||||
links[id].dpcm_capture = 1;
|
||||
links[id].no_pcm = 1;
|
||||
links[id].num_cpus = 1;
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
return links;
|
||||
|
||||
devm_err:
|
||||
@ -529,6 +574,7 @@ static int sof_es8336_probe(struct platform_device *pdev)
|
||||
struct acpi_device *adev;
|
||||
struct snd_soc_dai_link *dai_links;
|
||||
struct device *codec_dev;
|
||||
const struct acpi_gpio_mapping *gpio_mapping;
|
||||
unsigned int cnt = 0;
|
||||
int dmic_be_num = 0;
|
||||
int hdmi_num = 3;
|
||||
@ -541,29 +587,34 @@ static int sof_es8336_probe(struct platform_device *pdev)
|
||||
card = &sof_es8336_card;
|
||||
card->dev = dev;
|
||||
|
||||
if (pdev->id_entry && pdev->id_entry->driver_data)
|
||||
quirk = (unsigned long)pdev->id_entry->driver_data;
|
||||
|
||||
/* check GPIO DMI quirks */
|
||||
dmi_check_system(sof_es8336_quirk_table);
|
||||
|
||||
if (!mach->mach_params.i2s_link_mask) {
|
||||
dev_warn(dev, "No I2S link information provided, using SSP0. This may need to be modified with the quirk module parameter\n");
|
||||
} else {
|
||||
/*
|
||||
* Set configuration based on platform NHLT.
|
||||
* In this machine driver, we can only support one SSP for the
|
||||
* ES8336 link, the else-if below are intentional.
|
||||
* In some cases multiple SSPs can be reported by NHLT, starting MSB-first
|
||||
* seems to pick the right connection.
|
||||
*/
|
||||
unsigned long ssp = 0;
|
||||
/* Use NHLT configuration only for Non-HDMI capture use case.
|
||||
* Because more than one SSP will be enabled for HDMI capture hence wrong codec
|
||||
* SSP will be set.
|
||||
*/
|
||||
if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER) {
|
||||
if (!mach->mach_params.i2s_link_mask) {
|
||||
dev_warn(dev, "No I2S link information provided, using SSP0. This may need to be modified with the quirk module parameter\n");
|
||||
} else {
|
||||
/*
|
||||
* Set configuration based on platform NHLT.
|
||||
* In this machine driver, we can only support one SSP for the
|
||||
* ES8336 link.
|
||||
* In some cases multiple SSPs can be reported by NHLT, starting MSB-first
|
||||
* seems to pick the right connection.
|
||||
*/
|
||||
unsigned long ssp;
|
||||
|
||||
if (mach->mach_params.i2s_link_mask & BIT(2))
|
||||
ssp = SOF_ES8336_SSP_CODEC(2);
|
||||
else if (mach->mach_params.i2s_link_mask & BIT(1))
|
||||
ssp = SOF_ES8336_SSP_CODEC(1);
|
||||
else if (mach->mach_params.i2s_link_mask & BIT(0))
|
||||
ssp = SOF_ES8336_SSP_CODEC(0);
|
||||
/* fls returns 1-based results, SSPs indices are 0-based */
|
||||
ssp = fls(mach->mach_params.i2s_link_mask) - 1;
|
||||
|
||||
quirk |= ssp;
|
||||
quirk |= ssp;
|
||||
}
|
||||
}
|
||||
|
||||
if (mach->mach_params.dmic_num)
|
||||
@ -579,7 +630,13 @@ static int sof_es8336_probe(struct platform_device *pdev)
|
||||
if (quirk & SOF_ES8336_ENABLE_DMIC)
|
||||
dmic_be_num = 2;
|
||||
|
||||
sof_es8336_card.num_links += dmic_be_num + hdmi_num;
|
||||
/* compute number of dai links */
|
||||
sof_es8336_card.num_links = 1 + dmic_be_num + hdmi_num;
|
||||
|
||||
if (quirk & SOF_SSP_HDMI_CAPTURE_PRESENT)
|
||||
sof_es8336_card.num_links += (quirk & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) >>
|
||||
SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT;
|
||||
|
||||
dai_links = sof_card_dai_links_create(dev,
|
||||
SOF_ES8336_SSP_CODEC(quirk),
|
||||
dmic_be_num, hdmi_num);
|
||||
@ -635,6 +692,17 @@ static int sof_es8336_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* get speaker enable GPIO */
|
||||
if (quirk & SOF_ES8336_HEADPHONE_GPIO) {
|
||||
if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK)
|
||||
gpio_mapping = acpi_enable_both_gpios;
|
||||
else
|
||||
gpio_mapping = acpi_enable_both_gpios_rev_order;
|
||||
} else if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK) {
|
||||
gpio_mapping = acpi_speakers_enable_gpio1;
|
||||
} else {
|
||||
gpio_mapping = acpi_speakers_enable_gpio0;
|
||||
}
|
||||
|
||||
ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
|
||||
if (ret)
|
||||
dev_warn(codec_dev, "unable to add GPIO mapping table\n");
|
||||
@ -690,6 +758,21 @@ static int sof_es8336_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id board_ids[] = {
|
||||
{
|
||||
.name = "adl_es83x6_c1_h02",
|
||||
.driver_data = (kernel_ulong_t)(SOF_ES8336_SSP_CODEC(1) |
|
||||
SOF_NO_OF_HDMI_CAPTURE_SSP(2) |
|
||||
SOF_HDMI_CAPTURE_1_SSP(0) |
|
||||
SOF_HDMI_CAPTURE_2_SSP(2) |
|
||||
SOF_SSP_HDMI_CAPTURE_PRESENT |
|
||||
SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK |
|
||||
SOF_ES8336_JD_INVERTED),
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, board_ids);
|
||||
|
||||
static struct platform_driver sof_es8336_driver = {
|
||||
.driver = {
|
||||
.name = "sof-essx8336",
|
||||
@ -697,6 +780,7 @@ static struct platform_driver sof_es8336_driver = {
|
||||
},
|
||||
.probe = sof_es8336_probe,
|
||||
.remove = sof_es8336_remove,
|
||||
.id_table = board_ids,
|
||||
};
|
||||
module_platform_driver(sof_es8336_driver);
|
||||
|
||||
|
@ -190,11 +190,6 @@ static int sof_card_late_probe(struct snd_soc_card *card)
|
||||
struct sof_hdmi_pcm *pcm;
|
||||
int err;
|
||||
|
||||
if (list_empty(&ctx->hdmi_pcm_list))
|
||||
return -EINVAL;
|
||||
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head);
|
||||
|
||||
if (sof_nau8825_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
|
||||
/* Disable Left and Right Spk pin after boot */
|
||||
snd_soc_dapm_disable_pin(dapm, "Left Spk");
|
||||
@ -204,6 +199,11 @@ static int sof_card_late_probe(struct snd_soc_card *card)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (list_empty(&ctx->hdmi_pcm_list))
|
||||
return -EINVAL;
|
||||
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head);
|
||||
|
||||
return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
|
||||
}
|
||||
|
||||
|
@ -447,6 +447,15 @@ static int sof_card_late_probe(struct snd_soc_card *card)
|
||||
struct sof_hdmi_pcm *pcm;
|
||||
int err;
|
||||
|
||||
if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
|
||||
/* Disable Left and Right Spk pin after boot */
|
||||
snd_soc_dapm_disable_pin(dapm, "Left Spk");
|
||||
snd_soc_dapm_disable_pin(dapm, "Right Spk");
|
||||
err = snd_soc_dapm_sync(dapm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* HDMI is not supported by SOF on Baytrail/CherryTrail */
|
||||
if (is_legacy_cpu || !ctx->idisp_codec)
|
||||
return 0;
|
||||
@ -477,15 +486,6 @@ static int sof_card_late_probe(struct snd_soc_card *card)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
|
||||
/* Disable Left and Right Spk pin after boot */
|
||||
snd_soc_dapm_disable_pin(dapm, "Left Spk");
|
||||
snd_soc_dapm_disable_pin(dapm, "Right Spk");
|
||||
err = snd_soc_dapm_sync(dapm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return hdac_hdmi_jack_port_init(component, &card->dapm);
|
||||
}
|
||||
|
||||
@ -1092,6 +1092,14 @@ static const struct platform_device_id board_ids[] = {
|
||||
SOF_RT5682_SSP_AMP(1) |
|
||||
SOF_RT5682_NUM_HDMIDEV(4)),
|
||||
},
|
||||
{
|
||||
.name = "mtl_mx98357_rt5682",
|
||||
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
|
||||
SOF_RT5682_SSP_CODEC(0) |
|
||||
SOF_SPEAKER_AMP_PRESENT |
|
||||
SOF_RT5682_SSP_AMP(1) |
|
||||
SOF_RT5682_NUM_HDMIDEV(4)),
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, board_ids);
|
||||
|
@ -246,6 +246,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
||||
SOF_BT_OFFLOAD_SSP(2) |
|
||||
SOF_SSP_BT_OFFLOAD_PRESENT),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF0")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
RT711_JD2 |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
@ -315,6 +325,15 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
||||
RT711_JD2 |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16-k0xxx"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
RT711_JD2),
|
||||
},
|
||||
/* MeteorLake devices */
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
|
@ -139,6 +139,9 @@ int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_l
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (!ctx->headset_codec_dev)
|
||||
return 0;
|
||||
|
||||
device_remove_software_node(ctx->headset_codec_dev);
|
||||
put_device(ctx->headset_codec_dev);
|
||||
|
||||
|
@ -140,6 +140,9 @@ int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (!ctx->headset_codec_dev)
|
||||
return 0;
|
||||
|
||||
device_remove_software_node(ctx->headset_codec_dev);
|
||||
put_device(ctx->headset_codec_dev);
|
||||
|
||||
|
@ -8,6 +8,11 @@
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-acpi-intel-match.h>
|
||||
|
||||
static const struct snd_soc_acpi_codecs essx_83x6 = {
|
||||
.num_codecs = 3,
|
||||
.codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_endpoint single_endpoint = {
|
||||
.num = 0,
|
||||
.aggregated = 0,
|
||||
@ -137,6 +142,15 @@ static const struct snd_soc_acpi_adr_device rt1316_2_single_adr[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt1316_3_single_adr[] = {
|
||||
{
|
||||
.adr = 0x000330025D131601ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &single_endpoint,
|
||||
.name_prefix = "rt1316-1"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt714_0_adr[] = {
|
||||
{
|
||||
.adr = 0x000030025D071401ull,
|
||||
@ -326,6 +340,20 @@ static const struct snd_soc_acpi_link_adr adl_sdw_rt1316_link2_rt714_link0[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr adl_sdw_rt711_link0_rt1316_link3[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt711_sdca_0_adr),
|
||||
.adr_d = rt711_sdca_0_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(3),
|
||||
.num_adr = ARRAY_SIZE(rt1316_3_single_adr),
|
||||
.adr_d = rt1316_3_single_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device mx8373_2_adr[] = {
|
||||
{
|
||||
.adr = 0x000223019F837300ull,
|
||||
@ -412,6 +440,11 @@ static const struct snd_soc_acpi_codecs adl_max98390_amp = {
|
||||
.codecs = {"MX98390"}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_codecs adl_lt6911_hdmi = {
|
||||
.num_codecs = 1,
|
||||
.codecs = {"INTC10B0"}
|
||||
};
|
||||
|
||||
struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
|
||||
{
|
||||
.comp_ids = &adl_rt5682_rt5682s_hp,
|
||||
@ -492,6 +525,21 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
|
||||
.drv_name = "adl_cs35l41",
|
||||
.sof_tplg_filename = "sof-adl-cs35l41.tplg",
|
||||
},
|
||||
{
|
||||
.comp_ids = &essx_83x6,
|
||||
.drv_name = "adl_es83x6_c1_h02",
|
||||
.machine_quirk = snd_soc_acpi_codec_list,
|
||||
.quirk_data = &adl_lt6911_hdmi,
|
||||
.sof_tplg_filename = "sof-adl-es83x6-ssp1-hdmi-ssp02.tplg",
|
||||
},
|
||||
{
|
||||
.comp_ids = &essx_83x6,
|
||||
.drv_name = "sof-essx8336",
|
||||
.sof_tplg_filename = "sof-adl-es83x6", /* the tplg suffix is added at run time */
|
||||
.tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER |
|
||||
SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
|
||||
SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
|
||||
},
|
||||
{},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_adl_machines);
|
||||
@ -546,6 +594,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = {
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-adl-rt1316-l2-mono-rt714-l0.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = 0x9, /* 2 active links required */
|
||||
.links = adl_sdw_rt711_link0_rt1316_link3,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l3.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = 0x1, /* link0 required */
|
||||
.links = adl_rvp,
|
||||
|
@ -10,7 +10,24 @@
|
||||
#include <sound/soc-acpi-intel-match.h>
|
||||
#include "soc-acpi-intel-sdw-mockup-match.h"
|
||||
|
||||
static const struct snd_soc_acpi_codecs mtl_max98357a_amp = {
|
||||
.num_codecs = 1,
|
||||
.codecs = {"MX98357A"}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = {
|
||||
.num_codecs = 2,
|
||||
.codecs = {"10EC5682", "RTL5682"},
|
||||
};
|
||||
|
||||
struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = {
|
||||
{
|
||||
.comp_ids = &mtl_rt5682_rt5682s_hp,
|
||||
.drv_name = "mtl_mx98357_rt5682",
|
||||
.machine_quirk = snd_soc_acpi_codec_list,
|
||||
.quirk_data = &mtl_max98357a_amp,
|
||||
.sof_tplg_filename = "sof-mtl-max98357a-rt5682.tplg",
|
||||
},
|
||||
{},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_machines);
|
||||
|
@ -93,7 +93,6 @@ struct i2s_soc_info {
|
||||
};
|
||||
|
||||
struct jz4740_i2s {
|
||||
struct resource *mem;
|
||||
void __iomem *base;
|
||||
|
||||
struct clk *clk_aic;
|
||||
|
@ -152,6 +152,51 @@ config SND_SOC_MT8183_DA7219_MAX98357A
|
||||
Select Y if you have such device.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_MT8186
|
||||
tristate "ASoC support for Mediatek MT8186 chip"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
depends on COMMON_CLK
|
||||
select SND_SOC_MEDIATEK
|
||||
select SND_SOC_MT6358
|
||||
select MFD_SYSCON if SND_SOC_MT6358
|
||||
help
|
||||
This adds ASoC driver for Mediatek MT8186 boards
|
||||
that can be used with other codecs.
|
||||
Select Y if you have such device.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_MT8186_MT6366_DA7219_MAX98357
|
||||
tristate "ASoC Audio driver for MT8186 with DA7219 MAX98357A codec"
|
||||
depends on I2C && GPIOLIB
|
||||
depends on SND_SOC_MT8186 && MTK_PMIC_WRAP
|
||||
select SND_SOC_MT6358
|
||||
select SND_SOC_MAX98357A
|
||||
select SND_SOC_DA7219
|
||||
select SND_SOC_BT_SCO
|
||||
select SND_SOC_DMIC
|
||||
select SND_SOC_HDMI_CODEC
|
||||
help
|
||||
This adds ASoC driver for Mediatek MT8186 boards
|
||||
with the MT6366(MT6358) DA7219 MAX98357A codecs.
|
||||
Select Y if you have such device.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_MT8186_MT6366_RT1019_RT5682S
|
||||
tristate "ASoC Audio driver for MT8186 with RT1019 RT5682S codec"
|
||||
depends on I2C && GPIOLIB
|
||||
depends on SND_SOC_MT8186 && MTK_PMIC_WRAP
|
||||
select SND_SOC_MT6358
|
||||
select SND_SOC_RT1015P
|
||||
select SND_SOC_RT5682S
|
||||
select SND_SOC_BT_SCO
|
||||
select SND_SOC_DMIC
|
||||
select SND_SOC_HDMI_CODEC
|
||||
help
|
||||
This adds ASoC driver for Mediatek MT8186 boards
|
||||
with the MT6366(MT6358) RT1019 RT5682S codecs.
|
||||
Select Y if you have such device.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_MTK_BTCVSD
|
||||
tristate "ALSA BT SCO CVSD/MSBC Driver"
|
||||
help
|
||||
|
@ -4,5 +4,6 @@ obj-$(CONFIG_SND_SOC_MT2701) += mt2701/
|
||||
obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
|
||||
obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
|
||||
obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
|
||||
obj-$(CONFIG_SND_SOC_MT8186) += mt8186/
|
||||
obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
|
||||
obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
|
||||
|
@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# platform driver
|
||||
snd-soc-mtk-common-objs := mtk-afe-platform-driver.o mtk-afe-fe-dai.o
|
||||
snd-soc-mtk-common-objs := mtk-afe-platform-driver.o mtk-afe-fe-dai.o mtk-dsp-sof-common.o
|
||||
obj-$(CONFIG_SND_SOC_MEDIATEK) += snd-soc-mtk-common.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_MTK_BTCVSD) += mtk-btcvsd.o
|
||||
|
196
sound/soc/mediatek/common/mtk-dsp-sof-common.c
Normal file
196
sound/soc/mediatek/common/mtk-dsp-sof-common.c
Normal file
@ -0,0 +1,196 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* mtk-dsp-sof-common.c -- MediaTek dsp sof common ctrl
|
||||
*
|
||||
* Copyright (c) 2022 MediaTek Inc.
|
||||
* Author: Chunxu Li <chunxu.li@mediatek.com>
|
||||
*/
|
||||
|
||||
#include "mtk-dsp-sof-common.h"
|
||||
#include "mtk-soc-card.h"
|
||||
|
||||
/* fixup the BE DAI link to match any values from topology */
|
||||
int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
|
||||
struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
|
||||
int i, j, ret = 0;
|
||||
|
||||
for (i = 0; i < sof_priv->num_streams; i++) {
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
struct snd_soc_pcm_runtime *runtime;
|
||||
struct snd_soc_dai_link *sof_dai_link = NULL;
|
||||
const struct sof_conn_stream *conn = &sof_priv->conn_streams[i];
|
||||
|
||||
if (strcmp(rtd->dai_link->name, conn->normal_link))
|
||||
continue;
|
||||
|
||||
for_each_card_rtds(card, runtime) {
|
||||
if (strcmp(runtime->dai_link->name, conn->sof_link))
|
||||
continue;
|
||||
|
||||
for_each_rtd_cpu_dais(runtime, j, cpu_dai) {
|
||||
if (cpu_dai->stream_active[conn->stream_dir] > 0) {
|
||||
sof_dai_link = runtime->dai_link;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (sof_dai_link && sof_dai_link->be_hw_params_fixup)
|
||||
ret = sof_dai_link->be_hw_params_fixup(runtime, params);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_sof_dai_link_fixup);
|
||||
|
||||
int mtk_sof_card_probe(struct snd_soc_card *card)
|
||||
{
|
||||
int i;
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
|
||||
/* Set stream_name to help sof bind widgets */
|
||||
for_each_card_prelinks(card, i, dai_link) {
|
||||
if (dai_link->no_pcm && !dai_link->stream_name && dai_link->name)
|
||||
dai_link->stream_name = dai_link->name;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_sof_card_probe);
|
||||
|
||||
int mtk_sof_card_late_probe(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd;
|
||||
struct snd_soc_component *sof_comp = NULL;
|
||||
struct mtk_soc_card_data *soc_card_data =
|
||||
snd_soc_card_get_drvdata(card);
|
||||
struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
|
||||
int i;
|
||||
|
||||
/* 1. find sof component */
|
||||
for_each_card_rtds(card, rtd) {
|
||||
sof_comp = snd_soc_rtdcom_lookup(rtd, "sof-audio-component");
|
||||
if (sof_comp)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!sof_comp) {
|
||||
dev_info(card->dev, "probe without sof-audio-component\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 2. add route path and fixup callback */
|
||||
for (i = 0; i < sof_priv->num_streams; i++) {
|
||||
const struct sof_conn_stream *conn = &sof_priv->conn_streams[i];
|
||||
struct snd_soc_pcm_runtime *sof_rtd = NULL;
|
||||
struct snd_soc_pcm_runtime *normal_rtd = NULL;
|
||||
|
||||
for_each_card_rtds(card, rtd) {
|
||||
if (!strcmp(rtd->dai_link->name, conn->sof_link)) {
|
||||
sof_rtd = rtd;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(rtd->dai_link->name, conn->normal_link)) {
|
||||
normal_rtd = rtd;
|
||||
continue;
|
||||
}
|
||||
if (normal_rtd && sof_rtd)
|
||||
break;
|
||||
}
|
||||
if (normal_rtd && sof_rtd) {
|
||||
int j;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
|
||||
for_each_rtd_cpu_dais(sof_rtd, j, cpu_dai) {
|
||||
struct snd_soc_dapm_route route;
|
||||
struct snd_soc_dapm_path *p = NULL;
|
||||
struct snd_soc_dapm_widget *play_widget =
|
||||
cpu_dai->playback_widget;
|
||||
struct snd_soc_dapm_widget *cap_widget =
|
||||
cpu_dai->capture_widget;
|
||||
memset(&route, 0, sizeof(route));
|
||||
if (conn->stream_dir == SNDRV_PCM_STREAM_CAPTURE &&
|
||||
cap_widget) {
|
||||
snd_soc_dapm_widget_for_each_sink_path(cap_widget, p) {
|
||||
route.source = conn->sof_dma;
|
||||
route.sink = p->sink->name;
|
||||
snd_soc_dapm_add_routes(&card->dapm, &route, 1);
|
||||
}
|
||||
} else if (conn->stream_dir == SNDRV_PCM_STREAM_PLAYBACK &&
|
||||
play_widget) {
|
||||
snd_soc_dapm_widget_for_each_source_path(play_widget, p) {
|
||||
route.source = p->source->name;
|
||||
route.sink = conn->sof_dma;
|
||||
snd_soc_dapm_add_routes(&card->dapm, &route, 1);
|
||||
}
|
||||
} else {
|
||||
dev_err(cpu_dai->dev, "stream dir and widget not pair\n");
|
||||
}
|
||||
}
|
||||
|
||||
sof_rtd->dai_link->be_hw_params_fixup =
|
||||
sof_comp->driver->be_hw_params_fixup;
|
||||
if (sof_priv->sof_dai_link_fixup)
|
||||
normal_rtd->dai_link->be_hw_params_fixup =
|
||||
sof_priv->sof_dai_link_fixup;
|
||||
else
|
||||
normal_rtd->dai_link->be_hw_params_fixup = mtk_sof_dai_link_fixup;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_sof_card_late_probe);
|
||||
|
||||
int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np,
|
||||
const char *propname, struct snd_soc_dai_link *pre_dai_links,
|
||||
int pre_num_links)
|
||||
{
|
||||
struct device *dev = card->dev;
|
||||
struct snd_soc_dai_link *parsed_dai_link;
|
||||
const char *dai_name = NULL;
|
||||
int i, j, ret, num_links, parsed_num_links = 0;
|
||||
|
||||
num_links = of_property_count_strings(np, "mediatek,dai-link");
|
||||
if (num_links < 0 || num_links > card->num_links) {
|
||||
dev_dbg(dev, "number of dai-link is invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
parsed_dai_link = devm_kcalloc(dev, num_links, sizeof(*parsed_dai_link), GFP_KERNEL);
|
||||
if (!parsed_dai_link)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_links; i++) {
|
||||
ret = of_property_read_string_index(np, propname, i, &dai_name);
|
||||
if (ret) {
|
||||
dev_dbg(dev, "ASoC: Property '%s' index %d could not be read: %d\n",
|
||||
propname, i, ret);
|
||||
return ret;
|
||||
}
|
||||
dev_dbg(dev, "ASoC: Property get dai_name:%s\n", dai_name);
|
||||
for (j = 0; j < pre_num_links; j++) {
|
||||
if (!strcmp(dai_name, pre_dai_links[j].name)) {
|
||||
memcpy(&parsed_dai_link[parsed_num_links++], &pre_dai_links[j],
|
||||
sizeof(struct snd_soc_dai_link));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parsed_num_links != num_links)
|
||||
return -EINVAL;
|
||||
|
||||
card->dai_link = parsed_dai_link;
|
||||
card->num_links = parsed_num_links;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_sof_dailink_parse_of);
|
36
sound/soc/mediatek/common/mtk-dsp-sof-common.h
Normal file
36
sound/soc/mediatek/common/mtk-dsp-sof-common.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* mtk-dsp-sof-common.h -- MediaTek dsp sof common definition
|
||||
*
|
||||
* Copyright (c) 2022 MediaTek Inc.
|
||||
* Author: Chunxu Li <chunxu.li@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _MTK_DSP_SOF_COMMON_H_
|
||||
#define _MTK_DSP_SOF_COMMON_H_
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
struct sof_conn_stream {
|
||||
const char *normal_link;
|
||||
const char *sof_link;
|
||||
const char *sof_dma;
|
||||
int stream_dir;
|
||||
};
|
||||
|
||||
struct mtk_sof_priv {
|
||||
const struct sof_conn_stream *conn_streams;
|
||||
int num_streams;
|
||||
int (*sof_dai_link_fixup)(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params);
|
||||
};
|
||||
|
||||
int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params);
|
||||
int mtk_sof_card_probe(struct snd_soc_card *card);
|
||||
int mtk_sof_card_late_probe(struct snd_soc_card *card);
|
||||
int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np,
|
||||
const char *propname, struct snd_soc_dai_link *pre_dai_links,
|
||||
int pre_num_links);
|
||||
|
||||
#endif
|
17
sound/soc/mediatek/common/mtk-soc-card.h
Normal file
17
sound/soc/mediatek/common/mtk-soc-card.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* mtk-soc-card.h -- MediaTek soc card data definition
|
||||
*
|
||||
* Copyright (c) 2022 MediaTek Inc.
|
||||
* Author: Chunxu Li <chunxu.li@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _MTK_SOC_CARD_H_
|
||||
#define _MTK_SOC_CARD_H_
|
||||
|
||||
struct mtk_soc_card_data {
|
||||
void *mach_priv;
|
||||
void *sof_priv;
|
||||
};
|
||||
|
||||
#endif
|
22
sound/soc/mediatek/mt8186/Makefile
Normal file
22
sound/soc/mediatek/mt8186/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# platform driver
|
||||
snd-soc-mt8186-afe-objs := \
|
||||
mt8186-afe-pcm.o \
|
||||
mt8186-audsys-clk.o \
|
||||
mt8186-afe-clk.o \
|
||||
mt8186-afe-gpio.o \
|
||||
mt8186-dai-adda.o \
|
||||
mt8186-afe-control.o \
|
||||
mt8186-dai-i2s.o \
|
||||
mt8186-dai-hw-gain.o \
|
||||
mt8186-dai-pcm.o \
|
||||
mt8186-dai-src.o \
|
||||
mt8186-dai-hostless.o \
|
||||
mt8186-dai-tdm.o \
|
||||
mt8186-misc-control.o \
|
||||
mt8186-mt6366-common.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_MT8186) += snd-soc-mt8186-afe.o
|
||||
obj-$(CONFIG_SND_SOC_MT8186_MT6366_DA7219_MAX98357) += mt8186-mt6366-da7219-max98357.o
|
||||
obj-$(CONFIG_SND_SOC_MT8186_MT6366_RT1019_RT5682S) += mt8186-mt6366-rt1019-rt5682s.o
|
@ -645,7 +645,8 @@ int mt8186_init_clock(struct mtk_base_afe *afe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt8186_deinit_clock(struct mtk_base_afe *afe)
|
||||
void mt8186_deinit_clock(void *priv)
|
||||
{
|
||||
struct mtk_base_afe *afe = priv;
|
||||
mt8186_audsys_clk_unregister(afe);
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ enum {
|
||||
struct mtk_base_afe;
|
||||
int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe, int clk_id);
|
||||
int mt8186_init_clock(struct mtk_base_afe *afe);
|
||||
void mt8186_deinit_clock(struct mtk_base_afe *afe);
|
||||
void mt8186_deinit_clock(void *priv);
|
||||
int mt8186_afe_enable_cgs(struct mtk_base_afe *afe);
|
||||
void mt8186_afe_disable_cgs(struct mtk_base_afe *afe);
|
||||
int mt8186_afe_enable_clock(struct mtk_base_afe *afe);
|
||||
|
195
sound/soc/mediatek/mt8186/mt8186-afe-common.h
Normal file
195
sound/soc/mediatek/mt8186/mt8186-afe-common.h
Normal file
@ -0,0 +1,195 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* mt8186-afe-common.h -- Mediatek 8186 audio driver definitions
|
||||
*
|
||||
* Copyright (c) 2022 MediaTek Inc.
|
||||
* Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _MT_8186_AFE_COMMON_H_
|
||||
#define _MT_8186_AFE_COMMON_H_
|
||||
#include <sound/soc.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/regmap.h>
|
||||
#include "mt8186-reg.h"
|
||||
#include "../common/mtk-base-afe.h"
|
||||
|
||||
enum {
|
||||
MT8186_MEMIF_DL1,
|
||||
MT8186_MEMIF_DL12,
|
||||
MT8186_MEMIF_DL2,
|
||||
MT8186_MEMIF_DL3,
|
||||
MT8186_MEMIF_DL4,
|
||||
MT8186_MEMIF_DL5,
|
||||
MT8186_MEMIF_DL6,
|
||||
MT8186_MEMIF_DL7,
|
||||
MT8186_MEMIF_DL8,
|
||||
MT8186_MEMIF_VUL12,
|
||||
MT8186_MEMIF_VUL2,
|
||||
MT8186_MEMIF_VUL3,
|
||||
MT8186_MEMIF_VUL4,
|
||||
MT8186_MEMIF_VUL5,
|
||||
MT8186_MEMIF_VUL6,
|
||||
MT8186_MEMIF_AWB,
|
||||
MT8186_MEMIF_AWB2,
|
||||
MT8186_MEMIF_NUM,
|
||||
MT8186_DAI_ADDA = MT8186_MEMIF_NUM,
|
||||
MT8186_DAI_AP_DMIC,
|
||||
MT8186_DAI_CONNSYS_I2S,
|
||||
MT8186_DAI_I2S_0,
|
||||
MT8186_DAI_I2S_1,
|
||||
MT8186_DAI_I2S_2,
|
||||
MT8186_DAI_I2S_3,
|
||||
MT8186_DAI_HW_GAIN_1,
|
||||
MT8186_DAI_HW_GAIN_2,
|
||||
MT8186_DAI_SRC_1,
|
||||
MT8186_DAI_SRC_2,
|
||||
MT8186_DAI_PCM,
|
||||
MT8186_DAI_TDM_IN,
|
||||
MT8186_DAI_HOSTLESS_LPBK,
|
||||
MT8186_DAI_HOSTLESS_FM,
|
||||
MT8186_DAI_HOSTLESS_HW_GAIN_AAUDIO,
|
||||
MT8186_DAI_HOSTLESS_SRC_AAUDIO,
|
||||
MT8186_DAI_HOSTLESS_SRC_1,
|
||||
MT8186_DAI_HOSTLESS_SRC_BARGEIN,
|
||||
MT8186_DAI_HOSTLESS_UL1,
|
||||
MT8186_DAI_HOSTLESS_UL2,
|
||||
MT8186_DAI_HOSTLESS_UL3,
|
||||
MT8186_DAI_HOSTLESS_UL5,
|
||||
MT8186_DAI_HOSTLESS_UL6,
|
||||
MT8186_DAI_NUM,
|
||||
};
|
||||
|
||||
#define MT8186_RECORD_MEMIF MT8186_MEMIF_VUL12
|
||||
#define MT8186_ECHO_REF_MEMIF MT8186_MEMIF_AWB
|
||||
#define MT8186_PRIMARY_MEMIF MT8186_MEMIF_DL1
|
||||
#define MT8186_FAST_MEMIF MT8186_MEMIF_DL2
|
||||
#define MT8186_DEEP_MEMIF MT8186_MEMIF_DL3
|
||||
#define MT8186_VOIP_MEMIF MT8186_MEMIF_DL12
|
||||
#define MT8186_MMAP_DL_MEMIF MT8186_MEMIF_DL5
|
||||
#define MT8186_MMAP_UL_MEMIF MT8186_MEMIF_VUL5
|
||||
#define MT8186_BARGEIN_MEMIF MT8186_MEMIF_AWB
|
||||
|
||||
enum {
|
||||
MT8186_IRQ_0,
|
||||
MT8186_IRQ_1,
|
||||
MT8186_IRQ_2,
|
||||
MT8186_IRQ_3,
|
||||
MT8186_IRQ_4,
|
||||
MT8186_IRQ_5,
|
||||
MT8186_IRQ_6,
|
||||
MT8186_IRQ_7,
|
||||
MT8186_IRQ_8,
|
||||
MT8186_IRQ_9,
|
||||
MT8186_IRQ_10,
|
||||
MT8186_IRQ_11,
|
||||
MT8186_IRQ_12,
|
||||
MT8186_IRQ_13,
|
||||
MT8186_IRQ_14,
|
||||
MT8186_IRQ_15,
|
||||
MT8186_IRQ_16,
|
||||
MT8186_IRQ_17,
|
||||
MT8186_IRQ_18,
|
||||
MT8186_IRQ_19,
|
||||
MT8186_IRQ_20,
|
||||
MT8186_IRQ_21,
|
||||
MT8186_IRQ_22,
|
||||
MT8186_IRQ_23,
|
||||
MT8186_IRQ_24,
|
||||
MT8186_IRQ_25,
|
||||
MT8186_IRQ_26,
|
||||
MT8186_IRQ_NUM,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT8186_AFE_IRQ_DIR_MCU = 0,
|
||||
MT8186_AFE_IRQ_DIR_DSP,
|
||||
MT8186_AFE_IRQ_DIR_BOTH,
|
||||
};
|
||||
|
||||
enum {
|
||||
MTKAIF_PROTOCOL_1 = 0,
|
||||
MTKAIF_PROTOCOL_2,
|
||||
MTKAIF_PROTOCOL_2_CLK_P2,
|
||||
};
|
||||
|
||||
enum {
|
||||
MTK_AFE_ADDA_DL_GAIN_MUTE = 0,
|
||||
MTK_AFE_ADDA_DL_GAIN_NORMAL = 0xf74f,
|
||||
/* SA suggest apply -0.3db to audio/speech path */
|
||||
};
|
||||
|
||||
#define MTK_SPK_I2S_0_STR "MTK_SPK_I2S_0"
|
||||
#define MTK_SPK_I2S_1_STR "MTK_SPK_I2S_1"
|
||||
#define MTK_SPK_I2S_2_STR "MTK_SPK_I2S_2"
|
||||
#define MTK_SPK_I2S_3_STR "MTK_SPK_I2S_3"
|
||||
|
||||
/* MCLK */
|
||||
enum {
|
||||
MT8186_I2S0_MCK = 0,
|
||||
MT8186_I2S1_MCK,
|
||||
MT8186_I2S2_MCK,
|
||||
MT8186_I2S4_MCK,
|
||||
MT8186_TDM_MCK,
|
||||
MT8186_MCK_NUM,
|
||||
};
|
||||
|
||||
struct snd_pcm_substream;
|
||||
struct mtk_base_irq_data;
|
||||
struct clk;
|
||||
|
||||
struct mt8186_afe_private {
|
||||
struct clk **clk;
|
||||
struct clk_lookup **lookup;
|
||||
struct regmap *topckgen;
|
||||
struct regmap *apmixedsys;
|
||||
struct regmap *infracfg;
|
||||
int irq_cnt[MT8186_MEMIF_NUM];
|
||||
int stf_positive_gain_db;
|
||||
int pm_runtime_bypass_reg_ctl;
|
||||
int sgen_mode;
|
||||
int sgen_rate;
|
||||
int sgen_amplitude;
|
||||
|
||||
/* xrun assert */
|
||||
int xrun_assert[MT8186_MEMIF_NUM];
|
||||
|
||||
/* dai */
|
||||
bool dai_on[MT8186_DAI_NUM];
|
||||
void *dai_priv[MT8186_DAI_NUM];
|
||||
|
||||
/* adda */
|
||||
bool mtkaif_calibration_ok;
|
||||
int mtkaif_protocol;
|
||||
int mtkaif_chosen_phase[4];
|
||||
int mtkaif_phase_cycle[4];
|
||||
int mtkaif_calibration_num_phase;
|
||||
int mtkaif_dmic;
|
||||
int mtkaif_looback0;
|
||||
int mtkaif_looback1;
|
||||
|
||||
/* mck */
|
||||
int mck_rate[MT8186_MCK_NUM];
|
||||
};
|
||||
|
||||
int mt8186_dai_adda_register(struct mtk_base_afe *afe);
|
||||
int mt8186_dai_i2s_register(struct mtk_base_afe *afe);
|
||||
int mt8186_dai_tdm_register(struct mtk_base_afe *afe);
|
||||
int mt8186_dai_hw_gain_register(struct mtk_base_afe *afe);
|
||||
int mt8186_dai_src_register(struct mtk_base_afe *afe);
|
||||
int mt8186_dai_pcm_register(struct mtk_base_afe *afe);
|
||||
int mt8186_dai_hostless_register(struct mtk_base_afe *afe);
|
||||
|
||||
int mt8186_add_misc_control(struct snd_soc_component *component);
|
||||
|
||||
unsigned int mt8186_general_rate_transform(struct device *dev,
|
||||
unsigned int rate);
|
||||
unsigned int mt8186_rate_transform(struct device *dev,
|
||||
unsigned int rate, int aud_blk);
|
||||
unsigned int mt8186_tdm_relatch_rate_transform(struct device *dev,
|
||||
unsigned int rate);
|
||||
|
||||
int mt8186_dai_set_priv(struct mtk_base_afe *afe, int id,
|
||||
int priv_size, const void *priv_data);
|
||||
|
||||
#endif
|
255
sound/soc/mediatek/mt8186/mt8186-afe-control.c
Normal file
255
sound/soc/mediatek/mt8186/mt8186-afe-control.c
Normal file
@ -0,0 +1,255 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// MediaTek ALSA SoC Audio Control
|
||||
//
|
||||
// Copyright (c) 2022 MediaTek Inc.
|
||||
// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
|
||||
|
||||
#include "mt8186-afe-common.h"
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
enum {
|
||||
MTK_AFE_RATE_8K = 0,
|
||||
MTK_AFE_RATE_11K,
|
||||
MTK_AFE_RATE_12K,
|
||||
MTK_AFE_RATE_384K,
|
||||
MTK_AFE_RATE_16K,
|
||||
MTK_AFE_RATE_22K,
|
||||
MTK_AFE_RATE_24K,
|
||||
MTK_AFE_RATE_352K,
|
||||
MTK_AFE_RATE_32K,
|
||||
MTK_AFE_RATE_44K,
|
||||
MTK_AFE_RATE_48K,
|
||||
MTK_AFE_RATE_88K,
|
||||
MTK_AFE_RATE_96K,
|
||||
MTK_AFE_RATE_176K,
|
||||
MTK_AFE_RATE_192K,
|
||||
MTK_AFE_RATE_260K,
|
||||
};
|
||||
|
||||
enum {
|
||||
MTK_AFE_PCM_RATE_8K = 0,
|
||||
MTK_AFE_PCM_RATE_16K,
|
||||
MTK_AFE_PCM_RATE_32K,
|
||||
MTK_AFE_PCM_RATE_48K,
|
||||
};
|
||||
|
||||
enum {
|
||||
MTK_AFE_TDM_RATE_8K = 0,
|
||||
MTK_AFE_TDM_RATE_12K,
|
||||
MTK_AFE_TDM_RATE_16K,
|
||||
MTK_AFE_TDM_RATE_24K,
|
||||
MTK_AFE_TDM_RATE_32K,
|
||||
MTK_AFE_TDM_RATE_48K,
|
||||
MTK_AFE_TDM_RATE_64K,
|
||||
MTK_AFE_TDM_RATE_96K,
|
||||
MTK_AFE_TDM_RATE_128K,
|
||||
MTK_AFE_TDM_RATE_192K,
|
||||
MTK_AFE_TDM_RATE_256K,
|
||||
MTK_AFE_TDM_RATE_384K,
|
||||
MTK_AFE_TDM_RATE_11K,
|
||||
MTK_AFE_TDM_RATE_22K,
|
||||
MTK_AFE_TDM_RATE_44K,
|
||||
MTK_AFE_TDM_RATE_88K,
|
||||
MTK_AFE_TDM_RATE_176K,
|
||||
MTK_AFE_TDM_RATE_352K,
|
||||
};
|
||||
|
||||
enum {
|
||||
MTK_AFE_TDM_RELATCH_RATE_8K = 0,
|
||||
MTK_AFE_TDM_RELATCH_RATE_11K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_12K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_16K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_22K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_24K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_32K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_44K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_48K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_88K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_96K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_176K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_192K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_352K,
|
||||
MTK_AFE_TDM_RELATCH_RATE_384K,
|
||||
};
|
||||
|
||||
unsigned int mt8186_general_rate_transform(struct device *dev, unsigned int rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case 8000:
|
||||
return MTK_AFE_RATE_8K;
|
||||
case 11025:
|
||||
return MTK_AFE_RATE_11K;
|
||||
case 12000:
|
||||
return MTK_AFE_RATE_12K;
|
||||
case 16000:
|
||||
return MTK_AFE_RATE_16K;
|
||||
case 22050:
|
||||
return MTK_AFE_RATE_22K;
|
||||
case 24000:
|
||||
return MTK_AFE_RATE_24K;
|
||||
case 32000:
|
||||
return MTK_AFE_RATE_32K;
|
||||
case 44100:
|
||||
return MTK_AFE_RATE_44K;
|
||||
case 48000:
|
||||
return MTK_AFE_RATE_48K;
|
||||
case 88200:
|
||||
return MTK_AFE_RATE_88K;
|
||||
case 96000:
|
||||
return MTK_AFE_RATE_96K;
|
||||
case 176400:
|
||||
return MTK_AFE_RATE_176K;
|
||||
case 192000:
|
||||
return MTK_AFE_RATE_192K;
|
||||
case 260000:
|
||||
return MTK_AFE_RATE_260K;
|
||||
case 352800:
|
||||
return MTK_AFE_RATE_352K;
|
||||
case 384000:
|
||||
return MTK_AFE_RATE_384K;
|
||||
default:
|
||||
dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
|
||||
__func__, rate, MTK_AFE_RATE_48K);
|
||||
}
|
||||
|
||||
return MTK_AFE_RATE_48K;
|
||||
}
|
||||
|
||||
static unsigned int tdm_rate_transform(struct device *dev, unsigned int rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case 8000:
|
||||
return MTK_AFE_TDM_RATE_8K;
|
||||
case 11025:
|
||||
return MTK_AFE_TDM_RATE_11K;
|
||||
case 12000:
|
||||
return MTK_AFE_TDM_RATE_12K;
|
||||
case 16000:
|
||||
return MTK_AFE_TDM_RATE_16K;
|
||||
case 22050:
|
||||
return MTK_AFE_TDM_RATE_22K;
|
||||
case 24000:
|
||||
return MTK_AFE_TDM_RATE_24K;
|
||||
case 32000:
|
||||
return MTK_AFE_TDM_RATE_32K;
|
||||
case 44100:
|
||||
return MTK_AFE_TDM_RATE_44K;
|
||||
case 48000:
|
||||
return MTK_AFE_TDM_RATE_48K;
|
||||
case 64000:
|
||||
return MTK_AFE_TDM_RATE_64K;
|
||||
case 88200:
|
||||
return MTK_AFE_TDM_RATE_88K;
|
||||
case 96000:
|
||||
return MTK_AFE_TDM_RATE_96K;
|
||||
case 128000:
|
||||
return MTK_AFE_TDM_RATE_128K;
|
||||
case 176400:
|
||||
return MTK_AFE_TDM_RATE_176K;
|
||||
case 192000:
|
||||
return MTK_AFE_TDM_RATE_192K;
|
||||
case 256000:
|
||||
return MTK_AFE_TDM_RATE_256K;
|
||||
case 352800:
|
||||
return MTK_AFE_TDM_RATE_352K;
|
||||
case 384000:
|
||||
return MTK_AFE_TDM_RATE_384K;
|
||||
default:
|
||||
dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
|
||||
__func__, rate, MTK_AFE_TDM_RATE_48K);
|
||||
}
|
||||
|
||||
return MTK_AFE_TDM_RATE_48K;
|
||||
}
|
||||
|
||||
static unsigned int pcm_rate_transform(struct device *dev, unsigned int rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case 8000:
|
||||
return MTK_AFE_PCM_RATE_8K;
|
||||
case 16000:
|
||||
return MTK_AFE_PCM_RATE_16K;
|
||||
case 32000:
|
||||
return MTK_AFE_PCM_RATE_32K;
|
||||
case 48000:
|
||||
return MTK_AFE_PCM_RATE_48K;
|
||||
default:
|
||||
dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
|
||||
__func__, rate, MTK_AFE_PCM_RATE_48K);
|
||||
}
|
||||
|
||||
return MTK_AFE_PCM_RATE_48K;
|
||||
}
|
||||
|
||||
unsigned int mt8186_tdm_relatch_rate_transform(struct device *dev, unsigned int rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case 8000:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_8K;
|
||||
case 11025:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_11K;
|
||||
case 12000:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_12K;
|
||||
case 16000:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_16K;
|
||||
case 22050:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_22K;
|
||||
case 24000:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_24K;
|
||||
case 32000:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_32K;
|
||||
case 44100:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_44K;
|
||||
case 48000:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_48K;
|
||||
case 88200:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_88K;
|
||||
case 96000:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_96K;
|
||||
case 176400:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_176K;
|
||||
case 192000:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_192K;
|
||||
case 352800:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_352K;
|
||||
case 384000:
|
||||
return MTK_AFE_TDM_RELATCH_RATE_384K;
|
||||
default:
|
||||
dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
|
||||
__func__, rate, MTK_AFE_TDM_RELATCH_RATE_48K);
|
||||
}
|
||||
|
||||
return MTK_AFE_TDM_RELATCH_RATE_48K;
|
||||
}
|
||||
|
||||
unsigned int mt8186_rate_transform(struct device *dev, unsigned int rate, int aud_blk)
|
||||
{
|
||||
switch (aud_blk) {
|
||||
case MT8186_DAI_PCM:
|
||||
return pcm_rate_transform(dev, rate);
|
||||
case MT8186_DAI_TDM_IN:
|
||||
return tdm_rate_transform(dev, rate);
|
||||
default:
|
||||
return mt8186_general_rate_transform(dev, rate);
|
||||
}
|
||||
}
|
||||
|
||||
int mt8186_dai_set_priv(struct mtk_base_afe *afe, int id, int priv_size, const void *priv_data)
|
||||
{
|
||||
struct mt8186_afe_private *afe_priv = afe->platform_priv;
|
||||
void *temp_data;
|
||||
|
||||
temp_data = devm_kzalloc(afe->dev,
|
||||
priv_size,
|
||||
GFP_KERNEL);
|
||||
if (!temp_data)
|
||||
return -ENOMEM;
|
||||
|
||||
if (priv_data)
|
||||
memcpy(temp_data, priv_data, priv_size);
|
||||
|
||||
afe_priv->dai_priv[id] = temp_data;
|
||||
|
||||
return 0;
|
||||
}
|
3000
sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
Normal file
3000
sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -75,8 +75,7 @@ static struct mtk_afe_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe,
|
||||
struct mt8186_afe_private *afe_priv = afe->platform_priv;
|
||||
int dai_id;
|
||||
|
||||
if (strncmp(name, "aud_dac_hires_clk", 7) == 0 ||
|
||||
strncmp(name, "aud_adc_hires_clk", 7) == 0)
|
||||
if (strncmp(name, "aud_dac", 7) == 0 || strncmp(name, "aud_adc", 7) == 0)
|
||||
dai_id = MT8186_DAI_ADDA;
|
||||
else
|
||||
return NULL;
|
||||
@ -655,11 +654,6 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
|
||||
dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",
|
||||
__func__, id, substream->stream, rate);
|
||||
|
||||
if (!adda_priv) {
|
||||
dev_err(afe->dev, "%s(), adda_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
unsigned int dl_src2_con0;
|
||||
unsigned int dl_src2_con1;
|
||||
|
@ -119,12 +119,6 @@ static int mt8186_i2s_hd_get(struct snd_kcontrol *kcontrol,
|
||||
struct mtk_afe_i2s_priv *i2s_priv;
|
||||
|
||||
i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ucontrol->value.integer.value[0] = i2s_priv->low_jitter_en;
|
||||
|
||||
return 0;
|
||||
@ -148,12 +142,6 @@ static int mt8186_i2s_hd_set(struct snd_kcontrol *kcontrol,
|
||||
__func__, kcontrol->id.name, hd_en);
|
||||
|
||||
i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (i2s_priv->low_jitter_en == hd_en)
|
||||
return 0;
|
||||
|
||||
@ -377,11 +365,6 @@ static int mtk_i2s_en_event(struct snd_soc_dapm_widget *w,
|
||||
|
||||
i2s_priv = get_i2s_priv_by_name(afe, w->name);
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
|
||||
__func__, w->name, event);
|
||||
|
||||
@ -442,11 +425,6 @@ static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w,
|
||||
|
||||
i2s_priv = get_i2s_priv_by_name(afe, w->name);
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
mt8186_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate);
|
||||
@ -566,12 +544,6 @@ static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source,
|
||||
struct mtk_afe_i2s_priv *i2s_priv;
|
||||
|
||||
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i2s_priv->share_i2s_id < 0)
|
||||
return 0;
|
||||
|
||||
@ -587,12 +559,6 @@ static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget *source,
|
||||
struct mtk_afe_i2s_priv *i2s_priv;
|
||||
|
||||
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (get_i2s_id_by_name(afe, sink->name) ==
|
||||
get_i2s_id_by_name(afe, source->name))
|
||||
return i2s_priv->low_jitter_en;
|
||||
@ -618,15 +584,8 @@ static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source,
|
||||
int i2s_need_apll;
|
||||
|
||||
i2s_priv = get_i2s_priv_by_name(afe, w->name);
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* which apll */
|
||||
cur_apll = mt8186_get_apll_by_name(afe, source->name);
|
||||
|
||||
/* choose APLL from i2s rate */
|
||||
i2s_need_apll = mt8186_get_apll_by_rate(afe, i2s_priv->rate);
|
||||
|
||||
@ -642,12 +601,6 @@ static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source,
|
||||
struct mtk_afe_i2s_priv *i2s_priv;
|
||||
|
||||
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (get_i2s_id_by_name(afe, sink->name) ==
|
||||
get_i2s_id_by_name(afe, source->name))
|
||||
return (i2s_priv->mclk_rate > 0) ? 1 : 0;
|
||||
@ -672,12 +625,6 @@ static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source,
|
||||
int cur_apll;
|
||||
|
||||
i2s_priv = get_i2s_priv_by_name(afe, w->name);
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* which apll */
|
||||
cur_apll = mt8186_get_apll_by_name(afe, source->name);
|
||||
|
||||
@ -980,11 +927,6 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe,
|
||||
dev_dbg(afe->dev, "%s(), id %d, rate %d, format %d\n",
|
||||
__func__, i2s_id, rate, format);
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i2s_priv->rate = rate;
|
||||
|
||||
switch (i2s_id) {
|
||||
@ -1053,11 +995,6 @@ static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,
|
||||
int apll;
|
||||
int apll_rate;
|
||||
|
||||
if (!i2s_priv) {
|
||||
dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dir != SND_SOC_CLOCK_OUT) {
|
||||
dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
|
||||
return -EINVAL;
|
||||
|
@ -287,11 +287,6 @@ static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
struct mt8186_afe_private *afe_priv = afe->platform_priv;
|
||||
struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[dai->id];
|
||||
|
||||
if (!pcm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* DAI mode*/
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
|
@ -106,11 +106,6 @@ static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,
|
||||
int dai_id = get_tdm_id_by_name(w->name);
|
||||
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
|
||||
|
||||
if (!tdm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
|
||||
__func__, w->name, event);
|
||||
|
||||
@ -138,11 +133,6 @@ static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
|
||||
int dai_id = get_tdm_id_by_name(w->name);
|
||||
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
|
||||
|
||||
if (!tdm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
|
||||
__func__, w->name, event, dai_id);
|
||||
|
||||
@ -215,11 +205,6 @@ static int mtk_afe_tdm_mclk_connect(struct snd_soc_dapm_widget *source,
|
||||
int dai_id = get_tdm_id_by_name(w->name);
|
||||
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
|
||||
|
||||
if (!tdm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (tdm_priv->mclk_rate > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
@ -250,11 +235,6 @@ static int mtk_afe_tdm_hd_connect(struct snd_soc_dapm_widget *source,
|
||||
int dai_id = get_tdm_id_by_name(w->name);
|
||||
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
|
||||
|
||||
if (!tdm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tdm_priv->low_jitter_en;
|
||||
}
|
||||
|
||||
@ -270,11 +250,6 @@ static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
|
||||
int cur_apll;
|
||||
int tdm_need_apll;
|
||||
|
||||
if (!tdm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* which apll */
|
||||
cur_apll = mt8186_get_apll_by_name(afe, source->name);
|
||||
|
||||
@ -303,11 +278,6 @@ static int mt8186_tdm_hd_get(struct snd_kcontrol *kcontrol,
|
||||
int dai_id = get_tdm_id_by_name(kcontrol->id.name);
|
||||
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
|
||||
|
||||
if (!tdm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ucontrol->value.integer.value[0] = tdm_priv->low_jitter_en;
|
||||
|
||||
return 0;
|
||||
@ -332,11 +302,6 @@ static int mt8186_tdm_hd_set(struct snd_kcontrol *kcontrol,
|
||||
dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
|
||||
__func__, kcontrol->id.name, hd_en);
|
||||
|
||||
if (!tdm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tdm_priv->low_jitter_en == hd_en)
|
||||
return 0;
|
||||
|
||||
@ -421,22 +386,14 @@ static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
|
||||
unsigned int tran_rate;
|
||||
unsigned int tran_relatch_rate;
|
||||
|
||||
if (!tdm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tdm_priv->rate = rate;
|
||||
|
||||
tran_rate = mt8186_rate_transform(afe->dev, rate, dai->id);
|
||||
tran_relatch_rate = mt8186_tdm_relatch_rate_transform(afe->dev, rate);
|
||||
|
||||
/* calculate mclk_rate, if not set explicitly */
|
||||
if (!tdm_priv->mclk_rate) {
|
||||
tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
|
||||
mtk_dai_tdm_cal_mclk(afe,
|
||||
tdm_priv,
|
||||
tdm_priv->mclk_rate);
|
||||
mtk_dai_tdm_cal_mclk(afe, tdm_priv, tdm_priv->mclk_rate);
|
||||
}
|
||||
|
||||
/* ETDM_IN1_CON0 */
|
||||
@ -508,11 +465,6 @@ static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
|
||||
struct mt8186_afe_private *afe_priv = afe->platform_priv;
|
||||
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
|
||||
|
||||
if (!tdm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dir != SND_SOC_CLOCK_IN) {
|
||||
dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
|
||||
return -EINVAL;
|
||||
@ -529,11 +481,6 @@ static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
struct mt8186_afe_private *afe_priv = afe->platform_priv;
|
||||
struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
|
||||
|
||||
if (!tdm_priv) {
|
||||
dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* DAI mode*/
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
|
57
sound/soc/mediatek/mt8186/mt8186-mt6366-common.c
Normal file
57
sound/soc/mediatek/mt8186/mt8186-mt6366-common.c
Normal file
@ -0,0 +1,57 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// mt8186-mt6366-common.c
|
||||
// -- MT8186 MT6366 ALSA common driver
|
||||
//
|
||||
// Copyright (c) 2022 MediaTek Inc.
|
||||
// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
|
||||
//
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "../../codecs/mt6358.h"
|
||||
#include "../common/mtk-afe-platform-driver.h"
|
||||
#include "mt8186-afe-common.h"
|
||||
#include "mt8186-mt6366-common.h"
|
||||
|
||||
int mt8186_mt6366_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_component *cmpnt_afe =
|
||||
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
|
||||
struct snd_soc_component *cmpnt_codec =
|
||||
asoc_rtd_to_codec(rtd, 0)->component;
|
||||
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
|
||||
struct mt8186_afe_private *afe_priv = afe->platform_priv;
|
||||
struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
|
||||
int ret;
|
||||
|
||||
/* set mtkaif protocol */
|
||||
mt6358_set_mtkaif_protocol(cmpnt_codec,
|
||||
MT6358_MTKAIF_PROTOCOL_1);
|
||||
afe_priv->mtkaif_protocol = MT6358_MTKAIF_PROTOCOL_1;
|
||||
|
||||
ret = snd_soc_dapm_sync(dapm);
|
||||
if (ret) {
|
||||
dev_err(rtd->dev, "failed to snd_soc_dapm_sync\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt8186_mt6366_init);
|
||||
|
||||
int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *link,
|
||||
struct device_node *node,
|
||||
char *link_name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (node && strcmp(link->name, link_name) == 0) {
|
||||
ret = snd_soc_of_get_dai_link_codecs(card->dev, node, link);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(card->dev, ret, "get dai link codecs fail\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt8186_mt6366_card_set_be_link);
|
17
sound/soc/mediatek/mt8186/mt8186-mt6366-common.h
Normal file
17
sound/soc/mediatek/mt8186/mt8186-mt6366-common.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* mt8186-mt6366-common.h
|
||||
*
|
||||
* Copyright (c) 2022 MediaTek Inc.
|
||||
* Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _MT8186_MT6366_COMMON_H_
|
||||
#define _MT8186_MT6366_COMMON_H_
|
||||
|
||||
int mt8186_mt6366_init(struct snd_soc_pcm_runtime *rtd);
|
||||
int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *link,
|
||||
struct device_node *node,
|
||||
char *link_name);
|
||||
#endif
|
1002
sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
Normal file
1002
sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
Normal file
File diff suppressed because it is too large
Load Diff
978
sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c
Normal file
978
sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c
Normal file
@ -0,0 +1,978 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// mt8186-mt6366-rt1019-rt5682s.c
|
||||
// -- MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver
|
||||
//
|
||||
// Copyright (c) 2022 MediaTek Inc.
|
||||
// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
|
||||
//
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/rt5682.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "../../codecs/mt6358.h"
|
||||
#include "../../codecs/rt5682.h"
|
||||
#include "../common/mtk-afe-platform-driver.h"
|
||||
#include "mt8186-afe-common.h"
|
||||
#include "mt8186-afe-clk.h"
|
||||
#include "mt8186-afe-gpio.h"
|
||||
#include "mt8186-mt6366-common.h"
|
||||
|
||||
#define RT1019_CODEC_DAI "HiFi"
|
||||
#define RT1019_DEV0_NAME "rt1019p"
|
||||
|
||||
#define RT5682S_CODEC_DAI "rt5682s-aif1"
|
||||
#define RT5682S_DEV0_NAME "rt5682s.5-001a"
|
||||
|
||||
struct mt8186_mt6366_rt1019_rt5682s_priv {
|
||||
struct snd_soc_jack headset_jack, hdmi_jack;
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_conf mt8186_mt6366_rt1019_rt5682s_codec_conf[] = {
|
||||
{
|
||||
.dlc = COMP_CODEC_CONF("mt6358-sound"),
|
||||
.name_prefix = "Mt6366",
|
||||
},
|
||||
{
|
||||
.dlc = COMP_CODEC_CONF("bt-sco"),
|
||||
.name_prefix = "Mt8186 bt",
|
||||
},
|
||||
{
|
||||
.dlc = COMP_CODEC_CONF("hdmi-audio-codec"),
|
||||
.name_prefix = "Mt8186 hdmi",
|
||||
},
|
||||
};
|
||||
|
||||
static int mt8186_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct mt8186_mt6366_rt1019_rt5682s_priv *priv =
|
||||
snd_soc_card_get_drvdata(rtd->card);
|
||||
struct snd_soc_jack *jack = &priv->headset_jack;
|
||||
struct snd_soc_component *cmpnt_codec =
|
||||
asoc_rtd_to_codec(rtd, 0)->component;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
|
||||
SND_JACK_HEADSET | SND_JACK_BTN_0 |
|
||||
SND_JACK_BTN_1 | SND_JACK_BTN_2 |
|
||||
SND_JACK_BTN_3,
|
||||
jack);
|
||||
if (ret) {
|
||||
dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
|
||||
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
|
||||
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
|
||||
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
|
||||
|
||||
return snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
|
||||
}
|
||||
|
||||
static int mt8186_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
unsigned int rate = params_rate(params);
|
||||
unsigned int mclk_fs_ratio = 128;
|
||||
unsigned int mclk_fs = rate * mclk_fs_ratio;
|
||||
int bitwidth;
|
||||
int ret;
|
||||
|
||||
bitwidth = snd_pcm_format_width(params_format(params));
|
||||
if (bitwidth < 0) {
|
||||
dev_err(card->dev, "invalid bit width: %d\n", bitwidth);
|
||||
return bitwidth;
|
||||
}
|
||||
|
||||
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "failed to set tdm slot\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1,
|
||||
RT5682_PLL1_S_BCLK1,
|
||||
params_rate(params) * 64,
|
||||
params_rate(params) * 512);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "failed to set pll\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai,
|
||||
RT5682_SCLK_S_PLL1,
|
||||
params_rate(params) * 512,
|
||||
SND_SOC_CLOCK_IN);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "failed to set sysclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
|
||||
}
|
||||
|
||||
static const struct snd_soc_ops mt8186_rt5682s_i2s_ops = {
|
||||
.hw_params = mt8186_rt5682s_i2s_hw_params,
|
||||
};
|
||||
|
||||
static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_component *cmpnt_codec =
|
||||
asoc_rtd_to_codec(rtd, 0)->component;
|
||||
struct mt8186_mt6366_rt1019_rt5682s_priv *priv =
|
||||
snd_soc_card_get_drvdata(rtd->card);
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, &priv->hdmi_jack);
|
||||
if (ret) {
|
||||
dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
|
||||
}
|
||||
|
||||
static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params,
|
||||
snd_pcm_format_t fmt)
|
||||
{
|
||||
struct snd_interval *channels = hw_param_interval(params,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||
|
||||
dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt);
|
||||
|
||||
/* fix BE i2s channel to 2 channel */
|
||||
channels->min = 2;
|
||||
channels->max = 2;
|
||||
|
||||
/* clean param mask first */
|
||||
snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
|
||||
0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
|
||||
|
||||
params_set_format(params, fmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE);
|
||||
}
|
||||
|
||||
static int mt8186_it6505_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE);
|
||||
}
|
||||
|
||||
static int mt8186_mt6366_rt1019_rt5682s_playback_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
static const unsigned int rates[] = {
|
||||
48000
|
||||
};
|
||||
static const unsigned int channels[] = {
|
||||
2
|
||||
};
|
||||
static const struct snd_pcm_hw_constraint_list constraints_rates = {
|
||||
.count = ARRAY_SIZE(rates),
|
||||
.list = rates,
|
||||
.mask = 0,
|
||||
};
|
||||
static const struct snd_pcm_hw_constraint_list constraints_channels = {
|
||||
.count = ARRAY_SIZE(channels),
|
||||
.list = channels,
|
||||
.mask = 0,
|
||||
};
|
||||
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
int ret;
|
||||
|
||||
ret = snd_pcm_hw_constraint_list(runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
&constraints_rates);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_pcm_hw_constraint_list(runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
&constraints_channels);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "hw_constraint_list channel failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_playback_ops = {
|
||||
.startup = mt8186_mt6366_rt1019_rt5682s_playback_startup,
|
||||
};
|
||||
|
||||
static int mt8186_mt6366_rt1019_rt5682s_capture_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
static const unsigned int rates[] = {
|
||||
48000
|
||||
};
|
||||
static const unsigned int channels[] = {
|
||||
1, 2
|
||||
};
|
||||
static const struct snd_pcm_hw_constraint_list constraints_rates = {
|
||||
.count = ARRAY_SIZE(rates),
|
||||
.list = rates,
|
||||
.mask = 0,
|
||||
};
|
||||
static const struct snd_pcm_hw_constraint_list constraints_channels = {
|
||||
.count = ARRAY_SIZE(channels),
|
||||
.list = channels,
|
||||
.mask = 0,
|
||||
};
|
||||
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
int ret;
|
||||
|
||||
ret = snd_pcm_hw_constraint_list(runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
&constraints_rates);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_pcm_hw_constraint_list(runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
&constraints_channels);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "hw_constraint_list channel failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_capture_ops = {
|
||||
.startup = mt8186_mt6366_rt1019_rt5682s_capture_startup,
|
||||
};
|
||||
|
||||
/* FE */
|
||||
SND_SOC_DAILINK_DEFS(playback1,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(playback12,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("DL12")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(playback2,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(playback3,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(playback4,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("DL4")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(playback5,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("DL5")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(playback6,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(playback7,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(playback8,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(capture1,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(capture2,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(capture3,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(capture4,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(capture5,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(capture6,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
SND_SOC_DAILINK_DEFS(capture7,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("UL7")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
/* hostless */
|
||||
SND_SOC_DAILINK_DEFS(hostless_lpbk,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hostless_fm,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hostless_src1,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hostless_src_bargein,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
/* BE */
|
||||
SND_SOC_DAILINK_DEFS(adda,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound",
|
||||
"mt6358-snd-codec-aif1"),
|
||||
COMP_CODEC("dmic-codec",
|
||||
"dmic-hifi")),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(i2s0,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(i2s1,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(i2s2,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(i2s3,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hw_gain1,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hw_gain2,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hw_src1,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hw_src2,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(connsys_i2s,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(pcm1,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(tdm_in,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
/* hostless */
|
||||
SND_SOC_DAILINK_DEFS(hostless_ul1,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hostless_ul2,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hostless_ul3,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hostless_ul5,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hostless_ul6,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
SND_SOC_DAILINK_DEFS(hostless_src_aaudio,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")),
|
||||
DAILINK_COMP_ARRAY(COMP_DUMMY()),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
|
||||
/* Front End DAI links */
|
||||
{
|
||||
.name = "Playback_1",
|
||||
.stream_name = "Playback_1",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_merged_format = 1,
|
||||
.dpcm_merged_chan = 1,
|
||||
.dpcm_merged_rate = 1,
|
||||
.ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops,
|
||||
SND_SOC_DAILINK_REG(playback1),
|
||||
},
|
||||
{
|
||||
.name = "Playback_12",
|
||||
.stream_name = "Playback_12",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
SND_SOC_DAILINK_REG(playback12),
|
||||
},
|
||||
{
|
||||
.name = "Playback_2",
|
||||
.stream_name = "Playback_2",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_merged_format = 1,
|
||||
.dpcm_merged_chan = 1,
|
||||
.dpcm_merged_rate = 1,
|
||||
SND_SOC_DAILINK_REG(playback2),
|
||||
},
|
||||
{
|
||||
.name = "Playback_3",
|
||||
.stream_name = "Playback_3",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_merged_format = 1,
|
||||
.dpcm_merged_chan = 1,
|
||||
.dpcm_merged_rate = 1,
|
||||
.ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops,
|
||||
SND_SOC_DAILINK_REG(playback3),
|
||||
},
|
||||
{
|
||||
.name = "Playback_4",
|
||||
.stream_name = "Playback_4",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
SND_SOC_DAILINK_REG(playback4),
|
||||
},
|
||||
{
|
||||
.name = "Playback_5",
|
||||
.stream_name = "Playback_5",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
SND_SOC_DAILINK_REG(playback5),
|
||||
},
|
||||
{
|
||||
.name = "Playback_6",
|
||||
.stream_name = "Playback_6",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
SND_SOC_DAILINK_REG(playback6),
|
||||
},
|
||||
{
|
||||
.name = "Playback_7",
|
||||
.stream_name = "Playback_7",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
SND_SOC_DAILINK_REG(playback7),
|
||||
},
|
||||
{
|
||||
.name = "Playback_8",
|
||||
.stream_name = "Playback_8",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
SND_SOC_DAILINK_REG(playback8),
|
||||
},
|
||||
{
|
||||
.name = "Capture_1",
|
||||
.stream_name = "Capture_1",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_capture = 1,
|
||||
SND_SOC_DAILINK_REG(capture1),
|
||||
},
|
||||
{
|
||||
.name = "Capture_2",
|
||||
.stream_name = "Capture_2",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_capture = 1,
|
||||
.dpcm_merged_format = 1,
|
||||
.dpcm_merged_chan = 1,
|
||||
.dpcm_merged_rate = 1,
|
||||
.ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops,
|
||||
SND_SOC_DAILINK_REG(capture2),
|
||||
},
|
||||
{
|
||||
.name = "Capture_3",
|
||||
.stream_name = "Capture_3",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_capture = 1,
|
||||
SND_SOC_DAILINK_REG(capture3),
|
||||
},
|
||||
{
|
||||
.name = "Capture_4",
|
||||
.stream_name = "Capture_4",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_capture = 1,
|
||||
.dpcm_merged_format = 1,
|
||||
.dpcm_merged_chan = 1,
|
||||
.dpcm_merged_rate = 1,
|
||||
.ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops,
|
||||
SND_SOC_DAILINK_REG(capture4),
|
||||
},
|
||||
{
|
||||
.name = "Capture_5",
|
||||
.stream_name = "Capture_5",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_capture = 1,
|
||||
SND_SOC_DAILINK_REG(capture5),
|
||||
},
|
||||
{
|
||||
.name = "Capture_6",
|
||||
.stream_name = "Capture_6",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_capture = 1,
|
||||
.dpcm_merged_format = 1,
|
||||
.dpcm_merged_chan = 1,
|
||||
.dpcm_merged_rate = 1,
|
||||
SND_SOC_DAILINK_REG(capture6),
|
||||
},
|
||||
{
|
||||
.name = "Capture_7",
|
||||
.stream_name = "Capture_7",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_capture = 1,
|
||||
SND_SOC_DAILINK_REG(capture7),
|
||||
},
|
||||
{
|
||||
.name = "Hostless_LPBK",
|
||||
.stream_name = "Hostless_LPBK",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_lpbk),
|
||||
},
|
||||
{
|
||||
.name = "Hostless_FM",
|
||||
.stream_name = "Hostless_FM",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_fm),
|
||||
},
|
||||
{
|
||||
.name = "Hostless_SRC_1",
|
||||
.stream_name = "Hostless_SRC_1",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_src1),
|
||||
},
|
||||
{
|
||||
.name = "Hostless_SRC_Bargein",
|
||||
.stream_name = "Hostless_SRC_Bargein",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_src_bargein),
|
||||
},
|
||||
{
|
||||
.name = "Hostless_HW_Gain_AAudio",
|
||||
.stream_name = "Hostless_HW_Gain_AAudio",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio),
|
||||
},
|
||||
{
|
||||
.name = "Hostless_SRC_AAudio",
|
||||
.stream_name = "Hostless_SRC_AAudio",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
|
||||
SND_SOC_DPCM_TRIGGER_PRE},
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_src_aaudio),
|
||||
},
|
||||
/* Back End DAI links */
|
||||
{
|
||||
.name = "Primary Codec",
|
||||
.no_pcm = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
.init = mt8186_mt6366_init,
|
||||
SND_SOC_DAILINK_REG(adda),
|
||||
},
|
||||
{
|
||||
.name = "I2S3",
|
||||
.no_pcm = 1,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_IB_IF |
|
||||
SND_SOC_DAIFMT_CBM_CFM,
|
||||
.dpcm_playback = 1,
|
||||
.ignore_suspend = 1,
|
||||
.init = mt8186_mt6366_rt1019_rt5682s_hdmi_init,
|
||||
.be_hw_params_fixup = mt8186_it6505_i2s_hw_params_fixup,
|
||||
SND_SOC_DAILINK_REG(i2s3),
|
||||
},
|
||||
{
|
||||
.name = "I2S0",
|
||||
.no_pcm = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
|
||||
.ops = &mt8186_rt5682s_i2s_ops,
|
||||
SND_SOC_DAILINK_REG(i2s0),
|
||||
},
|
||||
{
|
||||
.name = "I2S1",
|
||||
.no_pcm = 1,
|
||||
.dpcm_playback = 1,
|
||||
.ignore_suspend = 1,
|
||||
.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
|
||||
.init = mt8186_rt5682s_init,
|
||||
.ops = &mt8186_rt5682s_i2s_ops,
|
||||
SND_SOC_DAILINK_REG(i2s1),
|
||||
},
|
||||
{
|
||||
.name = "I2S2",
|
||||
.no_pcm = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
|
||||
SND_SOC_DAILINK_REG(i2s2),
|
||||
},
|
||||
{
|
||||
.name = "HW Gain 1",
|
||||
.no_pcm = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hw_gain1),
|
||||
},
|
||||
{
|
||||
.name = "HW Gain 2",
|
||||
.no_pcm = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hw_gain2),
|
||||
},
|
||||
{
|
||||
.name = "HW_SRC_1",
|
||||
.no_pcm = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hw_src1),
|
||||
},
|
||||
{
|
||||
.name = "HW_SRC_2",
|
||||
.no_pcm = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hw_src2),
|
||||
},
|
||||
{
|
||||
.name = "CONNSYS_I2S",
|
||||
.no_pcm = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(connsys_i2s),
|
||||
},
|
||||
{
|
||||
.name = "PCM 1",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_IF,
|
||||
.no_pcm = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(pcm1),
|
||||
},
|
||||
{
|
||||
.name = "TDM IN",
|
||||
.no_pcm = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(tdm_in),
|
||||
},
|
||||
/* dummy BE for ul memif to record from dl memif */
|
||||
{
|
||||
.name = "Hostless_UL1",
|
||||
.no_pcm = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_ul1),
|
||||
},
|
||||
{
|
||||
.name = "Hostless_UL2",
|
||||
.no_pcm = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_ul2),
|
||||
},
|
||||
{
|
||||
.name = "Hostless_UL3",
|
||||
.no_pcm = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_ul3),
|
||||
},
|
||||
{
|
||||
.name = "Hostless_UL5",
|
||||
.no_pcm = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_ul5),
|
||||
},
|
||||
{
|
||||
.name = "Hostless_UL6",
|
||||
.no_pcm = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ignore_suspend = 1,
|
||||
SND_SOC_DAILINK_REG(hostless_ul6),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget
|
||||
mt8186_mt6366_rt1019_rt5682s_widgets[] = {
|
||||
SND_SOC_DAPM_SPK("Speakers", NULL),
|
||||
SND_SOC_DAPM_OUTPUT("HDMI1"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route
|
||||
mt8186_mt6366_rt1019_rt5682s_routes[] = {
|
||||
/* SPK */
|
||||
{ "Speakers", NULL, "Speaker" },
|
||||
/* HDMI */
|
||||
{ "HDMI1", NULL, "TX" },
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new
|
||||
mt8186_mt6366_rt1019_rt5682s_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Speakers"),
|
||||
SOC_DAPM_PIN_SWITCH("HDMI1"),
|
||||
};
|
||||
|
||||
static struct snd_soc_card mt8186_mt6366_rt1019_rt5682s_soc_card = {
|
||||
.name = "mt8186_mt6366_rt1019_rt5682s",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links,
|
||||
.num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links),
|
||||
.controls = mt8186_mt6366_rt1019_rt5682s_controls,
|
||||
.num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls),
|
||||
.dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets),
|
||||
.dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes),
|
||||
.codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf,
|
||||
.num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf),
|
||||
};
|
||||
|
||||
static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card;
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
struct mt8186_mt6366_rt1019_rt5682s_priv *priv;
|
||||
struct device_node *platform_node, *headset_codec, *playback_codec;
|
||||
int ret, i;
|
||||
|
||||
card = (struct snd_soc_card *)device_get_match_data(&pdev->dev);
|
||||
if (!card)
|
||||
return -EINVAL;
|
||||
card->dev = &pdev->dev;
|
||||
|
||||
platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
|
||||
if (!platform_node) {
|
||||
ret = -EINVAL;
|
||||
dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs");
|
||||
if (!playback_codec) {
|
||||
ret = -EINVAL;
|
||||
dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n");
|
||||
goto err_playback_codec;
|
||||
}
|
||||
|
||||
headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec");
|
||||
if (!headset_codec) {
|
||||
ret = -EINVAL;
|
||||
dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n");
|
||||
goto err_headset_codec;
|
||||
}
|
||||
|
||||
for_each_card_prelinks(card, i, dai_link) {
|
||||
ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3");
|
||||
if (ret) {
|
||||
dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n",
|
||||
dai_link->name);
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0");
|
||||
if (ret) {
|
||||
dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
|
||||
dai_link->name);
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1");
|
||||
if (ret) {
|
||||
dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
|
||||
dai_link->name);
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
if (!dai_link->platforms->name)
|
||||
dai_link->platforms->of_node = platform_node;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
ret = -ENOMEM;
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
snd_soc_card_set_drvdata(card, priv);
|
||||
|
||||
ret = mt8186_afe_gpio_init(&pdev->dev);
|
||||
if (ret) {
|
||||
dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__);
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
if (ret)
|
||||
dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__);
|
||||
|
||||
err_probe:
|
||||
of_node_put(headset_codec);
|
||||
err_headset_codec:
|
||||
of_node_put(playback_codec);
|
||||
err_playback_codec:
|
||||
of_node_put(platform_node);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id mt8186_mt6366_rt1019_rt5682s_dt_match[] = {
|
||||
{ .compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound",
|
||||
.data = &mt8186_mt6366_rt1019_rt5682s_soc_card,
|
||||
},
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver mt8186_mt6366_rt1019_rt5682s_driver = {
|
||||
.driver = {
|
||||
.name = "mt8186_mt6366_rt1019_rt5682s",
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
.of_match_table = mt8186_mt6366_rt1019_rt5682s_dt_match,
|
||||
#endif
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = mt8186_mt6366_rt1019_rt5682s_dev_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(mt8186_mt6366_rt1019_rt5682s_driver);
|
||||
|
||||
/* Module information */
|
||||
MODULE_DESCRIPTION("MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver");
|
||||
MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("mt8186_mt6366_rt1019_rt5682s soc card");
|
@ -20,6 +20,8 @@
|
||||
#include "../../codecs/rt1011.h"
|
||||
#include "../../codecs/rt5682.h"
|
||||
#include "../common/mtk-afe-platform-driver.h"
|
||||
#include "../common/mtk-dsp-sof-common.h"
|
||||
#include "../common/mtk-soc-card.h"
|
||||
#include "mt8195-afe-clk.h"
|
||||
#include "mt8195-afe-common.h"
|
||||
|
||||
@ -54,13 +56,6 @@ struct mt8195_card_data {
|
||||
unsigned long quirk;
|
||||
};
|
||||
|
||||
struct sof_conn_stream {
|
||||
const char *normal_link;
|
||||
const char *sof_link;
|
||||
const char *sof_dma;
|
||||
int stream_dir;
|
||||
};
|
||||
|
||||
struct mt8195_mt6359_priv {
|
||||
struct snd_soc_jack headset_jack;
|
||||
struct snd_soc_jack dp_jack;
|
||||
@ -374,7 +369,8 @@ static const struct snd_soc_ops mt8195_dptx_ops = {
|
||||
|
||||
static int mt8195_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct mt8195_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
|
||||
struct snd_soc_component *cmpnt_codec =
|
||||
asoc_rtd_to_codec(rtd, 0)->component;
|
||||
int ret;
|
||||
@ -389,7 +385,8 @@ static int mt8195_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||
|
||||
static int mt8195_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct mt8195_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
|
||||
struct snd_soc_component *cmpnt_codec =
|
||||
asoc_rtd_to_codec(rtd, 0)->component;
|
||||
int ret;
|
||||
@ -555,7 +552,8 @@ static int mt8195_rt5682_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_component *cmpnt_codec =
|
||||
asoc_rtd_to_codec(rtd, 0)->component;
|
||||
struct mt8195_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
|
||||
struct snd_soc_jack *jack = &priv->headset_jack;
|
||||
struct snd_soc_component *cmpnt_afe =
|
||||
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
|
||||
@ -722,7 +720,8 @@ static int mt8195_set_bias_level_post(struct snd_soc_card *card,
|
||||
struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
|
||||
{
|
||||
struct snd_soc_component *component = dapm->component;
|
||||
struct mt8195_mt6359_priv *priv = snd_soc_card_get_drvdata(card);
|
||||
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
|
||||
struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -1321,175 +1320,24 @@ static struct snd_soc_card mt8195_mt6359_soc_card = {
|
||||
static int mt8195_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct snd_soc_dai_link *sof_dai_link = NULL;
|
||||
struct snd_soc_pcm_runtime *runtime;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
int i, j, ret = 0;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(g_sof_conn_streams); i++) {
|
||||
const struct sof_conn_stream *conn = &g_sof_conn_streams[i];
|
||||
|
||||
if (strcmp(rtd->dai_link->name, conn->normal_link))
|
||||
continue;
|
||||
|
||||
for_each_card_rtds(card, runtime) {
|
||||
if (strcmp(runtime->dai_link->name, conn->sof_link))
|
||||
continue;
|
||||
|
||||
for_each_rtd_cpu_dais(runtime, j, cpu_dai) {
|
||||
if (cpu_dai->stream_active[conn->stream_dir] > 0) {
|
||||
sof_dai_link = runtime->dai_link;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (sof_dai_link && sof_dai_link->be_hw_params_fixup)
|
||||
ret = sof_dai_link->be_hw_params_fixup(runtime, params);
|
||||
|
||||
break;
|
||||
}
|
||||
ret = mtk_sof_dai_link_fixup(rtd, params);
|
||||
|
||||
if (!strcmp(rtd->dai_link->name, "ETDM2_IN_BE") ||
|
||||
!strcmp(rtd->dai_link->name, "ETDM1_OUT_BE")) {
|
||||
mt8195_etdm_hw_params_fixup(runtime, params);
|
||||
mt8195_etdm_hw_params_fixup(rtd, params);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt8195_mt6359_card_late_probe(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *runtime;
|
||||
struct snd_soc_component *sof_comp = NULL;
|
||||
int i;
|
||||
|
||||
/* 1. find sof component */
|
||||
for_each_card_rtds(card, runtime) {
|
||||
for (i = 0; i < runtime->num_components; i++) {
|
||||
if (!runtime->components[i]->driver->name)
|
||||
continue;
|
||||
if (!strcmp(runtime->components[i]->driver->name, "sof-audio-component")) {
|
||||
sof_comp = runtime->components[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!sof_comp) {
|
||||
dev_info(card->dev, " probe without component\n");
|
||||
return 0;
|
||||
}
|
||||
/* 2. add route path and fixup callback */
|
||||
for (i = 0; i < ARRAY_SIZE(g_sof_conn_streams); i++) {
|
||||
const struct sof_conn_stream *conn = &g_sof_conn_streams[i];
|
||||
struct snd_soc_pcm_runtime *sof_rtd = NULL;
|
||||
struct snd_soc_pcm_runtime *normal_rtd = NULL;
|
||||
struct snd_soc_pcm_runtime *rtd = NULL;
|
||||
|
||||
for_each_card_rtds(card, rtd) {
|
||||
if (!strcmp(rtd->dai_link->name, conn->sof_link)) {
|
||||
sof_rtd = rtd;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(rtd->dai_link->name, conn->normal_link)) {
|
||||
normal_rtd = rtd;
|
||||
continue;
|
||||
}
|
||||
if (normal_rtd && sof_rtd)
|
||||
break;
|
||||
}
|
||||
if (normal_rtd && sof_rtd) {
|
||||
int j;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
|
||||
for_each_rtd_cpu_dais(sof_rtd, j, cpu_dai) {
|
||||
struct snd_soc_dapm_route route;
|
||||
struct snd_soc_dapm_path *p = NULL;
|
||||
struct snd_soc_dapm_widget *play_widget =
|
||||
cpu_dai->playback_widget;
|
||||
struct snd_soc_dapm_widget *cap_widget =
|
||||
cpu_dai->capture_widget;
|
||||
memset(&route, 0, sizeof(route));
|
||||
if (conn->stream_dir == SNDRV_PCM_STREAM_CAPTURE &&
|
||||
cap_widget) {
|
||||
snd_soc_dapm_widget_for_each_sink_path(cap_widget, p) {
|
||||
route.source = conn->sof_dma;
|
||||
route.sink = p->sink->name;
|
||||
snd_soc_dapm_add_routes(&card->dapm, &route, 1);
|
||||
}
|
||||
} else if (conn->stream_dir == SNDRV_PCM_STREAM_PLAYBACK &&
|
||||
play_widget){
|
||||
snd_soc_dapm_widget_for_each_source_path(play_widget, p) {
|
||||
route.source = p->source->name;
|
||||
route.sink = conn->sof_dma;
|
||||
snd_soc_dapm_add_routes(&card->dapm, &route, 1);
|
||||
}
|
||||
} else {
|
||||
dev_err(cpu_dai->dev, "stream dir and widget not pair\n");
|
||||
}
|
||||
}
|
||||
normal_rtd->dai_link->be_hw_params_fixup = mt8195_dai_link_fixup;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt8195_dailink_parse_of(struct snd_soc_card *card, struct device_node *np,
|
||||
const char *propname)
|
||||
{
|
||||
struct device *dev = card->dev;
|
||||
struct snd_soc_dai_link *link;
|
||||
const char *dai_name = NULL;
|
||||
int i, j, ret, num_links;
|
||||
|
||||
num_links = of_property_count_strings(np, "mediatek,dai-link");
|
||||
|
||||
if (num_links < 0 || num_links > ARRAY_SIZE(mt8195_mt6359_dai_links)) {
|
||||
dev_dbg(dev, "number of dai-link is invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
card->dai_link = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL);
|
||||
if (!card->dai_link)
|
||||
return -ENOMEM;
|
||||
|
||||
card->num_links = 0;
|
||||
link = card->dai_link;
|
||||
|
||||
for (i = 0; i < num_links; i++) {
|
||||
ret = of_property_read_string_index(np, propname, i, &dai_name);
|
||||
if (ret) {
|
||||
dev_dbg(dev, "ASoC: Property '%s' index %d could not be read: %d\n",
|
||||
propname, i, ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(mt8195_mt6359_dai_links); j++) {
|
||||
if (!strcmp(dai_name, mt8195_mt6359_dai_links[j].name)) {
|
||||
memcpy(link, &mt8195_mt6359_dai_links[j],
|
||||
sizeof(struct snd_soc_dai_link));
|
||||
link++;
|
||||
card->num_links++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (card->num_links != num_links)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = &mt8195_mt6359_soc_card;
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
struct mt8195_mt6359_priv *priv;
|
||||
struct mtk_soc_card_data *soc_card_data;
|
||||
struct mt8195_mt6359_priv *mach_priv;
|
||||
struct device_node *platform_node, *adsp_node, *dp_node, *hdmi_node;
|
||||
struct mt8195_card_data *card_data;
|
||||
int is5682s = 0;
|
||||
@ -1512,17 +1360,41 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
|
||||
|
||||
if (strstr(card->name, "_5682s"))
|
||||
is5682s = 1;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*card_data), GFP_KERNEL);
|
||||
if (!soc_card_data)
|
||||
return -ENOMEM;
|
||||
|
||||
mach_priv = devm_kzalloc(&pdev->dev, sizeof(*mach_priv), GFP_KERNEL);
|
||||
if (!mach_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
soc_card_data->mach_priv = mach_priv;
|
||||
|
||||
adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0);
|
||||
if (adsp_node) {
|
||||
struct mtk_sof_priv *sof_priv;
|
||||
|
||||
sof_priv = devm_kzalloc(&pdev->dev, sizeof(*sof_priv), GFP_KERNEL);
|
||||
if (!sof_priv) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc;
|
||||
}
|
||||
sof_priv->conn_streams = g_sof_conn_streams;
|
||||
sof_priv->num_streams = ARRAY_SIZE(g_sof_conn_streams);
|
||||
sof_priv->sof_dai_link_fixup = mt8195_dai_link_fixup;
|
||||
soc_card_data->sof_priv = sof_priv;
|
||||
card->late_probe = mtk_sof_card_late_probe;
|
||||
sof_on = 1;
|
||||
}
|
||||
|
||||
if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) {
|
||||
ret = mt8195_dailink_parse_of(card, pdev->dev.of_node,
|
||||
"mediatek,dai-link");
|
||||
ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node,
|
||||
"mediatek,dai-link",
|
||||
mt8195_mt6359_dai_links,
|
||||
ARRAY_SIZE(mt8195_mt6359_dai_links));
|
||||
if (ret) {
|
||||
dev_dbg(&pdev->dev, "Parse dai-link fail\n");
|
||||
return -EINVAL;
|
||||
goto err_parse_of;
|
||||
}
|
||||
} else {
|
||||
if (!sof_on)
|
||||
@ -1533,13 +1405,10 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
|
||||
"mediatek,platform", 0);
|
||||
if (!platform_node) {
|
||||
dev_dbg(&pdev->dev, "Property 'platform' missing or invalid\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_platform_node;
|
||||
}
|
||||
|
||||
adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0);
|
||||
if (adsp_node)
|
||||
sof_on = 1;
|
||||
|
||||
dp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,dptx-codec", 0);
|
||||
hdmi_node = of_parse_phandle(pdev->dev.of_node,
|
||||
"mediatek,hdmi-codec", 0);
|
||||
@ -1612,17 +1481,17 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
if (sof_on)
|
||||
card->late_probe = mt8195_mt6359_card_late_probe;
|
||||
|
||||
snd_soc_card_set_drvdata(card, priv);
|
||||
snd_soc_card_set_drvdata(card, soc_card_data);
|
||||
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
|
||||
of_node_put(platform_node);
|
||||
of_node_put(adsp_node);
|
||||
of_node_put(dp_node);
|
||||
of_node_put(hdmi_node);
|
||||
err_kzalloc:
|
||||
err_parse_of:
|
||||
err_platform_node:
|
||||
of_node_put(adsp_node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ static struct q6copp *q6adm_alloc_copp(struct q6adm *adm, int port_idx)
|
||||
idx = find_first_zero_bit(&adm->copp_bitmap[port_idx],
|
||||
MAX_COPPS_PER_PORT);
|
||||
|
||||
if (idx > MAX_COPPS_PER_PORT)
|
||||
if (idx >= MAX_COPPS_PER_PORT)
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
c = kzalloc(sizeof(*c), GFP_ATOMIC);
|
||||
|
@ -513,7 +513,7 @@ int q6asm_map_memory_regions(unsigned int dir, struct audio_client *ac,
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = kzalloc(((sizeof(struct audio_buffer)) * periods), GFP_ATOMIC);
|
||||
buf = kcalloc(periods, sizeof(*buf), GFP_ATOMIC);
|
||||
if (!buf) {
|
||||
spin_unlock_irqrestore(&ac->lock, flags);
|
||||
return -ENOMEM;
|
||||
|
@ -274,22 +274,22 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
|
||||
const char *ssp_str)
|
||||
{
|
||||
const char *tplg_filename = NULL;
|
||||
char *filename;
|
||||
char *split_ext;
|
||||
const char *split_ext;
|
||||
char *filename, *tmp;
|
||||
|
||||
filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL);
|
||||
filename = kstrdup(sof_tplg_filename, GFP_KERNEL);
|
||||
if (!filename)
|
||||
return NULL;
|
||||
|
||||
/* this assumes a .tplg extension */
|
||||
split_ext = strsep(&filename, ".");
|
||||
if (split_ext) {
|
||||
tmp = filename;
|
||||
split_ext = strsep(&tmp, ".");
|
||||
if (split_ext)
|
||||
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
|
||||
"%s-%s.tplg",
|
||||
split_ext, ssp_str);
|
||||
if (!tplg_filename)
|
||||
return NULL;
|
||||
}
|
||||
kfree(filename);
|
||||
|
||||
return tplg_filename;
|
||||
}
|
||||
|
||||
|
@ -25,9 +25,9 @@ hda_compr_get_stream(struct snd_compr_stream *cstream)
|
||||
return cstream->runtime->private_data;
|
||||
}
|
||||
|
||||
static int hda_probes_compr_assign(struct sof_client_dev *cdev,
|
||||
struct snd_compr_stream *cstream,
|
||||
struct snd_soc_dai *dai, u32 *stream_id)
|
||||
static int hda_probes_compr_startup(struct sof_client_dev *cdev,
|
||||
struct snd_compr_stream *cstream,
|
||||
struct snd_soc_dai *dai, u32 *stream_id)
|
||||
{
|
||||
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
|
||||
struct hdac_ext_stream *hext_stream;
|
||||
@ -45,9 +45,9 @@ static int hda_probes_compr_assign(struct sof_client_dev *cdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hda_probes_compr_free(struct sof_client_dev *cdev,
|
||||
struct snd_compr_stream *cstream,
|
||||
struct snd_soc_dai *dai)
|
||||
static int hda_probes_compr_shutdown(struct sof_client_dev *cdev,
|
||||
struct snd_compr_stream *cstream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
|
||||
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
|
||||
@ -127,8 +127,8 @@ static int hda_probes_compr_pointer(struct sof_client_dev *cdev,
|
||||
|
||||
/* SOF client implementation */
|
||||
static const struct sof_probes_host_ops hda_probes_ops = {
|
||||
.assign = hda_probes_compr_assign,
|
||||
.free = hda_probes_compr_free,
|
||||
.startup = hda_probes_compr_startup,
|
||||
.shutdown = hda_probes_compr_shutdown,
|
||||
.set_params = hda_probes_compr_set_params,
|
||||
.trigger = hda_probes_compr_trigger,
|
||||
.pointer = hda_probes_compr_pointer,
|
||||
|
@ -411,6 +411,11 @@ int hda_dsp_iccmax_stream_hw_params(struct snd_sof_dev *sdev, struct hdac_ext_st
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!dmab) {
|
||||
dev_err(sdev->dev, "error: no dma buffer allocated!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (hstream->posbuf)
|
||||
*hstream->posbuf = 0;
|
||||
|
||||
@ -485,16 +490,16 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* decouple host and link DMA */
|
||||
mask = 0x1 << hstream->index;
|
||||
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
|
||||
mask, mask);
|
||||
|
||||
if (!dmab) {
|
||||
dev_err(sdev->dev, "error: no dma buffer allocated!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* decouple host and link DMA */
|
||||
mask = 0x1 << hstream->index;
|
||||
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
|
||||
mask, mask);
|
||||
|
||||
/* clear stream status */
|
||||
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset,
|
||||
SOF_HDA_CL_DMA_SD_INT_MASK |
|
||||
|
@ -776,13 +776,12 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
|
||||
return tplg_filename;
|
||||
}
|
||||
|
||||
static int dmic_topology_fixup(struct snd_sof_dev *sdev,
|
||||
const char **tplg_filename,
|
||||
const char *idisp_str,
|
||||
int *dmic_found)
|
||||
static int dmic_detect_topology_fixup(struct snd_sof_dev *sdev,
|
||||
const char **tplg_filename,
|
||||
const char *idisp_str,
|
||||
int *dmic_found,
|
||||
bool tplg_fixup)
|
||||
{
|
||||
const char *default_tplg_filename = *tplg_filename;
|
||||
const char *fixed_tplg_filename;
|
||||
const char *dmic_str;
|
||||
int dmic_num;
|
||||
|
||||
@ -808,14 +807,19 @@ static int dmic_topology_fixup(struct snd_sof_dev *sdev,
|
||||
break;
|
||||
}
|
||||
|
||||
fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename,
|
||||
idisp_str, dmic_str);
|
||||
if (!fixed_tplg_filename)
|
||||
return -ENOMEM;
|
||||
if (tplg_fixup) {
|
||||
const char *default_tplg_filename = *tplg_filename;
|
||||
const char *fixed_tplg_filename;
|
||||
|
||||
fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename,
|
||||
idisp_str, dmic_str);
|
||||
if (!fixed_tplg_filename)
|
||||
return -ENOMEM;
|
||||
*tplg_filename = fixed_tplg_filename;
|
||||
}
|
||||
|
||||
dev_info(sdev->dev, "DMICs detected in NHLT tables: %d\n", dmic_num);
|
||||
*dmic_found = dmic_num;
|
||||
*tplg_filename = fixed_tplg_filename;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1221,6 +1225,8 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
|
||||
* - one external HDAudio codec
|
||||
*/
|
||||
if (!*mach && codec_num <= 2) {
|
||||
bool tplg_fixup;
|
||||
|
||||
hda_mach = snd_soc_acpi_intel_hda_machines;
|
||||
|
||||
dev_info(bus->dev, "using HDA machine driver %s now\n",
|
||||
@ -1232,8 +1238,15 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
|
||||
idisp_str = "";
|
||||
|
||||
/* topology: use the info from hda_machines */
|
||||
tplg_filename = hda_mach->sof_tplg_filename;
|
||||
ret = dmic_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num);
|
||||
if (pdata->tplg_filename) {
|
||||
tplg_fixup = false;
|
||||
tplg_filename = pdata->tplg_filename;
|
||||
} else {
|
||||
tplg_fixup = true;
|
||||
tplg_filename = hda_mach->sof_tplg_filename;
|
||||
}
|
||||
ret = dmic_detect_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num,
|
||||
tplg_fixup);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
@ -1397,30 +1410,37 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
|
||||
}
|
||||
if (mach && mach->link_mask) {
|
||||
int dmic_num = 0;
|
||||
bool tplg_fixup;
|
||||
const char *tplg_filename;
|
||||
|
||||
mach->mach_params.links = mach->links;
|
||||
mach->mach_params.link_mask = mach->link_mask;
|
||||
mach->mach_params.platform = dev_name(sdev->dev);
|
||||
pdata->fw_filename = pdata->desc->default_fw_filename[pdata->ipc_type];
|
||||
pdata->tplg_filename = mach->sof_tplg_filename;
|
||||
|
||||
if (pdata->tplg_filename) {
|
||||
tplg_fixup = false;
|
||||
} else {
|
||||
tplg_fixup = true;
|
||||
tplg_filename = mach->sof_tplg_filename;
|
||||
}
|
||||
|
||||
/*
|
||||
* DMICs use up to 4 pins and are typically pin-muxed with SoundWire
|
||||
* link 2 and 3, thus we only try to enable dmics if all conditions
|
||||
* are true:
|
||||
* a) link 2 and 3 are not used by SoundWire
|
||||
* link 2 and 3, or link 1 and 2, thus we only try to enable dmics
|
||||
* if all conditions are true:
|
||||
* a) 2 or fewer links are used by SoundWire
|
||||
* b) the NHLT table reports the presence of microphones
|
||||
*/
|
||||
if (!(mach->link_mask & GENMASK(3, 2))) {
|
||||
const char *tplg_filename = mach->sof_tplg_filename;
|
||||
if (hweight_long(mach->link_mask) <= 2) {
|
||||
int ret;
|
||||
|
||||
ret = dmic_topology_fixup(sdev, &tplg_filename, "", &dmic_num);
|
||||
ret = dmic_detect_topology_fixup(sdev, &tplg_filename, "",
|
||||
&dmic_num, tplg_fixup);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
pdata->tplg_filename = tplg_filename;
|
||||
}
|
||||
if (tplg_fixup)
|
||||
pdata->tplg_filename = tplg_filename;
|
||||
mach->mach_params.dmic_num = dmic_num;
|
||||
|
||||
dev_dbg(sdev->dev,
|
||||
@ -1466,18 +1486,22 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
|
||||
mach = snd_soc_acpi_find_machine(desc->machines);
|
||||
if (mach) {
|
||||
bool add_extension = false;
|
||||
bool tplg_fixup = false;
|
||||
|
||||
/*
|
||||
* If tplg file name is overridden, use it instead of
|
||||
* the one set in mach table
|
||||
*/
|
||||
if (!sof_pdata->tplg_filename)
|
||||
if (!sof_pdata->tplg_filename) {
|
||||
sof_pdata->tplg_filename = mach->sof_tplg_filename;
|
||||
tplg_fixup = true;
|
||||
}
|
||||
|
||||
/* report to machine driver if any DMICs are found */
|
||||
mach->mach_params.dmic_num = check_dmic_num(sdev);
|
||||
|
||||
if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER &&
|
||||
if (tplg_fixup &&
|
||||
mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER &&
|
||||
mach->mach_params.dmic_num) {
|
||||
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
|
||||
"%s%s%d%s",
|
||||
@ -1500,8 +1524,10 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
|
||||
/* report SSP link mask to machine driver */
|
||||
mach->mach_params.i2s_link_mask = check_nhlt_ssp_mask(sdev);
|
||||
|
||||
if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER &&
|
||||
if (tplg_fixup &&
|
||||
mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER &&
|
||||
mach->mach_params.i2s_link_mask) {
|
||||
const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata);
|
||||
int ssp_num;
|
||||
|
||||
if (hweight_long(mach->mach_params.i2s_link_mask) > 1 &&
|
||||
@ -1511,6 +1537,12 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
|
||||
/* fls returns 1-based results, SSPs indices are 0-based */
|
||||
ssp_num = fls(mach->mach_params.i2s_link_mask) - 1;
|
||||
|
||||
if (ssp_num >= chip->ssp_count) {
|
||||
dev_err(sdev->dev, "Invalid SSP %d, max on this platform is %d\n",
|
||||
ssp_num, chip->ssp_count);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
|
||||
"%s%s%d",
|
||||
sof_pdata->tplg_filename,
|
||||
@ -1523,7 +1555,7 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
|
||||
add_extension = true;
|
||||
}
|
||||
|
||||
if (add_extension) {
|
||||
if (tplg_fixup && add_extension) {
|
||||
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
|
||||
"%s%s",
|
||||
sof_pdata->tplg_filename,
|
||||
|
@ -372,20 +372,9 @@ static int mtl_dsp_core_power_up(struct snd_sof_dev *sdev, int core)
|
||||
ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
|
||||
(dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
|
||||
HDA_DSP_RESET_TIMEOUT_US);
|
||||
if (ret < 0) {
|
||||
if (ret < 0)
|
||||
dev_err(sdev->dev, "%s: timeout on MTL_DSP2CXCTL_PRIMARY_CORE read\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* did core power up ? */
|
||||
dspcxctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE);
|
||||
if ((dspcxctl & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK)
|
||||
!= MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK) {
|
||||
dev_err(sdev->dev, "power up core failed core %d adspcs %#x\n",
|
||||
core, dspcxctl);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ static int ipc3_fw_ext_man_get_config_data(struct snd_sof_dev *sdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t ipc3_fw_ext_man_size(const struct firmware *fw)
|
||||
static ssize_t ipc3_fw_ext_man_size(struct snd_sof_dev *sdev, const struct firmware *fw)
|
||||
{
|
||||
const struct sof_ext_man_header *head;
|
||||
|
||||
@ -131,6 +131,8 @@ static ssize_t ipc3_fw_ext_man_size(const struct firmware *fw)
|
||||
return head->full_size;
|
||||
|
||||
/* otherwise given fw don't have an extended manifest */
|
||||
dev_dbg(sdev->dev, "Unexpected extended manifest magic number: %#x\n",
|
||||
head->magic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -147,7 +149,7 @@ static size_t sof_ipc3_fw_parse_ext_man(struct snd_sof_dev *sdev)
|
||||
|
||||
head = (struct sof_ext_man_header *)fw->data;
|
||||
remaining = head->full_size - head->header_size;
|
||||
ext_man_size = ipc3_fw_ext_man_size(fw);
|
||||
ext_man_size = ipc3_fw_ext_man_size(sdev, fw);
|
||||
|
||||
/* Assert firmware starts with extended manifest */
|
||||
if (ext_man_size <= 0)
|
||||
|
@ -115,6 +115,9 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
|
||||
pcm.params.no_stream_position = 1;
|
||||
}
|
||||
|
||||
if (platform_params->cont_update_posn)
|
||||
pcm.params.cont_update_posn = 1;
|
||||
|
||||
dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag);
|
||||
|
||||
/* send hw_params IPC to the DSP */
|
||||
|
@ -179,6 +179,7 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
|
||||
struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name);
|
||||
struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
||||
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
|
||||
struct sof_ipc4_copier *ipc4_copier;
|
||||
@ -201,6 +202,9 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
snd_mask_none(fmt);
|
||||
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);
|
||||
|
||||
rate->min = ipc4_copier->available_fmt.base_config->audio_fmt.sampling_frequency;
|
||||
rate->max = rate->min;
|
||||
|
||||
/*
|
||||
* Set trigger order for capture to SND_SOC_DPCM_TRIGGER_PRE. This is required
|
||||
* to ensure that the BE DAI pipeline gets stopped/suspended before the FE DAI
|
||||
|
@ -111,6 +111,12 @@ static const struct sof_topology_token gain_tokens[] = {
|
||||
get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)},
|
||||
};
|
||||
|
||||
/* SRC */
|
||||
static const struct sof_topology_token src_tokens[] = {
|
||||
{SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
|
||||
offsetof(struct sof_ipc4_src, sink_rate)},
|
||||
};
|
||||
|
||||
static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
|
||||
[SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)},
|
||||
[SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)},
|
||||
@ -134,6 +140,7 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
|
||||
[SOF_AUDIO_FMT_NUM_TOKENS] = {"IPC4 Audio format number tokens",
|
||||
ipc4_audio_fmt_num_tokens, ARRAY_SIZE(ipc4_audio_fmt_num_tokens)},
|
||||
[SOF_GAIN_TOKENS] = {"Gain tokens", gain_tokens, ARRAY_SIZE(gain_tokens)},
|
||||
[SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)},
|
||||
};
|
||||
|
||||
static void sof_ipc4_dbg_audio_format(struct device *dev,
|
||||
@ -307,6 +314,7 @@ static int sof_ipc4_widget_set_module_info(struct snd_sof_widget *swidget)
|
||||
static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_ipc4_msg *msg)
|
||||
{
|
||||
struct sof_ipc4_fw_module *fw_module;
|
||||
uint32_t type;
|
||||
int ret;
|
||||
|
||||
ret = sof_ipc4_widget_set_module_info(swidget);
|
||||
@ -323,6 +331,9 @@ static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_
|
||||
msg->extension = SOF_IPC4_MOD_EXT_PPL_ID(swidget->pipeline_id);
|
||||
msg->extension |= SOF_IPC4_MOD_EXT_CORE_ID(swidget->core);
|
||||
|
||||
type = fw_module->man4_module_entry.type & SOF_IPC4_MODULE_DP ? 1 : 0;
|
||||
msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -740,6 +751,58 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
|
||||
{
|
||||
struct snd_soc_component *scomp = swidget->scomp;
|
||||
struct sof_ipc4_src *src;
|
||||
int ret;
|
||||
|
||||
dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name);
|
||||
|
||||
src = kzalloc(sizeof(*src), GFP_KERNEL);
|
||||
if (!src)
|
||||
return -ENOMEM;
|
||||
|
||||
swidget->private = src;
|
||||
|
||||
/* The out_audio_fmt in topology is ignored as it is not required by SRC */
|
||||
ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, false);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples,
|
||||
swidget->num_tuples, sizeof(src), 1);
|
||||
if (ret) {
|
||||
dev_err(scomp->dev, "Parsing SRC tokens failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev_dbg(scomp->dev, "SRC sink rate %d\n", src->sink_rate);
|
||||
|
||||
ret = sof_ipc4_widget_setup_msg(swidget, &src->msg);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
sof_ipc4_free_audio_fmt(&src->available_fmt);
|
||||
kfree(src);
|
||||
swidget->private = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sof_ipc4_widget_free_comp_src(struct snd_sof_widget *swidget)
|
||||
{
|
||||
struct sof_ipc4_src *src = swidget->private;
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
sof_ipc4_free_audio_fmt(&src->available_fmt);
|
||||
kfree(swidget->private);
|
||||
swidget->private = NULL;
|
||||
}
|
||||
|
||||
static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget)
|
||||
{
|
||||
struct sof_ipc4_mixer *mixer = swidget->private;
|
||||
@ -891,7 +954,6 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev,
|
||||
|
||||
static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
|
||||
{
|
||||
struct sof_ipc4_fw_module *fw_module = swidget->module_info;
|
||||
struct sof_ipc4_copier *ipc4_copier = NULL;
|
||||
struct snd_sof_widget *pipe_widget;
|
||||
struct sof_ipc4_pipeline *pipeline;
|
||||
@ -925,8 +987,6 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
|
||||
ipc4_copier->ipc_config_data = NULL;
|
||||
ipc4_copier->ipc_config_size = 0;
|
||||
}
|
||||
|
||||
ida_free(&fw_module->m_ida, swidget->instance_id);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT)
|
||||
@ -1254,15 +1314,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
|
||||
/* update pipeline memory usage */
|
||||
sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &copier_data->base_config);
|
||||
|
||||
/* assign instance ID */
|
||||
return sof_ipc4_widget_assign_instance_id(sdev, swidget);
|
||||
}
|
||||
|
||||
static void sof_ipc4_unprepare_generic_module(struct snd_sof_widget *swidget)
|
||||
{
|
||||
struct sof_ipc4_fw_module *fw_module = swidget->module_info;
|
||||
|
||||
ida_free(&fw_module->m_ida, swidget->instance_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
|
||||
@ -1287,8 +1339,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
|
||||
/* update pipeline memory usage */
|
||||
sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &gain->base_config);
|
||||
|
||||
/* assign instance ID */
|
||||
return sof_ipc4_widget_assign_instance_id(sdev, swidget);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
|
||||
@ -1314,8 +1365,38 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
|
||||
/* update pipeline memory usage */
|
||||
sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &mixer->base_config);
|
||||
|
||||
/* assign instance ID */
|
||||
return sof_ipc4_widget_assign_instance_id(sdev, swidget);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
|
||||
struct snd_pcm_hw_params *fe_params,
|
||||
struct snd_sof_platform_stream_params *platform_params,
|
||||
struct snd_pcm_hw_params *pipeline_params, int dir)
|
||||
{
|
||||
struct snd_soc_component *scomp = swidget->scomp;
|
||||
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||
struct sof_ipc4_src *src = swidget->private;
|
||||
struct snd_interval *rate;
|
||||
int ret;
|
||||
|
||||
src->available_fmt.ref_audio_fmt = &src->available_fmt.base_config->audio_fmt;
|
||||
|
||||
/* output format is not required to be sent to the FW for SRC */
|
||||
ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config,
|
||||
NULL, pipeline_params, &src->available_fmt,
|
||||
sizeof(src->base_config));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* update pipeline memory usage */
|
||||
sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &src->base_config);
|
||||
|
||||
/* update pipeline_params for sink widgets */
|
||||
rate = hw_param_interval(pipeline_params, SNDRV_PCM_HW_PARAM_RATE);
|
||||
rate->min = src->sink_rate;
|
||||
rate->max = rate->min;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
|
||||
@ -1373,9 +1454,6 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
|
||||
u32 ipc_size = 0;
|
||||
int ret;
|
||||
|
||||
dev_dbg(sdev->dev, "Create widget %s instance %d - pipe %d - core %d\n",
|
||||
swidget->widget->name, swidget->instance_id, swidget->pipeline_id, swidget->core);
|
||||
|
||||
switch (swidget->id) {
|
||||
case snd_soc_dapm_scheduler:
|
||||
pipeline = swidget->private;
|
||||
@ -1430,21 +1508,37 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
|
||||
msg = &mixer->msg;
|
||||
break;
|
||||
}
|
||||
case snd_soc_dapm_src:
|
||||
{
|
||||
struct sof_ipc4_src *src = swidget->private;
|
||||
|
||||
ipc_size = sizeof(struct sof_ipc4_base_module_cfg) + sizeof(src->sink_rate);
|
||||
ipc_data = src;
|
||||
|
||||
msg = &src->msg;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dev_err(sdev->dev, "widget type %d not supported", swidget->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (swidget->id != snd_soc_dapm_scheduler) {
|
||||
ret = sof_ipc4_widget_assign_instance_id(sdev, swidget);
|
||||
if (ret < 0) {
|
||||
dev_err(sdev->dev, "failed to assign instance id for %s\n",
|
||||
swidget->widget->name);
|
||||
return ret;
|
||||
}
|
||||
pipeline = pipe_widget->private;
|
||||
msg->primary &= ~SOF_IPC4_MOD_INSTANCE_MASK;
|
||||
msg->primary |= SOF_IPC4_MOD_INSTANCE(swidget->instance_id);
|
||||
|
||||
msg->extension &= ~SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK;
|
||||
msg->extension |= ipc_size >> 2;
|
||||
msg->extension &= ~SOF_IPC4_MOD_EXT_DOMAIN_MASK;
|
||||
msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(pipeline->lp_mode);
|
||||
}
|
||||
dev_dbg(sdev->dev, "Create widget %s instance %d - pipe %d - core %d\n",
|
||||
swidget->widget->name, swidget->instance_id, swidget->pipeline_id, swidget->core);
|
||||
|
||||
msg->data_size = ipc_size;
|
||||
msg->data_ptr = ipc_data;
|
||||
@ -1458,6 +1552,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
|
||||
|
||||
static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
|
||||
{
|
||||
struct sof_ipc4_fw_module *fw_module = swidget->module_info;
|
||||
int ret = 0;
|
||||
|
||||
/* freeing a pipeline frees all the widgets associated with it */
|
||||
@ -1480,6 +1575,8 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget
|
||||
|
||||
pipeline->mem_usage = 0;
|
||||
pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED;
|
||||
} else {
|
||||
ida_free(&fw_module->m_ida, swidget->instance_id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1766,6 +1863,15 @@ static enum sof_tokens mixer_token_list[] = {
|
||||
SOF_COMP_EXT_TOKENS,
|
||||
};
|
||||
|
||||
static enum sof_tokens src_token_list[] = {
|
||||
SOF_COMP_TOKENS,
|
||||
SOF_SRC_TOKENS,
|
||||
SOF_AUDIO_FMT_NUM_TOKENS,
|
||||
SOF_IN_AUDIO_FORMAT_TOKENS,
|
||||
SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS,
|
||||
SOF_COMP_EXT_TOKENS,
|
||||
};
|
||||
|
||||
static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = {
|
||||
[snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
|
||||
host_token_list, ARRAY_SIZE(host_token_list), NULL,
|
||||
@ -1789,11 +1895,15 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY
|
||||
[snd_soc_dapm_pga] = {sof_ipc4_widget_setup_comp_pga, sof_ipc4_widget_free_comp_pga,
|
||||
pga_token_list, ARRAY_SIZE(pga_token_list), NULL,
|
||||
sof_ipc4_prepare_gain_module,
|
||||
sof_ipc4_unprepare_generic_module},
|
||||
NULL},
|
||||
[snd_soc_dapm_mixer] = {sof_ipc4_widget_setup_comp_mixer, sof_ipc4_widget_free_comp_mixer,
|
||||
mixer_token_list, ARRAY_SIZE(mixer_token_list),
|
||||
NULL, sof_ipc4_prepare_mixer_module,
|
||||
sof_ipc4_unprepare_generic_module},
|
||||
NULL},
|
||||
[snd_soc_dapm_src] = {sof_ipc4_widget_setup_comp_src, sof_ipc4_widget_free_comp_src,
|
||||
src_token_list, ARRAY_SIZE(src_token_list),
|
||||
NULL, sof_ipc4_prepare_src_module,
|
||||
NULL},
|
||||
};
|
||||
|
||||
const struct sof_ipc_tplg_ops ipc4_tplg_ops = {
|
||||
|
@ -15,7 +15,18 @@
|
||||
#define SOF_IPC4_FW_PAGE(x) ((((x) + BIT(12) - 1) & ~(BIT(12) - 1)) >> 12)
|
||||
#define SOF_IPC4_FW_ROUNDUP(x) (((x) + BIT(6) - 1) & (~(BIT(6) - 1)))
|
||||
|
||||
#define SOF_IPC4_MODULE_LL BIT(5)
|
||||
#define SOF_IPC4_MODULE_LOAD_TYPE GENMASK(3, 0)
|
||||
#define SOF_IPC4_MODULE_AUTO_START BIT(4)
|
||||
/*
|
||||
* Two module schedule domains in fw :
|
||||
* LL domain - Low latency domain
|
||||
* DP domain - Data processing domain
|
||||
* The LL setting should be equal to !DP setting
|
||||
*/
|
||||
#define SOF_IPC4_MODULE_LL BIT(5)
|
||||
#define SOF_IPC4_MODULE_DP BIT(6)
|
||||
#define SOF_IPC4_MODULE_LIB_CODE BIT(7)
|
||||
|
||||
#define SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE 12
|
||||
#define SOF_IPC4_PIPELINE_OBJECT_SIZE 448
|
||||
#define SOF_IPC4_DATA_QUEUE_OBJECT_SIZE 128
|
||||
@ -242,4 +253,18 @@ struct sof_ipc4_mixer {
|
||||
struct sof_ipc4_msg msg;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sof_ipc4_src SRC config data
|
||||
* @base_config: IPC base config data
|
||||
* @sink_rate: Output rate for sink module
|
||||
* @available_fmt: Available audio format
|
||||
* @msg: IPC4 message struct containing header and data info
|
||||
*/
|
||||
struct sof_ipc4_src {
|
||||
struct sof_ipc4_base_module_cfg base_config;
|
||||
uint32_t sink_rate;
|
||||
struct sof_ipc4_available_audio_format available_fmt;
|
||||
struct sof_ipc4_msg msg;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@ void sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr)
|
||||
|
||||
/* pull high StatVectorSel to use AltResetVec (set bit4 to 1) */
|
||||
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
|
||||
DSP_RESET_SW, DSP_RESET_SW);
|
||||
STATVECTOR_SEL, STATVECTOR_SEL);
|
||||
|
||||
/* toggle DReset & BReset */
|
||||
/* pull high DReset & BReset */
|
||||
@ -29,6 +29,9 @@ void sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr)
|
||||
ADSP_BRESET_SW | ADSP_DRESET_SW,
|
||||
ADSP_BRESET_SW | ADSP_DRESET_SW);
|
||||
|
||||
/* delay 10 DSP cycles at 26M about 1us by IP vendor's suggestion */
|
||||
udelay(1);
|
||||
|
||||
/* pull low DReset & BReset */
|
||||
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
|
||||
ADSP_BRESET_SW | ADSP_DRESET_SW,
|
||||
@ -46,11 +49,13 @@ void sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr)
|
||||
|
||||
void sof_hifixdsp_shutdown(struct snd_sof_dev *sdev)
|
||||
{
|
||||
/* Clear to 0 firstly */
|
||||
snd_sof_dsp_write(sdev, DSP_REG_BAR, DSP_RESET_SW, 0x0);
|
||||
|
||||
/* RUN_STALL pull high again to reset */
|
||||
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
|
||||
ADSP_RUNSTALL, ADSP_RUNSTALL);
|
||||
|
||||
/* pull high DReset & BReset */
|
||||
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
|
||||
ADSP_BRESET_SW | ADSP_DRESET_SW,
|
||||
ADSP_BRESET_SW | ADSP_DRESET_SW);
|
||||
}
|
||||
|
||||
|
@ -270,9 +270,9 @@ static int sof_probes_compr_startup(struct snd_compr_stream *cstream,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ops->assign(cdev, cstream, dai, &priv->extractor_stream_tag);
|
||||
ret = ops->startup(cdev, cstream, dai, &priv->extractor_stream_tag);
|
||||
if (ret) {
|
||||
dev_err(dai->dev, "Failed to assign probe stream: %d\n", ret);
|
||||
dev_err(dai->dev, "Failed to startup probe stream: %d\n", ret);
|
||||
priv->extractor_stream_tag = SOF_PROBES_INVALID_NODE_ID;
|
||||
sof_client_core_module_put(cdev);
|
||||
}
|
||||
@ -310,7 +310,7 @@ exit:
|
||||
priv->extractor_stream_tag = SOF_PROBES_INVALID_NODE_ID;
|
||||
snd_compr_free_pages(cstream);
|
||||
|
||||
ret = ops->free(cdev, cstream, dai);
|
||||
ret = ops->shutdown(cdev, cstream, dai);
|
||||
|
||||
sof_client_core_module_put(cdev);
|
||||
|
||||
@ -709,7 +709,7 @@ static int sof_probes_client_probe(struct auxiliary_device *auxdev,
|
||||
|
||||
ops = dev->platform_data;
|
||||
|
||||
if (!ops->assign || !ops->free || !ops->set_params || !ops->trigger ||
|
||||
if (!ops->startup || !ops->shutdown || !ops->set_params || !ops->trigger ||
|
||||
!ops->pointer) {
|
||||
dev_err(dev, "missing platform callback(s)\n");
|
||||
return -ENODEV;
|
||||
|
@ -14,10 +14,10 @@ struct snd_soc_dai;
|
||||
* DSP and host, like HDA.
|
||||
*/
|
||||
struct sof_probes_host_ops {
|
||||
int (*assign)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
|
||||
struct snd_soc_dai *dai, u32 *stream_id);
|
||||
int (*free)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
|
||||
struct snd_soc_dai *dai);
|
||||
int (*startup)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
|
||||
struct snd_soc_dai *dai, u32 *stream_id);
|
||||
int (*shutdown)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
|
||||
struct snd_soc_dai *dai);
|
||||
int (*set_params)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
|
||||
struct snd_compr_params *params,
|
||||
struct snd_soc_dai *dai);
|
||||
|
@ -126,6 +126,7 @@ struct snd_sof_platform_stream_params {
|
||||
bool use_phy_address;
|
||||
u32 phy_addr;
|
||||
bool no_ipc_position;
|
||||
bool cont_update_posn;
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user