Commit a3b5d471 authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-v5.20-2' of...

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.
parents 9769e44d 40d060b8
......@@ -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:
- |
......
# 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>;
};
# 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>;
};
# 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>;
};
* 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>;
};
* 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>;
};
* 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:
......
# 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";
};
...
# 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>;
};
};
...
# 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:
......
# 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,
};
......
# 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
// 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");
/* 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);
}
/* 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 @@ static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
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;
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);
quirk |= ssp;
/* 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;
/* fls returns 1-based results, SSPs indices are 0-based */
ssp = fls(mach->mach_params.i2s_link_mask) - 1;
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/
# 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
// 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);
/* 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
/* 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
# 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);
......
/* 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
// 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;
}
This diff is collapsed.
......@@ -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:
......
// 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);
/* 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
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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 |
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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 */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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;
};
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment