ASoC: Updates for v5.20

This is a big release thus far and there will probably be more changes
 to come, it's a combination of a larger than usual crop of new drivers
 and some subsysetm wide cleanups from Charles rather than anything
 structural.  The SOF and Intel DSP code both also continue to be very
 actively developed.
 
  - Restructing of the set_fmt() callbacks to be specified in terms of
    the device rather than with semantics depending on if the device is
    supposed to be a CODEC or SoC, making things clearer in situations
    like CODEC to CODEC links.
  - Clean up of the way we flag which DAI naming scheme we use to reflect
    the progress that's been made modernising things.
  - Merge of more of the Intel AVS driver stack, including some board
    integrations.
  - New version 4 mechanism for communication with SOF DSPs.
  - Suppoort for dynamically selecting the PLL to use at runtime on i.MX
    platforms.
  - Improvements for CODEC to CODEC support in the generic cards.
  - Support for AMD Jadeite and various machines, Intel MetorLake DSPs,
    Mediatek MT8186 DSPs and MT6366, nVidia Tegra MDDRC, OPE and PEQ, NXP
    TFA9890, Qualcomm SDM845, WCD9335 and WAS883x, and Texas Instruments
    TAS2780.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmLRa6sACgkQJNaLcl1U
 h9Bkvwf9HJRDLQ513AIAg8QJVZ4a+vAX4dirPUkpsyxRJ9WUdaOVdYiRIwDfMKQl
 Y9gH8xN3/JcLThKDuCxbyndgXEbfhu+s55VerrJ1/KAlnxZoYXcCuc+PKr78ZNCq
 goMQT3EcKiJXPEXcxZVMGMsK0XaoWNycKHm/wQ+27OF8kiFs58iRvnFk27HLgd6z
 ucVF7Zmj+vABIS2eou+pAvAT2Ln9OraCdwjH26nSSZ3J8z4SIvsaJXJ5Fsasevpa
 ExL+RIBXTG4Xs5MH60P0P6qNV3zIuiRkLTN2BZabr7R3OHE8eW4Vz6p2QQ70eZ9R
 UdusEjJONjfHwoF9jD+QIk/zv9T/BA==
 =oiKM
 -----END PGP SIGNATURE-----

Merge tag 'asoc-v5.20' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next

ASoC: Updates for v5.20

This is a big release thus far and there will probably be more changes
to come, it's a combination of a larger than usual crop of new drivers
and some subsysetm wide cleanups from Charles rather than anything
structural.  The SOF and Intel DSP code both also continue to be very
actively developed.

 - Restructing of the set_fmt() callbacks to be specified in terms of
   the device rather than with semantics depending on if the device is
   supposed to be a CODEC or SoC, making things clearer in situations
   like CODEC to CODEC links.
 - Clean up of the way we flag which DAI naming scheme we use to reflect
   the progress that's been made modernising things.
 - Merge of more of the Intel AVS driver stack, including some board
   integrations.
 - New version 4 mechanism for communication with SOF DSPs.
 - Suppoort for dynamically selecting the PLL to use at runtime on i.MX
   platforms.
 - Improvements for CODEC to CODEC support in the generic cards.
 - Support for AMD Jadeite and various machines, Intel MetorLake DSPs,
   Mediatek MT8186 DSPs and MT6366, nVidia Tegra MDDRC, OPE and PEQ, NXP
   TFA9890, Qualcomm SDM845, WCD9335 and WAS883x, and Texas Instruments
   TAS2780.
This commit is contained in:
Takashi Iwai 2022-07-15 16:11:58 +02:00
commit 29a249d72d
688 changed files with 28060 additions and 3388 deletions

View File

@ -0,0 +1,91 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/dsp/mediatek,mt8186-dsp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek mt8186 DSP core
maintainers:
- Tinghan Shen <tinghan.shen@mediatek.com>
description: |
MediaTek mt8186 SoC contains a DSP core used for
advanced pre- and post- audio processing.
properties:
compatible:
const: mediatek,mt8186-dsp
reg:
items:
- description: Address and size of the DSP config registers
- description: Address and size of the DSP SRAM
- description: Address and size of the DSP secure registers
- description: Address and size of the DSP bus registers
reg-names:
items:
- const: cfg
- const: sram
- const: sec
- const: bus
clocks:
items:
- description: mux for audio dsp clock
- description: mux for audio dsp local bus
clock-names:
items:
- const: audiodsp
- const: adsp_bus
power-domains:
maxItems: 1
mboxes:
items:
- description: mailbox for receiving audio DSP requests.
- description: mailbox for transmitting requests to audio DSP.
mbox-names:
items:
- const: rx
- const: tx
memory-region:
items:
- description: dma buffer between host and DSP.
- description: DSP system memory.
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- power-domains
- mbox-names
- mboxes
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt8186-clk.h>
dsp@10680000 {
compatible = "mediatek,mt8186-dsp";
reg = <0x10680000 0x2000>,
<0x10800000 0x100000>,
<0x1068b000 0x100>,
<0x1068f000 0x1000>;
reg-names = "cfg", "sram", "sec", "bus";
clocks = <&topckgen CLK_TOP_AUDIODSP>,
<&topckgen CLK_TOP_ADSP_BUS>;
clock-names = "audiodsp",
"adsp_bus";
power-domains = <&spm 6>;
mbox-names = "rx", "tx";
mboxes = <&adsp_mailbox0>, <&adsp_mailbox1>;
};

View File

@ -50,13 +50,13 @@ properties:
mboxes:
items:
- description: ipc reply between host and audio DSP.
- description: ipc request between host and audio DSP.
- description: mailbox for receiving audio DSP requests.
- description: mailbox for transmitting requests to audio DSP.
mbox-names:
items:
- const: mbox0
- const: mbox1
- const: rx
- const: tx
memory-region:
items:
@ -100,6 +100,6 @@ examples:
memory-region = <&adsp_dma_mem_reserved>,
<&adsp_mem_reserved>;
power-domains = <&spm 6>; //MT8195_POWER_DOMAIN_ADSP
mbox-names = "mbox0", "mbox1";
mbox-names = "rx", "tx";
mboxes = <&adsp_mailbox0>, <&adsp_mailbox1>;
};

View File

@ -24,6 +24,21 @@ properties:
maxItems: 1
description: I2C address of the device.
avdd-supply:
description: A 1.8V supply that powers up the AVDD pin.
dvdd-supply:
description: A 1.2V supply that powers up the DVDD pin.
dvddio-supply:
description: A 1.2V or 1.8V supply that powers up the VDDIO pin.
pvdd-supply:
description: A 3.0V to 20V supply that powers up the PVDD pin.
vbat-supply:
description: A 3.3V to 5.5V supply that powers up the VBAT pin.
adi,vmon-slot-no:
description: slot number of the voltage sense monitor
$ref: "/schemas/types.yaml#/definitions/uint32"
@ -36,13 +51,22 @@ properties:
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 15
default: 0
default: 1
adi,spkfb-slot-no:
description: slot number of speaker DSP monitor
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 15
default: 2
adi,bypass-slot-no:
description:
Selects the PCM data input channel that is routed to the speaker
audio processing bypass path.
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 15
default: 0
adi,interleave-mode:
@ -72,6 +96,10 @@ examples:
max98396: amplifier@39 {
compatible = "adi,max98396";
reg = <0x39>;
dvdd-supply = <&regulator_1v2>;
dvddio-supply = <&regulator_1v8>;
avdd-supply = <&regulator_1v8>;
pvdd-supply = <&regulator_pvdd>;
adi,vmon-slot-no = <0>;
adi,imon-slot-no = <1>;
reset-gpios = <&gpio 4 GPIO_ACTIVE_LOW>;

View File

@ -21,6 +21,11 @@ properties:
description:
Regulator for the headphone amplifier
allwinner,internal-bias-resistor:
description:
Enable the internal 2.2K bias resistor between HBIAS and MICDET pins
type: boolean
required:
- compatible
- reg

View File

@ -16,7 +16,7 @@ Board connectors:
* Line In Jack
wm8731 pins:
cf Documentation/devicetree/bindings/sound/wm8731.txt
cf Documentation/devicetree/bindings/sound/wlf,wm8731.yaml
Example:
sound {

View File

@ -1,35 +0,0 @@
DesignWare I2S controller
Required properties:
- compatible : Must be "snps,designware-i2s"
- reg : Must contain the I2S core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's
clocks. The controller expects one clock: the clock used as the sampling
rate reference clock sample.
- clock-names : "i2sclk" for the sample rate reference clock.
- dmas: Pairs of phandle and specifier for the DMA channels that are used by
the core. The core expects one or two dma channels: one for transmit and
one for receive.
- dma-names : "tx" for the transmit channel, "rx" for the receive channel.
Optional properties:
- interrupts: The interrupt line number for the I2S controller. Add this
parameter if the I2S controller that you are using does not support DMA.
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names'
properties please check:
* resource-names.txt
* clock/clock-bindings.txt
* dma/dma.txt
Example:
soc_i2s: i2s@7ff90000 {
compatible = "snps,designware-i2s";
reg = <0x0 0x7ff90000 0x0 0x1000>;
clocks = <&scpi_i2sclk 0>;
clock-names = "i2sclk";
#sound-dai-cells = <0>;
dmas = <&dma0 5>;
dma-names = "tx";
};

View File

@ -1,33 +0,0 @@
NXP MICFIL Digital Audio Interface (MICFIL).
The MICFIL digital interface provides a 16-bit audio signal from a PDM
microphone bitstream in a configurable output sampling rate.
Required properties:
- compatible : Compatible list, contains "fsl,imx8mm-micfil"
or "fsl,imx8mp-micfil"
- reg : Offset and length of the register set for the device.
- interrupts : Contains the micfil interrupts.
- clocks : Must contain an entry for each entry in clock-names.
- clock-names : Must include the "ipg_clk" for register access and
"ipg_clk_app" for internal micfil clock.
- dmas : Generic dma devicetree binding as described in
Documentation/devicetree/bindings/dma/dma.txt.
Example:
micfil: micfil@30080000 {
compatible = "fsl,imx8mm-micfil";
reg = <0x0 0x30080000 0x0 0x10000>;
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MM_CLK_PDM_IPG>,
<&clk IMX8MM_CLK_PDM_ROOT>;
clock-names = "ipg_clk", "ipg_clk_app";
dmas = <&sdma2 24 26 0x80000000>;
};

View File

@ -0,0 +1,85 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/fsl,micfil.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP MICFIL Digital Audio Interface (MICFIL)
maintainers:
- Shengjiu Wang <shengjiu.wang@nxp.com>
description: |
The MICFIL digital interface provides a 16-bit or 24-bit audio signal
from a PDM microphone bitstream in a configurable output sampling rate.
properties:
compatible:
enum:
- fsl,imx8mm-micfil
- fsl,imx8mp-micfil
reg:
maxItems: 1
interrupts:
items:
- description: Digital Microphone interface interrupt
- description: Digital Microphone interface error interrupt
- description: voice activity detector event interrupt
- description: voice activity detector error interrupt
dmas:
items:
- description: DMA controller phandle and request line for RX
dma-names:
items:
- const: rx
clocks:
items:
- description: The ipg clock for register access
- description: internal micfil clock
- description: PLL clock source for 8kHz series
- description: PLL clock source for 11kHz series
- description: External clock 3
minItems: 2
clock-names:
items:
- const: ipg_clk
- const: ipg_clk_app
- const: pll8k
- const: pll11k
- const: clkext3
minItems: 2
required:
- compatible
- reg
- interrupts
- dmas
- dma-names
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/imx8mm-clock.h>
micfil: audio-controller@30080000 {
compatible = "fsl,imx8mm-micfil";
reg = <0x30080000 0x10000>;
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MM_CLK_PDM_IPG>,
<&clk IMX8MM_CLK_PDM_ROOT>;
clock-names = "ipg_clk", "ipg_clk_app";
dmas = <&sdma2 24 25 0>;
dma-names = "rx";
};

View File

@ -2,7 +2,7 @@ fsl,mqs audio CODEC
Required properties:
- compatible : Must contain one of "fsl,imx6sx-mqs", "fsl,codec-mqs"
"fsl,imx8qm-mqs", "fsl,imx8qxp-mqs".
"fsl,imx8qm-mqs", "fsl,imx8qxp-mqs", "fsl,imx93-mqs".
- clocks : A list of phandles + clock-specifiers, one for each entry in
clock-names
- clock-names : "mclk" - must required.

View File

@ -58,6 +58,8 @@ properties:
slave of the Shared Peripheral Bus and when two or more bus masters
(CPU, DMA or DSP) try to access it. This property is optional depending
on the SoC design.
- description: PLL clock source for 8kHz series rate, optional.
- description: PLL clock source for 11khz series rate, optional.
minItems: 9
clock-names:
@ -72,6 +74,8 @@ properties:
- const: rxtx6
- const: rxtx7
- const: spba
- const: pll8k
- const: pll11k
minItems: 9
big-endian:

View File

@ -21,6 +21,9 @@ Required properties:
- clock-names : Must include the "bus" for register access and
"mclk1", "mclk2", "mclk3" for bit clock and frame
clock providing.
"pll8k", "pll11k" are optional, they are the clock
source for root clock, one is for 8kHz series rates
another one is for 11kHz series rates.
- dmas : Generic dma devicetree binding as described in
Documentation/devicetree/bindings/dma/dma.txt.
@ -49,6 +52,14 @@ Required properties:
receive data by following their own bit clocks and
frame sync clocks separately.
- fsl,dataline : configure the dataline. it has 3 value for each configuration
first one means the type: I2S(1) or PDM(2)
second one is dataline mask for 'rx'
third one is dataline mask for 'tx'.
for example: fsl,dataline = <1 0xff 0xff 2 0xff 0x11>;
it means I2S type rx mask is 0xff, tx mask is 0xff, PDM type
rx mask is 0xff, tx mask is 0x11 (dataline 1 and 4 enabled).
Optional properties:
- big-endian : Boolean property, required if all the SAI

View File

@ -34,7 +34,7 @@ Optional properties:
- nuvoton,jack-eject-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms
- nuvoton,dmic-clk-threshold: the ADC threshold of DMIC clock.
- nuvoton,key_enable: Headset button detection switch.
Example:

View File

@ -110,6 +110,10 @@ patternProperties:
type: object
$ref: nvidia,tegra186-asrc.yaml#
'^processing-engine@[0-9a-f]+$':
type: object
$ref: nvidia,tegra210-ope.yaml#
required:
- compatible
- reg

View File

@ -0,0 +1,47 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra210-mbdrc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Tegra210 MBDRC
description:
The Multi Band Dynamic Range Compressor (MBDRC) is part of Output
Processing Engine (OPE) which interfaces with Audio Hub (AHUB) via
Audio Client Interface (ACIF). MBDRC can be used as a traditional
single full band or a dual band or a multi band dynamic processor.
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Mohan Kumar <mkumard@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
properties:
compatible:
oneOf:
- const: nvidia,tegra210-mbdrc
- items:
- enum:
- nvidia,tegra234-mbdrc
- nvidia,tegra194-mbdrc
- nvidia,tegra186-mbdrc
- const: nvidia,tegra210-mbdrc
reg:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
dynamic-range-compressor@702d8200 {
compatible = "nvidia,tegra210-mbdrc";
reg = <0x702d8200 0x200>;
};
...

View File

@ -0,0 +1,87 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra210-ope.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Tegra210 OPE
description:
The Output Processing Engine (OPE) is one of the AHUB client. It has
PEQ (Parametric Equalizer) and MBDRC (Multi Band Dynamic Range Compressor)
sub blocks for data processing.
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Mohan Kumar <mkumard@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: name-prefix.yaml#
properties:
compatible:
oneOf:
- const: nvidia,tegra210-ope
- items:
- enum:
- nvidia,tegra234-ope
- nvidia,tegra194-ope
- nvidia,tegra186-ope
- const: nvidia,tegra210-ope
reg:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 1
ranges: true
sound-name-prefix:
pattern: "^OPE[1-9]$"
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description:
OPE ACIF (Audio Client Interface) input port. This is connected
to corresponding ACIF output port on AHUB (Audio Hub).
port@1:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description:
OPE ACIF output port. This is connected to corresponding ACIF
input port on AHUB.
patternProperties:
'^equalizer@[0-9a-f]+$':
type: object
$ref: nvidia,tegra210-peq.yaml#
'^dynamic-range-compressor@[0-9a-f]+$':
type: object
$ref: nvidia,tegra210-mbdrc.yaml#
required:
- compatible
- reg
additionalProperties: false
examples:
- |
processing-engine@702d8000 {
compatible = "nvidia,tegra210-ope";
reg = <0x702d8000 0x100>;
sound-name-prefix = "OPE1";
};
...

View File

@ -0,0 +1,48 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra210-peq.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Tegra210 PEQ
description:
The Parametric Equalizer (PEQ) is a cascade of biquad filters with
each filter tuned based on certain parameters. It can be used to
equalize the irregularities in the speaker frequency response.
PEQ sits inside Output Processing Engine (OPE) which interfaces
with Audio Hub (AHUB) via Audio Client Interface (ACIF).
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Mohan Kumar <mkumard@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
properties:
compatible:
oneOf:
- const: nvidia,tegra210-peq
- items:
- enum:
- nvidia,tegra234-peq
- nvidia,tegra194-peq
- nvidia,tegra186-peq
- const: nvidia,tegra210-peq
reg:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
equalizer@702d8100 {
compatible = "nvidia,tegra210-peq";
reg = <0x702d8100 0x100>;
};
...

View File

@ -15,6 +15,7 @@ allOf:
properties:
compatible:
enum:
- nxp,tfa9890
- nxp,tfa9895
- nxp,tfa9897

View File

@ -25,12 +25,12 @@ properties:
- qcom,sc7280-lpass-cpu
reg:
minItems: 2
minItems: 1
maxItems: 6
description: LPAIF core registers
reg-names:
minItems: 2
minItems: 1
maxItems: 6
clocks:
@ -42,12 +42,12 @@ properties:
maxItems: 10
interrupts:
minItems: 2
minItems: 1
maxItems: 4
description: LPAIF DMA buffer interrupt
interrupt-names:
minItems: 2
minItems: 1
maxItems: 4
qcom,adsp:

View File

@ -1,91 +0,0 @@
* Qualcomm Technologies Inc. SDM845 ASoC sound card driver
This binding describes the SDM845 sound card, which uses qdsp for audio.
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be one of this
"qcom,sdm845-sndcard"
"qcom,db845c-sndcard"
"lenovo,yoga-c630-sndcard"
- audio-routing:
Usage: Optional
Value type: <stringlist>
Definition: A list of the connections between audio components.
Each entry is a pair of strings, the first being the
connection's sink, the second being the connection's
source. Valid names could be power supplies, MicBias
of codec and the jacks on the board.
- model:
Usage: required
Value type: <stringlist>
Definition: The user-visible name of this sound card.
- aux-devs
Usage: optional
Value type: <array of phandles>
Definition: A list of phandles for auxiliary devices (e.g. analog
amplifiers) that do not appear directly within the DAI
links. Should be connected to another audio component
using "audio-routing".
= dailinks
Each subnode of sndcard represents either a dailink, and subnodes of each
dailinks would be cpu/codec/platform dais.
- link-name:
Usage: required
Value type: <string>
Definition: User friendly name for dai link
= CPU, PLATFORM, CODEC dais subnodes
- cpu:
Usage: required
Value type: <subnode>
Definition: cpu dai sub-node
- codec:
Usage: required
Value type: <subnode>
Definition: codec dai sub-node
- platform:
Usage: Optional
Value type: <subnode>
Definition: platform dai sub-node
- sound-dai:
Usage: required
Value type: <phandle>
Definition: dai phandle/s and port of CPU/CODEC/PLATFORM node.
Example:
audio {
compatible = "qcom,sdm845-sndcard";
model = "sdm845-snd-card";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active>;
pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep>;
mm1-dai-link {
link-name = "MultiMedia1";
cpu {
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
};
};
pri-mi2s-dai-link {
link-name = "PRI MI2S Playback";
cpu {
sound-dai = <&q6afedai PRIMARY_MI2S_RX>;
};
platform {
sound-dai = <&q6routing>;
};
};
};

View File

@ -16,8 +16,11 @@ description:
properties:
compatible:
enum:
- lenovo,yoga-c630-sndcard
- qcom,apq8016-sbc-sndcard
- qcom,db845c-sndcard
- qcom,msm8916-qdsp6-sndcard
- qcom,sdm845-sndcard
- qcom,sm8250-sndcard
- qcom,qrb5165-rb5-sndcard

View File

@ -0,0 +1,74 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,wsa883x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Bindings for The Qualcomm WSA8830/WSA8832/WSA8835
smart speaker amplifier
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
description: |
WSA883X is the Qualcomm Aqstic smart speaker amplifier
Their primary operating mode uses a SoundWire digital audio
interface. This binding is for SoundWire interface.
properties:
compatible:
const: sdw10217020200
reg:
maxItems: 1
powerdown-gpios:
description: GPIO spec for Powerdown/Shutdown line to use
maxItems: 1
vdd-supply:
description: VDD Supply for the Codec
'#thermal-sensor-cells':
const: 0
'#sound-dai-cells':
const: 0
required:
- compatible
- reg
- vdd-supply
- powerdown-gpios
- "#thermal-sensor-cells"
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
soundwire-controller@3250000 {
#address-cells = <2>;
#size-cells = <0>;
reg = <0x3250000 0x2000>;
speaker@0,1 {
compatible = "sdw10217020200";
reg = <0 1>;
powerdown-gpios = <&tlmm 1 0>;
vdd-supply = <&vreg_s10b_1p8>;
#thermal-sensor-cells = <0>;
#sound-dai-cells = <0>;
};
speaker@0,2 {
compatible = "sdw10217020200";
reg = <0 2>;
powerdown-gpios = <&tlmm 89 0>;
vdd-supply = <&vreg_s10b_1p8>;
#thermal-sensor-cells = <0>;
#sound-dai-cells = <0>;
};
};
...

View File

@ -61,6 +61,13 @@ properties:
- const: tx
- const: rx
pinctrl-names:
oneOf:
- const: default
- items:
- const: bclk_on
- const: bclk_off
power-domains:
maxItems: 1

View File

@ -0,0 +1,94 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/snps,designware-i2s.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: DesignWare I2S controller
maintainers:
- Jose Abreu <joabreu@synopsys.com>
properties:
compatible:
oneOf:
- items:
- const: canaan,k210-i2s
- const: snps,designware-i2s
- enum:
- snps,designware-i2s
reg:
maxItems: 1
interrupts:
description: |
The interrupt line number for the I2S controller. Add this
parameter if the I2S controller that you are using does not
support DMA.
maxItems: 1
clocks:
description: Sampling rate reference clock
maxItems: 1
clock-names:
const: i2sclk
resets:
maxItems: 1
dmas:
items:
- description: TX DMA Channel
- description: RX DMA Channel
minItems: 1
dma-names:
items:
- const: tx
- const: rx
minItems: 1
if:
properties:
compatible:
contains:
const: canaan,k210-i2s
then:
properties:
"#sound-dai-cells":
const: 1
else:
properties:
"#sound-dai-cells":
const: 0
required:
- compatible
- reg
- clocks
- clock-names
oneOf:
- required:
- dmas
- dma-names
- required:
- interrupts
unevaluatedProperties: false
examples:
- |
soc_i2s: i2s@7ff90000 {
compatible = "snps,designware-i2s";
reg = <0x7ff90000 0x1000>;
clocks = <&scpi_i2sclk 0>;
clock-names = "i2sclk";
#sound-dai-cells = <0>;
dmas = <&dma0 5>;
dma-names = "tx";
};

View File

@ -0,0 +1,72 @@
# 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>;
};
};
...

View File

@ -108,7 +108,7 @@ On-line docs
* Title: **Writing an ALSA Driver**
:Author: Takashi Iwai <tiwai@suse.de>
:URL: http://www.alsa-project.org/~iwai/writing-an-alsa-driver/index.html
:URL: https://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html
:Date: 2005
:Keywords: ALSA, sound, soundcard, driver, lowlevel, hardware.
:Description: Advanced Linux Sound Architecture for developers,

View File

@ -132,7 +132,7 @@ The codec driver also supports the following ALSA PCM operations:-
};
Please refer to the ALSA driver PCM documentation for details.
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/
https://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html
DAPM description

View File

@ -10,7 +10,7 @@ AC97
====
AC97 is a five wire interface commonly found on many PC sound cards. It is
now also popular in many portable devices. This DAI has a reset line and time
now also popular in many portable devices. This DAI has a RESET line and time
multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97

View File

@ -46,7 +46,7 @@ snd_soc_component_driver:-
};
Please refer to the ALSA driver documentation for details of audio DMA.
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/
https://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html
An example DMA driver is soc/pxa/pxa2xx-pcm.c

View File

@ -16268,6 +16268,9 @@ M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
M: Banajit Goswami <bgoswami@quicinc.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Supported
F: include/dt-bindings/sound/qcom,wcd9335.h
F: sound/soc/codecs/lpass-rx-macro.*
F: sound/soc/codecs/lpass-tx-macro.*
F: sound/soc/codecs/lpass-va-macro.c
F: sound/soc/codecs/lpass-wsa-macro.*
F: sound/soc/codecs/msm8916-wcd-analog.c
@ -16275,7 +16278,9 @@ F: sound/soc/codecs/msm8916-wcd-digital.c
F: sound/soc/codecs/wcd9335.*
F: sound/soc/codecs/wcd934x.c
F: sound/soc/codecs/wcd-clsh-v2.*
F: sound/soc/codecs/wcd-mbhc-v2.*
F: sound/soc/codecs/wsa881x.c
F: sound/soc/codecs/wsa883x.c
F: sound/soc/qcom/
QCOM EMBEDDED USB DEBUGGER (EUD)

View File

@ -1880,8 +1880,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
*/
bool regmap_can_raw_write(struct regmap *map)
{
return map->bus && map->bus->write && map->format.format_val &&
map->format.format_reg;
return map->write && map->format.format_val && map->format.format_reg;
}
EXPORT_SYMBOL_GPL(regmap_can_raw_write);
@ -2155,10 +2154,9 @@ int regmap_noinc_write(struct regmap *map, unsigned int reg,
size_t write_len;
int ret;
if (!map->bus)
return -EINVAL;
if (!map->bus->write)
if (!map->write)
return -ENOTSUPP;
if (val_len % map->format.val_bytes)
return -EINVAL;
if (!IS_ALIGNED(reg, map->reg_stride))
@ -2220,6 +2218,28 @@ int regmap_field_update_bits_base(struct regmap_field *field,
}
EXPORT_SYMBOL_GPL(regmap_field_update_bits_base);
/**
* regmap_field_test_bits() - Check if all specified bits are set in a
* register field.
*
* @field: Register field to operate on
* @bits: Bits to test
*
* Returns -1 if the underlying regmap_field_read() fails, 0 if at least one of the
* tested bits is not set and 1 if all tested bits are set.
*/
int regmap_field_test_bits(struct regmap_field *field, unsigned int bits)
{
unsigned int val, ret;
ret = regmap_field_read(field, &val);
if (ret)
return ret;
return (val & bits) == bits;
}
EXPORT_SYMBOL_GPL(regmap_field_test_bits);
/**
* regmap_fields_update_bits_base() - Perform a read/modify/write cycle a
* register field with port ID
@ -2278,7 +2298,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
* Some devices don't support bulk write, for them we have a series of
* single write operations.
*/
if (!map->bus || !map->format.parse_inplace) {
if (!map->write || !map->format.parse_inplace) {
map->lock(map->lock_arg);
for (i = 0; i < val_count; i++) {
unsigned int ival;
@ -2904,6 +2924,9 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
size_t read_len;
int ret;
if (!map->read)
return -ENOTSUPP;
if (val_len % map->format.val_bytes)
return -EINVAL;
if (!IS_ALIGNED(reg, map->reg_stride))
@ -3017,7 +3040,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
if (val_count == 0)
return -EINVAL;
if (map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
if (map->read && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
if (ret != 0)
return ret;

View File

@ -12,6 +12,8 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
static const char * const adsp_mbox_ch_names[MTK_ADSP_MBOX_NUM] = { "rx", "tx" };
/*
* mtk_adsp_ipc_send - send ipc cmd to MTK ADSP
*
@ -72,7 +74,6 @@ static int mtk_adsp_ipc_probe(struct platform_device *pdev)
struct mtk_adsp_ipc *adsp_ipc;
struct mtk_adsp_chan *adsp_chan;
struct mbox_client *cl;
char *chan_name;
int ret;
int i, j;
@ -83,12 +84,6 @@ static int mtk_adsp_ipc_probe(struct platform_device *pdev)
return -ENOMEM;
for (i = 0; i < MTK_ADSP_MBOX_NUM; i++) {
chan_name = kasprintf(GFP_KERNEL, "mbox%d", i);
if (!chan_name) {
ret = -ENOMEM;
goto out;
}
adsp_chan = &adsp_ipc->chans[i];
cl = &adsp_chan->cl;
cl->dev = dev->parent;
@ -99,17 +94,20 @@ static int mtk_adsp_ipc_probe(struct platform_device *pdev)
adsp_chan->ipc = adsp_ipc;
adsp_chan->idx = i;
adsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
adsp_chan->ch = mbox_request_channel_byname(cl, adsp_mbox_ch_names[i]);
if (IS_ERR(adsp_chan->ch)) {
ret = PTR_ERR(adsp_chan->ch);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to request mbox chan %d ret %d\n",
i, ret);
goto out_free;
}
dev_err(dev, "Failed to request mbox chan %s ret %d\n",
adsp_mbox_ch_names[i], ret);
dev_dbg(dev, "request mbox chan %s\n", chan_name);
kfree(chan_name);
for (j = 0; j < i; j++) {
adsp_chan = &adsp_ipc->chans[j];
mbox_free_channel(adsp_chan->ch);
}
return ret;
}
}
adsp_ipc->dev = dev;
@ -117,16 +115,6 @@ static int mtk_adsp_ipc_probe(struct platform_device *pdev)
dev_dbg(dev, "MTK ADSP IPC initialized\n");
return 0;
out_free:
kfree(chan_name);
out:
for (j = 0; j < i; j++) {
adsp_chan = &adsp_ipc->chans[j];
mbox_free_channel(adsp_chan->ch);
}
return ret;
}
static int mtk_adsp_ipc_remove(struct platform_device *pdev)

View File

@ -549,8 +549,9 @@ static int sii902x_audio_hw_params(struct device *dev, void *data,
unsigned long mclk_rate;
int i, ret;
if (daifmt->bit_clk_master || daifmt->frame_clk_master) {
dev_dbg(dev, "%s: I2S master mode not supported\n", __func__);
if (daifmt->bit_clk_provider || daifmt->frame_clk_provider) {
dev_dbg(dev, "%s: I2S clock provider mode not supported\n",
__func__);
return -EINVAL;
}

View File

@ -45,7 +45,7 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
u8 inputclkfs = 0;
/* it cares I2S only */
if (fmt->bit_clk_master | fmt->frame_clk_master) {
if (fmt->bit_clk_provider | fmt->frame_clk_provider) {
dev_err(dev, "unsupported clock settings\n");
return -EINVAL;
}

View File

@ -1594,12 +1594,12 @@ static int hdmi_audio_hw_params(struct device *dev, void *data,
struct hdmi_context *hdata = dev_get_drvdata(dev);
if (daifmt->fmt != HDMI_I2S || daifmt->bit_clk_inv ||
daifmt->frame_clk_inv || daifmt->bit_clk_master ||
daifmt->frame_clk_master) {
daifmt->frame_clk_inv || daifmt->bit_clk_provider ||
daifmt->frame_clk_provider) {
dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
daifmt->bit_clk_inv, daifmt->frame_clk_inv,
daifmt->bit_clk_master,
daifmt->frame_clk_master);
daifmt->bit_clk_provider,
daifmt->frame_clk_provider);
return -EINVAL;
}

View File

@ -1095,11 +1095,11 @@ static int tda998x_audio_hw_params(struct device *dev, void *data,
if (!spdif &&
(daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
daifmt->bit_clk_master || daifmt->frame_clk_master)) {
daifmt->bit_clk_provider || daifmt->frame_clk_provider)) {
dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
daifmt->bit_clk_inv, daifmt->frame_clk_inv,
daifmt->bit_clk_master,
daifmt->frame_clk_master);
daifmt->bit_clk_provider,
daifmt->frame_clk_provider);
return -EINVAL;
}

View File

@ -1175,12 +1175,12 @@ static int hdmi_audio_hw_params(struct device *dev,
DRM_DEBUG_DRIVER("\n");
if ((daifmt->fmt != HDMI_I2S) || daifmt->bit_clk_inv ||
daifmt->frame_clk_inv || daifmt->bit_clk_master ||
daifmt->frame_clk_master) {
daifmt->frame_clk_inv || daifmt->bit_clk_provider ||
daifmt->frame_clk_provider) {
dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
daifmt->bit_clk_inv, daifmt->frame_clk_inv,
daifmt->bit_clk_master,
daifmt->frame_clk_master);
daifmt->bit_clk_provider,
daifmt->frame_clk_provider);
return -EINVAL;
}

View File

@ -1969,6 +1969,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = {
.name = "vc4-hdmi-cpu-dai-component",
.legacy_dai_naming = 1,
};
static int vc4_hdmi_audio_cpu_dai_probe(struct snd_soc_dai *dai)

View File

@ -2517,7 +2517,6 @@ static struct snd_soc_component_driver tda1997x_codec_driver = {
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static int tda1997x_probe(struct i2c_client *client,

View File

@ -1004,9 +1004,18 @@ static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct sn
{
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_intel *sdw = cdns_to_intel(cdns);
struct sdw_intel_link_res *res = sdw->link_res;
struct sdw_cdns_dma_data *dma;
int ret = 0;
/*
* The .trigger callback is used to send required IPC to audio
* firmware. The .free_stream callback will still be called
* by intel_free_stream() in the TRIGGER_SUSPEND case.
*/
if (res->ops && res->ops->trigger)
res->ops->trigger(dai, cmd, substream->stream);
dma = snd_soc_dai_get_dma_data(dai, substream);
if (!dma) {
dev_err(dai->dev, "failed to get dma data in %s\n",
@ -1097,8 +1106,9 @@ static const struct snd_soc_dai_ops intel_pcm_dai_ops = {
};
static const struct snd_soc_component_driver dai_component = {
.name = "soundwire",
.suspend = intel_component_dais_suspend
.name = "soundwire",
.suspend = intel_component_dais_suspend,
.legacy_dai_naming = 1,
};
static int intel_create_dai(struct sdw_cdns *cdns,

View File

@ -13,6 +13,7 @@
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/pm_wakeirq.h>
#include <linux/slimbus.h>
@ -142,6 +143,7 @@ struct qcom_swrm_ctrl {
struct device *dev;
struct regmap *regmap;
void __iomem *mmio;
struct reset_control *audio_cgcr;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs;
#endif
@ -656,6 +658,8 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
val = FIELD_PREP(SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK, ctrl->rows_index);
val |= FIELD_PREP(SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK, ctrl->cols_index);
reset_control_reset(ctrl->audio_cgcr);
ctrl->reg_write(ctrl, SWRM_MCP_FRAME_CTRL_BANK_ADDR(0), val);
/* Enable Auto enumeration */
@ -1332,6 +1336,10 @@ static int qcom_swrm_probe(struct platform_device *pdev)
ctrl->bus.compute_params = &qcom_swrm_compute_params;
ctrl->bus.clk_stop_timeout = 300;
ctrl->audio_cgcr = devm_reset_control_get_exclusive(dev, "swr_audio_cgcr");
if (IS_ERR(ctrl->audio_cgcr))
dev_err(dev, "Failed to get audio_cgcr reset required for soundwire-v1.6.0\n");
ret = qcom_swrm_get_port_config(ctrl);
if (ret)
goto err_clk;
@ -1485,6 +1493,8 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev)
qcom_swrm_get_device_status(ctrl);
sdw_handle_slave_status(&ctrl->bus, ctrl->status);
} else {
reset_control_reset(ctrl->audio_cgcr);
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START);
ctrl->reg_write(ctrl, SWRM_INTERRUPT_CLEAR,
SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET);

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
#ifndef __DT_SOUND_QCOM_WCD9335_H
#define __DT_SOUND_QCOM_WCD9335_H
#define AIF1_PB 0
#define AIF1_CAP 1
#define AIF2_PB 2
#define AIF2_CAP 3
#define AIF3_PB 4
#define AIF3_CAP 5
#define AIF4_PB 6
#define NUM_CODEC_DAIS 7
#endif

View File

@ -1336,6 +1336,22 @@ static inline int regmap_field_update_bits(struct regmap_field *field,
NULL, false, false);
}
static inline int regmap_field_set_bits(struct regmap_field *field,
unsigned int bits)
{
return regmap_field_update_bits_base(field, bits, bits, NULL, false,
false);
}
static inline int regmap_field_clear_bits(struct regmap_field *field,
unsigned int bits)
{
return regmap_field_update_bits_base(field, bits, 0, NULL, false,
false);
}
int regmap_field_test_bits(struct regmap_field *field, unsigned int bits);
static inline int
regmap_field_force_update_bits(struct regmap_field *field,
unsigned int mask, unsigned int val)
@ -1769,6 +1785,27 @@ regmap_field_force_update_bits(struct regmap_field *field,
return -EINVAL;
}
static inline int regmap_field_set_bits(struct regmap_field *field,
unsigned int bits)
{
WARN_ONCE(1, "regmap API is disabled");
return -EINVAL;
}
static inline int regmap_field_clear_bits(struct regmap_field *field,
unsigned int bits)
{
WARN_ONCE(1, "regmap API is disabled");
return -EINVAL;
}
static inline int regmap_field_test_bits(struct regmap_field *field,
unsigned int bits)
{
WARN_ONCE(1, "regmap API is disabled");
return -EINVAL;
}
static inline int regmap_fields_write(struct regmap_field *field,
unsigned int id, unsigned int val)
{

View File

@ -9,6 +9,8 @@
#define SDW_SHIM_BASE 0x2C000
#define SDW_ALH_BASE 0x2C800
#define SDW_SHIM_BASE_ACE 0x38000
#define SDW_ALH_BASE_ACE 0x24000
#define SDW_LINK_BASE 0x30000
#define SDW_LINK_SIZE 0x10000
@ -119,6 +121,7 @@ struct sdw_intel_ops {
struct sdw_intel_stream_params_data *params_data);
int (*free_stream)(struct device *dev,
struct sdw_intel_stream_free_data *free_data);
int (*trigger)(struct snd_soc_dai *dai, int cmd, int stream);
};
/**

View File

@ -885,6 +885,9 @@ void cs35l41_configure_cs_dsp(struct device *dev, struct regmap *reg, struct cs_
int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap,
enum cs35l41_cspl_mbox_cmd cmd);
int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap);
int cs35l41_enter_hibernate(struct device *dev, struct regmap *regmap,
enum cs35l41_boost_type b_type);
int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap);
int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
struct cs35l41_hw_cfg *hw_cfg);
bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type);

View File

@ -32,8 +32,8 @@ struct hdmi_codec_daifmt {
} fmt;
unsigned int bit_clk_inv:1;
unsigned int frame_clk_inv:1;
unsigned int bit_clk_master:1;
unsigned int frame_clk_master:1;
unsigned int bit_clk_provider:1;
unsigned int frame_clk_provider:1;
/* bit_fmt could be standard PCM format or
* IEC958 encoded format. ALSA IEC958 plugin will pass
* IEC958_SUBFRAME format to the underneath driver.

View File

@ -9,7 +9,7 @@
#ifndef MADERA_CODEC_PDATA_H
#define MADERA_CODEC_PDATA_H
#include <linux/kernel.h>
#include <linux/types.h>
#define MADERA_MAX_INPUT 6
#define MADERA_MAX_MUXED_CHANNELS 4

View File

@ -1434,6 +1434,20 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
const char *snd_pcm_format_name(snd_pcm_format_t format);
/**
* snd_pcm_direction_name - Get a string naming the direction of a stream
* @direction: Stream's direction, one of SNDRV_PCM_STREAM_XXX
*
* Returns a string naming the direction of the stream.
*/
static inline const char *snd_pcm_direction_name(int direction)
{
if (direction == SNDRV_PCM_STREAM_PLAYBACK)
return "Playback";
else
return "Capture";
}
/**
* snd_pcm_stream_str - Get a string naming the direction of a stream
* @substream: the pcm substream instance
@ -1442,10 +1456,7 @@ const char *snd_pcm_format_name(snd_pcm_format_t format);
*/
static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream)
{
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
return "Playback";
else
return "Capture";
return snd_pcm_direction_name(substream->stream);
}
/*

View File

@ -51,7 +51,6 @@ struct prop_nums {
int cpus;
int codecs;
int platforms;
int c2c;
};
struct asoc_simple_priv {
@ -64,7 +63,6 @@ struct asoc_simple_priv {
struct snd_soc_dai_link_component *platforms;
struct asoc_simple_data adata;
struct snd_soc_codec_conf *codec_conf;
struct snd_soc_pcm_stream *c2c_conf;
struct prop_nums num;
unsigned int mclk_fs;
} *dai_props;
@ -75,7 +73,6 @@ struct asoc_simple_priv {
struct snd_soc_dai_link_component *dlcs;
struct snd_soc_dai_link_component dummy;
struct snd_soc_codec_conf *codec_conf;
struct snd_soc_pcm_stream *c2c_conf;
struct gpio_desc *pa_gpio;
const struct snd_soc_ops *ops;
unsigned int dpcm_selectable:1;
@ -173,7 +170,7 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platfo
void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus,
int is_single_links);
int asoc_simple_clean_reference(struct snd_soc_card *card);
void asoc_simple_clean_reference(struct snd_soc_card *card);
void asoc_simple_convert_fixup(struct asoc_simple_data *data,
struct snd_pcm_hw_params *params);

View File

@ -30,6 +30,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[];
@ -37,6 +38,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[];
/*
* generic table used for HDA codec-based platforms, possibly with

View File

@ -29,6 +29,7 @@ int snd_soc_card_resume_post(struct snd_soc_card *card);
int snd_soc_card_probe(struct snd_soc_card *card);
int snd_soc_card_late_probe(struct snd_soc_card *card);
void snd_soc_card_fixup_controls(struct snd_soc_card *card);
int snd_soc_card_remove(struct snd_soc_card *card);
int snd_soc_card_set_bias_level(struct snd_soc_card *card,

View File

@ -179,7 +179,7 @@ struct snd_soc_component_driver {
* analogue).
*/
unsigned int endianness:1;
unsigned int non_legacy_dai_naming:1;
unsigned int legacy_dai_naming:1;
/* this component uses topology and ignore machine driver FEs */
const char *ignore_machine;
@ -348,11 +348,6 @@ static inline int snd_soc_component_cache_sync(
return regcache_sync(component->regmap);
}
static inline int snd_soc_component_is_codec(struct snd_soc_component *component)
{
return component->driver->non_legacy_dai_naming;
}
void snd_soc_component_set_aux(struct snd_soc_component *component,
struct snd_soc_aux_dev *aux);
int snd_soc_component_init(struct snd_soc_component *component);

View File

@ -124,6 +124,12 @@ struct snd_compr_stream;
#define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC
#define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC
/* when passed to set_fmt directly indicate if the device is provider or consumer */
#define SND_SOC_DAIFMT_BP_FP SND_SOC_DAIFMT_CBP_CFP
#define SND_SOC_DAIFMT_BC_FP SND_SOC_DAIFMT_CBC_CFP
#define SND_SOC_DAIFMT_BP_FC SND_SOC_DAIFMT_CBP_CFC
#define SND_SOC_DAIFMT_BC_FC SND_SOC_DAIFMT_CBC_CFC
/* Describes the possible PCM format */
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT 48
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)

View File

@ -136,6 +136,18 @@
.put = snd_soc_put_volsw, \
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
max, invert, 0) }
#define SOC_DOUBLE_SX_TLV(xname, xreg, shift_left, shift_right, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw_sx, \
.get = snd_soc_get_volsw_sx, \
.put = snd_soc_put_volsw_sx, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xreg, \
.shift = shift_left, .rshift = shift_right, \
.max = xmax, .min = xmin} }
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@ -414,7 +426,7 @@ enum snd_soc_pcm_subclass {
};
int snd_soc_register_card(struct snd_soc_card *card);
int snd_soc_unregister_card(struct snd_soc_card *card);
void snd_soc_unregister_card(struct snd_soc_card *card);
int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card);
#ifdef CONFIG_PM_SLEEP
int snd_soc_suspend(struct device *dev);
@ -914,6 +926,7 @@ struct snd_soc_card {
int (*probe)(struct snd_soc_card *card);
int (*late_probe)(struct snd_soc_card *card);
void (*fixup_controls)(struct snd_soc_card *card);
int (*remove)(struct snd_soc_card *card);
/* the pre and post PM functions are used to do any PM work before and

View File

@ -138,6 +138,7 @@ struct sof_dev_desc {
struct snd_sof_dsp_ops *ops;
int (*ops_init)(struct snd_sof_dev *sdev);
void (*ops_free)(struct snd_sof_dev *sdev);
};
int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd);

View File

@ -18,4 +18,11 @@ struct sof_ipc_dai_acp_params {
uint32_t fsync_rate; /* FSYNC frequency in Hz */
uint32_t tdm_slots;
} __packed;
/* ACPDMIC Configuration Request - SOF_IPC_DAI_AMD_CONFIG */
struct sof_ipc_dai_acpdmic_params {
uint32_t pdm_rate;
uint32_t pdm_ch;
} __packed;
#endif

View File

@ -111,7 +111,7 @@ struct sof_ipc_dai_config {
struct sof_ipc_dai_sai_params sai;
struct sof_ipc_dai_acp_params acpbt;
struct sof_ipc_dai_acp_params acpsp;
struct sof_ipc_dai_acp_params acpdmic;
struct sof_ipc_dai_acpdmic_params acpdmic;
struct sof_ipc_dai_mtk_afe_params afe;
};
} __packed;

View File

@ -385,6 +385,14 @@ struct sof_ipc4_fw_version {
uint16_t build;
} __packed;
/* Payload data for SOF_IPC4_MOD_SET_DX */
struct sof_ipc4_dx_state_info {
/* core(s) to apply the change */
uint32_t core_mask;
/* core state: 0: put core_id to D3; 1: put core_id to D0 */
uint32_t dx_mask;
} __packed __aligned(4);
/* Reply messages */
/*

View File

@ -86,9 +86,11 @@ struct sof_ipc_stream_params {
uint32_t host_period_bytes;
uint16_t no_stream_position; /**< 1 means don't send stream position */
uint8_t cont_update_posn; /**< 1 means continuous update stream position */
uint8_t reserved[5];
uint8_t reserved0;
int16_t ext_data_length; /**< 0, means no extended data */
uint8_t reserved[2];
uint16_t chmap[SOF_IPC_MAX_CHANNELS]; /**< channel map - SOF_CHMAP_ */
uint8_t ext_data[]; /**< extended data */
} __packed;
/* PCM params info - SOF_IPC_STREAM_PCM_PARAMS */

View File

@ -24,9 +24,11 @@
#ifndef __INCLUDE_UAPI_SOUND_SOF_ABI_H__
#define __INCLUDE_UAPI_SOUND_SOF_ABI_H__
#include <linux/types.h>
/* SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3
#define SOF_ABI_MINOR 21
#define SOF_ABI_MINOR 22
#define SOF_ABI_PATCH 0
/* SOF ABI version number. Format within 32bit word is MMmmmppp */

View File

@ -26,4 +26,34 @@ struct sof_abi_hdr {
__u32 data[0]; /**< Component data - opaque to core */
} __packed;
#define SOF_MANIFEST_DATA_TYPE_NHLT 1
/**
* struct sof_manifest_tlv - SOF manifest TLV data
* @type: type of data
* @size: data size (not including the size of this struct)
* @data: payload data
*/
struct sof_manifest_tlv {
__le32 type;
__le32 size;
__u8 data[];
};
/**
* struct sof_manifest - SOF topology manifest
* @abi_major: Major ABI version
* @abi_minor: Minor ABI version
* @abi_patch: ABI patch
* @count: count of tlv items
* @items: consecutive variable size tlv items
*/
struct sof_manifest {
__le16 abi_major;
__le16 abi_minor;
__le16 abi_patch;
__le16 count;
struct sof_manifest_tlv items[];
};
#endif

View File

@ -52,11 +52,17 @@
#define SOF_TKN_SCHED_FRAMES 204
#define SOF_TKN_SCHED_TIME_DOMAIN 205
#define SOF_TKN_SCHED_DYNAMIC_PIPELINE 206
#define SOF_TKN_SCHED_LP_MODE 207
#define SOF_TKN_SCHED_MEM_USAGE 208
/* volume */
#define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250
#define SOF_TKN_VOLUME_RAMP_STEP_MS 251
#define SOF_TKN_GAIN_RAMP_TYPE 260
#define SOF_TKN_GAIN_RAMP_DURATION 261
#define SOF_TKN_GAIN_VAL 262
/* SRC */
#define SOF_TKN_SRC_RATE_IN 300
#define SOF_TKN_SRC_RATE_OUT 301
@ -79,6 +85,9 @@
*/
#define SOF_TKN_COMP_CORE_ID 404
#define SOF_TKN_COMP_UUID 405
#define SOF_TKN_COMP_CPC 406
#define SOF_TKN_COMP_IS_PAGES 409
#define SOF_TKN_COMP_NUM_AUDIO_FORMATS 410
/* SSP */
#define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500
@ -145,4 +154,39 @@
#define SOF_TKN_MEDIATEK_AFE_CH 1601
#define SOF_TKN_MEDIATEK_AFE_FORMAT 1602
/* MIXER */
#define SOF_TKN_MIXER_TYPE 1700
/* ACPDMIC */
#define SOF_TKN_AMD_ACPDMIC_RATE 1800
#define SOF_TKN_AMD_ACPDMIC_CH 1801
/* CAVS AUDIO FORMAT */
#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_RATE 1900
#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_BIT_DEPTH 1901
#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_VALID_BIT 1902
#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CHANNELS 1903
#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_MAP 1904
#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_CFG 1905
#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE 1906
#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG 1907
#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_SAMPLE_TYPE 1908
/* intentional token numbering discontinuity, reserved for future use */
#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE 1930
#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH 1931
#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_VALID_BIT 1932
#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CHANNELS 1933
#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_MAP 1934
#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_CFG 1935
#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_INTERLEAVING_STYLE 1936
#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_FMT_CFG 1937
#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_SAMPLE_TYPE 1938
/* intentional token numbering discontinuity, reserved for future use */
#define SOF_TKN_CAVS_AUDIO_FORMAT_IBS 1970
#define SOF_TKN_CAVS_AUDIO_FORMAT_OBS 1971
#define SOF_TKN_CAVS_AUDIO_FORMAT_DMA_BUFFER_SIZE 1972
/* COPIER */
#define SOF_TKN_INTEL_COPIER_NODE_TYPE 1980
#endif

View File

@ -8,7 +8,7 @@
/* Power-Management-Code ( CONFIG_PM )
* for ens1371 only ( FIXME )
* derived from cs4281.c, atiixp.c and via82xx.c
* using http://www.alsa-project.org/~tiwai/writing-an-alsa-driver/
* using https://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html
* by Kurt J. Bosch
*/

View File

@ -161,6 +161,7 @@ static struct snd_soc_dai_driver axi_i2s_dai = {
static const struct snd_soc_component_driver axi_i2s_component = {
.name = "axi-i2s",
.legacy_dai_naming = 1,
};
static const struct regmap_config axi_i2s_regmap_config = {

View File

@ -167,6 +167,7 @@ static struct snd_soc_dai_driver axi_spdif_dai = {
static const struct snd_soc_component_driver axi_spdif_component = {
.name = "axi-spdif",
.legacy_dai_naming = 1,
};
static const struct regmap_config axi_spdif_regmap_config = {

View File

@ -23,6 +23,18 @@ config SND_SOC_AMD_CZ_RT5645_MACH
help
This option enables machine driver for rt5645.
config SND_SOC_AMD_ST_ES8336_MACH
tristate "AMD ST support for ES8336"
select SND_SOC_ACPI if ACPI
select SND_SOC_ES8316
depends on SND_SOC_AMD_ACP && ACPI
depends on I2C
help
This option enables machine driver for Jadeite platform
using es8336 codec.
Say m if you have such a device.
If unsure select "N".
config SND_SOC_AMD_ACP3x
tristate "AMD Audio Coprocessor-v3.x support"
depends on X86 && PCI

View File

@ -2,12 +2,14 @@
acp_audio_dma-objs := acp-pcm-dma.o
snd-soc-acp-da7219mx98357-mach-objs := acp-da7219-max98357a.o
snd-soc-acp-rt5645-mach-objs := acp-rt5645.o
snd-soc-acp-es8336-mach-objs := acp-es8336.o
snd-soc-acp-rt5682-mach-objs := acp3x-rt5682-max9836.o
snd-acp-config-objs := acp-config.o
obj-$(CONFIG_SND_SOC_AMD_ACP) += acp_audio_dma.o
obj-$(CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH) += snd-soc-acp-da7219mx98357-mach.o
obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o
obj-$(CONFIG_SND_SOC_AMD_ST_ES8336_MACH) += snd-soc-acp-es8336-mach.o
obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/
obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o
obj-$(CONFIG_SND_SOC_AMD_RENOIR) += renoir/

View File

@ -130,4 +130,34 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[] = {
};
EXPORT_SYMBOL(snd_soc_acpi_amd_sof_machines);
struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[] = {
{
.id = "AMDI1019",
.drv_name = "rmb-dsp",
.pdata = &acp_quirk_data,
.fw_filename = "sof-rmb.ri",
.sof_tplg_filename = "sof-acp-rmb.tplg",
},
{
.id = "10508825",
.drv_name = "nau8825-max",
.pdata = &acp_quirk_data,
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &amp_max,
.fw_filename = "sof-rmb.ri",
.sof_tplg_filename = "sof-rmb-nau8825-max98360.tplg",
},
{
.id = "RTL5682",
.drv_name = "rt5682s-hs-rt1019",
.pdata = &acp_quirk_data,
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &amp_rt1019,
.fw_filename = "sof-rmb.ri",
.sof_tplg_filename = "sof-rmb-rt5682s-rt1019.tplg",
},
{},
};
EXPORT_SYMBOL(snd_soc_acpi_amd_rmb_sof_machines);
MODULE_LICENSE("Dual BSD/GPL");

318
sound/soc/amd/acp-es8336.c Normal file
View File

@ -0,0 +1,318 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Machine driver for AMD Stoney platform using ES8336 Codec
*
* Copyright 2022 Advanced Micro Devices, Inc.
*/
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include "acp.h"
#define DUAL_CHANNEL 2
#define DRV_NAME "acp2x_mach"
#define ST_JADEITE 1
#define ES8336_PLL_FREQ (48000 * 256)
static unsigned long acp2x_machine_id;
static struct snd_soc_jack st_jack;
static struct device *codec_dev;
static struct gpio_desc *gpio_pa;
static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
if (SND_SOC_DAPM_EVENT_ON(event))
gpiod_set_value_cansleep(gpio_pa, true);
else
gpiod_set_value_cansleep(gpio_pa, false);
return 0;
}
static struct snd_soc_jack_pin st_es8316_jack_pins[] = {
{
.pin = "Headphone",
.mask = SND_JACK_HEADPHONE,
},
{
.pin = "Headset Mic",
.mask = SND_JACK_MICROPHONE,
},
};
static int st_es8336_init(struct snd_soc_pcm_runtime *rtd)
{
int ret;
struct snd_soc_card *card;
struct snd_soc_component *codec;
codec = asoc_rtd_to_codec(rtd, 0)->component;
card = rtd->card;
ret = snd_soc_card_jack_new_pins(card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0,
&st_jack, st_es8316_jack_pins,
ARRAY_SIZE(st_es8316_jack_pins));
if (ret) {
dev_err(card->dev, "HP jack creation failed %d\n", ret);
return ret;
}
snd_jack_set_key(st_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
ret = snd_soc_component_set_jack(codec, &st_jack, NULL);
if (ret) {
dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
return ret;
}
return 0;
}
static const unsigned int st_channels[] = {
DUAL_CHANNEL,
};
static const unsigned int st_rates[] = {
48000,
};
static const struct snd_pcm_hw_constraint_list st_constraints_rates = {
.count = ARRAY_SIZE(st_rates),
.list = st_rates,
.mask = 0,
};
static const struct snd_pcm_hw_constraint_list st_constraints_channels = {
.count = ARRAY_SIZE(st_channels),
.list = st_channels,
.mask = 0,
};
static int st_es8336_codec_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime;
struct snd_soc_pcm_runtime *rtd;
struct snd_soc_card *card;
struct acp_platform_info *machine;
struct snd_soc_dai *codec_dai;
int ret;
runtime = substream->runtime;
rtd = asoc_substream_to_rtd(substream);
card = rtd->card;
machine = snd_soc_card_get_drvdata(card);
codec_dai = asoc_rtd_to_codec(rtd, 0);
ret = snd_soc_dai_set_sysclk(codec_dai, 0, ES8336_PLL_FREQ, SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
return ret;
}
runtime->hw.channels_max = DUAL_CHANNEL;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
&st_constraints_channels);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&st_constraints_rates);
machine->play_i2s_instance = I2S_MICSP_INSTANCE;
machine->cap_i2s_instance = I2S_MICSP_INSTANCE;
machine->capture_channel = CAP_CHANNEL0;
return 0;
}
static const struct snd_soc_ops st_es8336_ops = {
.startup = st_es8336_codec_startup,
};
SND_SOC_DAILINK_DEF(designware1,
DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.2.auto")));
SND_SOC_DAILINK_DEF(codec,
DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi")));
SND_SOC_DAILINK_DEF(platform,
DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.1.auto")));
static struct snd_soc_dai_link st_dai_es8336[] = {
{
.name = "amdes8336",
.stream_name = "ES8336 HiFi Play",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
.stop_dma_first = 1,
.dpcm_capture = 1,
.dpcm_playback = 1,
.init = st_es8336_init,
.ops = &st_es8336_ops,
SND_SOC_DAILINK_REG(designware1, codec, platform),
},
};
static const struct snd_soc_dapm_widget st_widgets[] = {
SND_SOC_DAPM_SPK("Speaker", NULL),
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Internal Mic", NULL),
SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
sof_es8316_speaker_power_event,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
};
static const struct snd_soc_dapm_route st_audio_route[] = {
{"Speaker", NULL, "HPOL"},
{"Speaker", NULL, "HPOR"},
{"Headphone", NULL, "HPOL"},
{"Headphone", NULL, "HPOR"},
{"MIC1", NULL, "Headset Mic"},
{"MIC2", NULL, "Internal Mic"},
{"Speaker", NULL, "Speaker Power"},
};
static const struct snd_kcontrol_new st_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Speaker"),
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Internal Mic"),
};
static const struct acpi_gpio_params pa_enable_gpio = { 0, 0, false };
static const struct acpi_gpio_mapping acpi_es8336_gpios[] = {
{ "pa-enable-gpios", &pa_enable_gpio, 1 },
{ }
};
static int st_es8336_late_probe(struct snd_soc_card *card)
{
struct acpi_device *adev;
int ret;
adev = acpi_dev_get_first_match_dev("ESSX8336", NULL, -1);
if (adev)
put_device(&adev->dev);
codec_dev = acpi_get_first_physical_node(adev);
if (!codec_dev)
dev_err(card->dev, "can not find codec dev\n");
ret = devm_acpi_dev_add_driver_gpios(codec_dev, acpi_es8336_gpios);
if (ret)
dev_warn(card->dev, "Failed to add driver gpios\n");
gpio_pa = gpiod_get_optional(codec_dev, "pa-enable", GPIOD_OUT_LOW);
if (IS_ERR(gpio_pa)) {
ret = dev_err_probe(card->dev, PTR_ERR(gpio_pa),
"could not get pa-enable GPIO\n");
put_device(codec_dev);
return ret;
}
return 0;
}
static struct snd_soc_card st_card = {
.name = "acpes8336",
.owner = THIS_MODULE,
.dai_link = st_dai_es8336,
.num_links = ARRAY_SIZE(st_dai_es8336),
.dapm_widgets = st_widgets,
.num_dapm_widgets = ARRAY_SIZE(st_widgets),
.dapm_routes = st_audio_route,
.num_dapm_routes = ARRAY_SIZE(st_audio_route),
.controls = st_mc_controls,
.num_controls = ARRAY_SIZE(st_mc_controls),
.late_probe = st_es8336_late_probe,
};
static int st_es8336_quirk_cb(const struct dmi_system_id *id)
{
acp2x_machine_id = ST_JADEITE;
return 1;
}
static const struct dmi_system_id st_es8336_quirk_table[] = {
{
.callback = st_es8336_quirk_cb,
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMD"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jadeite"),
},
},
{
.callback = st_es8336_quirk_cb,
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "IP3 Technology CO.,Ltd."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ASN1D"),
},
},
{
.callback = st_es8336_quirk_cb,
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Standard"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ASN10"),
},
},
{}
};
static int st_es8336_probe(struct platform_device *pdev)
{
int ret;
struct snd_soc_card *card;
struct acp_platform_info *machine;
machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info), GFP_KERNEL);
if (!machine)
return -ENOMEM;
dmi_check_system(st_es8336_quirk_table);
switch (acp2x_machine_id) {
case ST_JADEITE:
card = &st_card;
st_card.dev = &pdev->dev;
break;
default:
return -ENODEV;
}
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, machine);
ret = devm_snd_soc_register_card(&pdev->dev, &st_card);
if (ret) {
return dev_err_probe(&pdev->dev, ret,
"devm_snd_soc_register_card(%s) failed\n",
card->name);
}
return 0;
}
#ifdef CONFIG_ACPI
static const struct acpi_device_id st_audio_acpi_match[] = {
{"AMDI8336", 0},
{},
};
MODULE_DEVICE_TABLE(acpi, st_audio_acpi_match);
#endif
static struct platform_driver st_mach_driver = {
.driver = {
.name = "st-es8316",
.acpi_match_table = ACPI_PTR(st_audio_acpi_match),
.pm = &snd_soc_pm_ops,
},
.probe = st_es8336_probe,
};
module_platform_driver(st_mach_driver);
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
MODULE_DESCRIPTION("st-es8316 audio support");
MODULE_LICENSE("GPL v2");

View File

@ -433,6 +433,7 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num, bool is_circular)
case I2S_TO_ACP_DMA_CH_NUM:
case ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM:
case I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM:
case ACP_TO_I2S_DMA_MICSP_INSTANCE_CH_NUM:
dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
break;
default:
@ -710,6 +711,13 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
if ((intr_flag & BIT(ACP_TO_I2S_DMA_MICSP_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->play_i2s_micsp_stream);
acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_MICSP_INSTANCE_CH_NUM)) << 16,
acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
if ((intr_flag & BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->play_i2sbt_stream);
@ -807,7 +815,8 @@ static int acp_dma_open(struct snd_soc_component *component,
* stream is not closed
*/
if (!intr_data->play_i2ssp_stream && !intr_data->capture_i2ssp_stream &&
!intr_data->play_i2sbt_stream && !intr_data->capture_i2sbt_stream)
!intr_data->play_i2sbt_stream && !intr_data->capture_i2sbt_stream &&
!intr_data->play_i2s_micsp_stream)
acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@ -867,6 +876,9 @@ static int acp_dma_hw_params(struct snd_soc_component *component,
case I2S_BT_INSTANCE:
val |= ACP_I2S_BT_16BIT_RESOLUTION_EN;
break;
case I2S_MICSP_INSTANCE:
val |= ACP_I2S_MICSP_16BIT_RESOLUTION_EN;
break;
case I2S_SP_INSTANCE:
default:
val |= ACP_I2S_SP_16BIT_RESOLUTION_EN;
@ -876,6 +888,7 @@ static int acp_dma_hw_params(struct snd_soc_component *component,
case I2S_BT_INSTANCE:
val |= ACP_I2S_BT_16BIT_RESOLUTION_EN;
break;
case I2S_MICSP_INSTANCE:
case I2S_SP_INSTANCE:
default:
val |= ACP_I2S_MIC_16BIT_RESOLUTION_EN;
@ -901,6 +914,27 @@ static int acp_dma_hw_params(struct snd_soc_component *component,
mmACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW;
adata->play_i2sbt_stream = substream;
break;
case I2S_MICSP_INSTANCE:
switch (adata->asic_type) {
case CHIP_STONEY:
rtd->pte_offset = ACP_ST_PLAYBACK_PTE_OFFSET;
break;
default:
rtd->pte_offset = ACP_PLAYBACK_PTE_OFFSET;
}
rtd->ch1 = SYSRAM_TO_ACP_MICSP_INSTANCE_CH_NUM;
rtd->ch2 = ACP_TO_I2S_DMA_MICSP_INSTANCE_CH_NUM;
rtd->sram_bank = ACP_SRAM_BANK_1_ADDRESS;
rtd->destination = TO_ACP_I2S_2;
rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH4;
rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH5;
rtd->byte_cnt_high_reg_offset =
mmACP_I2S_MICSP_TRANSMIT_BYTE_CNT_HIGH;
rtd->byte_cnt_low_reg_offset =
mmACP_I2S_MICSP_TRANSMIT_BYTE_CNT_LOW;
adata->play_i2s_micsp_stream = substream;
break;
case I2S_SP_INSTANCE:
default:
switch (adata->asic_type) {
@ -939,6 +973,7 @@ static int acp_dma_hw_params(struct snd_soc_component *component,
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
adata->capture_i2sbt_stream = substream;
break;
case I2S_MICSP_INSTANCE:
case I2S_SP_INSTANCE:
default:
rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
@ -1160,6 +1195,9 @@ static int acp_dma_close(struct snd_soc_component *component,
case I2S_BT_INSTANCE:
adata->play_i2sbt_stream = NULL;
break;
case I2S_MICSP_INSTANCE:
adata->play_i2s_micsp_stream = NULL;
break;
case I2S_SP_INSTANCE:
default:
adata->play_i2ssp_stream = NULL;
@ -1181,6 +1219,7 @@ static int acp_dma_close(struct snd_soc_component *component,
case I2S_BT_INSTANCE:
adata->capture_i2sbt_stream = NULL;
break;
case I2S_MICSP_INSTANCE:
case I2S_SP_INSTANCE:
default:
adata->capture_i2ssp_stream = NULL;
@ -1197,7 +1236,8 @@ static int acp_dma_close(struct snd_soc_component *component,
* another stream is also not active.
*/
if (!adata->play_i2ssp_stream && !adata->capture_i2ssp_stream &&
!adata->play_i2sbt_stream && !adata->capture_i2sbt_stream)
!adata->play_i2sbt_stream && !adata->capture_i2sbt_stream &&
!adata->play_i2s_micsp_stream)
acp_reg_write(0, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB);
kfree(rtd);
return 0;
@ -1245,6 +1285,7 @@ static int acp_audio_probe(struct platform_device *pdev)
audio_drv_data->capture_i2ssp_stream = NULL;
audio_drv_data->play_i2sbt_stream = NULL;
audio_drv_data->capture_i2sbt_stream = NULL;
audio_drv_data->play_i2s_micsp_stream = NULL;
audio_drv_data->asic_type = *pdata;
@ -1333,6 +1374,11 @@ static int acp_pcm_resume(struct device *dev)
config_acp_dma(adata->acp_mmio, rtd, adata->asic_type);
}
if (adata->asic_type != CHIP_CARRIZO) {
if (adata->play_i2s_micsp_stream &&
adata->play_i2s_micsp_stream->runtime) {
rtd = adata->play_i2s_micsp_stream->runtime->private_data;
config_acp_dma(adata->acp_mmio, rtd, adata->asic_type);
}
if (adata->play_i2sbt_stream &&
adata->play_i2sbt_stream->runtime) {
rtd = adata->play_i2sbt_stream->runtime->private_data;

View File

@ -55,6 +55,7 @@
#define I2S_SP_INSTANCE 0x01
#define I2S_BT_INSTANCE 0x02
#define I2S_MICSP_INSTANCE 0x03
#define CAP_CHANNEL0 0x00
#define CAP_CHANNEL1 0x01
@ -85,6 +86,10 @@
#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 10
#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 11
/* Playback DMA channels for I2S MICSP instance */
#define SYSRAM_TO_ACP_MICSP_INSTANCE_CH_NUM 4
#define ACP_TO_I2S_DMA_MICSP_INSTANCE_CH_NUM 5
#define NUM_DSCRS_PER_CHANNEL 2
#define PLAYBACK_START_DMA_DESCR_CH12 0
@ -108,8 +113,15 @@
#define CAPTURE_START_DMA_DESCR_CH11 14
#define CAPTURE_END_DMA_DESCR_CH11 15
/* I2S MICSP Instance DMA Descriptors */
#define PLAYBACK_START_DMA_DESCR_CH4 0
#define PLAYBACK_END_DMA_DESCR_CH4 1
#define PLAYBACK_START_DMA_DESCR_CH5 2
#define PLAYBACK_END_DMA_DESCR_CH5 3
#define mmACP_I2S_16BIT_RESOLUTION_EN 0x5209
#define ACP_I2S_MIC_16BIT_RESOLUTION_EN 0x01
#define ACP_I2S_MICSP_16BIT_RESOLUTION_EN 0x01
#define ACP_I2S_SP_16BIT_RESOLUTION_EN 0x02
#define ACP_I2S_BT_16BIT_RESOLUTION_EN 0x04
#define ACP_BT_UART_PAD_SELECT_MASK 0x1
@ -149,6 +161,7 @@ struct audio_drv_data {
struct snd_pcm_substream *capture_i2ssp_stream;
struct snd_pcm_substream *play_i2sbt_stream;
struct snd_pcm_substream *capture_i2sbt_stream;
struct snd_pcm_substream *play_i2s_micsp_stream;
void __iomem *acp_mmio;
u32 asic_type;
snd_pcm_sframes_t delay;

View File

@ -40,6 +40,17 @@ config SND_AMD_ASOC_RENOIR
help
This option enables Renoir I2S support on AMD platform.
config SND_AMD_ASOC_REMBRANDT
tristate "AMD ACP ASOC Rembrandt Support"
select SND_SOC_AMD_ACP_PCM
select SND_SOC_AMD_ACP_I2S
select SND_SOC_AMD_ACP_PDM
depends on X86 && PCI
help
This option enables Rembrandt I2S support on AMD platform.
Say Y if you want to enable AUDIO on Rembrandt
If unsure select "N".
config SND_SOC_AMD_MACH_COMMON
tristate
depends on X86 && PCI && I2C
@ -49,6 +60,7 @@ config SND_SOC_AMD_MACH_COMMON
select SND_SOC_RT1019
select SND_SOC_MAX98357A
select SND_SOC_RT5682S
select SND_SOC_NAU8825
help
This option enables common Machine driver module for ACP.

View File

@ -12,6 +12,7 @@ snd-acp-pci-objs := acp-pci.o
#platform specific driver
snd-acp-renoir-objs := acp-renoir.o
snd-acp-rembrandt-objs := acp-rembrandt.o
#machine specific driver
snd-acp-mach-objs := acp-mach-common.o
@ -24,6 +25,7 @@ obj-$(CONFIG_SND_SOC_AMD_ACP_PDM) += snd-acp-pdm.o
obj-$(CONFIG_SND_SOC_AMD_ACP_PCI) += snd-acp-pci.o
obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
obj-$(CONFIG_SND_AMD_ASOC_REMBRANDT) += snd-acp-rembrandt.o
obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o

View File

@ -30,11 +30,14 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
{
struct device *dev = dai->component->dev;
struct acp_dev_data *adata;
struct acp_resource *rsrc;
u32 val;
u32 xfer_resolution;
u32 reg_val;
u32 lrclk_div_val, bclk_div_val;
adata = snd_soc_dai_get_drvdata(dai);
rsrc = adata->rsrc;
/* These values are as per Hardware Spec */
switch (params_format(params)) {
@ -63,6 +66,9 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
case I2S_SP_INSTANCE:
reg_val = ACP_I2STDM_ITER;
break;
case I2S_HS_INSTANCE:
reg_val = ACP_HSTDM_ITER;
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
return -EINVAL;
@ -75,6 +81,9 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
case I2S_SP_INSTANCE:
reg_val = ACP_I2STDM_IRER;
break;
case I2S_HS_INSTANCE:
reg_val = ACP_HSTDM_IRER;
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
return -EINVAL;
@ -86,6 +95,74 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
val = val | (xfer_resolution << 3);
writel(val, adata->acp_base + reg_val);
if (rsrc->soc_mclk) {
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
switch (params_rate(params)) {
case 8000:
bclk_div_val = 768;
break;
case 16000:
bclk_div_val = 384;
break;
case 24000:
bclk_div_val = 256;
break;
case 32000:
bclk_div_val = 192;
break;
case 44100:
case 48000:
bclk_div_val = 128;
break;
case 88200:
case 96000:
bclk_div_val = 64;
break;
case 192000:
bclk_div_val = 32;
break;
default:
return -EINVAL;
}
lrclk_div_val = 32;
break;
case SNDRV_PCM_FORMAT_S32_LE:
switch (params_rate(params)) {
case 8000:
bclk_div_val = 384;
break;
case 16000:
bclk_div_val = 192;
break;
case 24000:
bclk_div_val = 128;
break;
case 32000:
bclk_div_val = 96;
break;
case 44100:
case 48000:
bclk_div_val = 64;
break;
case 88200:
case 96000:
bclk_div_val = 32;
break;
case 192000:
bclk_div_val = 16;
break;
default:
return -EINVAL;
}
lrclk_div_val = 64;
break;
default:
return -EINVAL;
}
adata->lrclk_div = lrclk_div_val;
adata->bclk_div = bclk_div_val;
}
return 0;
}
@ -94,6 +171,7 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
struct acp_stream *stream = substream->runtime->private_data;
struct device *dev = dai->component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
struct acp_resource *rsrc = adata->rsrc;
u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg;
period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size);
@ -118,6 +196,12 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
ier_val = ACP_I2STDM_IER;
buf_reg = ACP_I2S_TX_RINGBUFSIZE;
break;
case I2S_HS_INSTANCE:
water_val = ACP_HS_TX_INTR_WATERMARK_SIZE;
reg_val = ACP_HSTDM_ITER;
ier_val = ACP_HSTDM_IER;
buf_reg = ACP_HS_TX_RINGBUFSIZE;
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
return -EINVAL;
@ -136,6 +220,12 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
ier_val = ACP_I2STDM_IER;
buf_reg = ACP_I2S_RX_RINGBUFSIZE;
break;
case I2S_HS_INSTANCE:
water_val = ACP_HS_RX_INTR_WATERMARK_SIZE;
reg_val = ACP_HSTDM_IRER;
ier_val = ACP_HSTDM_IER;
buf_reg = ACP_HS_RX_RINGBUFSIZE;
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
return -EINVAL;
@ -147,6 +237,8 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
val = val | BIT(0);
writel(val, adata->acp_base + reg_val);
writel(1, adata->acp_base + ier_val);
if (rsrc->soc_mclk)
acp_set_i2s_clk(adata, dai->driver->id);
return 0;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
@ -159,6 +251,9 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
case I2S_SP_INSTANCE:
reg_val = ACP_I2STDM_ITER;
break;
case I2S_HS_INSTANCE:
reg_val = ACP_HSTDM_ITER;
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
return -EINVAL;
@ -172,6 +267,9 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
case I2S_SP_INSTANCE:
reg_val = ACP_I2STDM_IRER;
break;
case I2S_HS_INSTANCE:
reg_val = ACP_HSTDM_IRER;
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
return -EINVAL;
@ -187,6 +285,9 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) &&
!(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0)))
writel(0, adata->acp_base + ACP_I2STDM_IER);
if (!(readl(adata->acp_base + ACP_HSTDM_ITER) & BIT(0)) &&
!(readl(adata->acp_base + ACP_HSTDM_IRER) & BIT(0)))
writel(0, adata->acp_base + ACP_HSTDM_IER);
return 0;
default:
return -EINVAL;
@ -199,6 +300,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
{
struct device *dev = dai->component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
struct acp_resource *rsrc = adata->rsrc;
struct acp_stream *stream = substream->runtime->private_data;
u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
@ -208,7 +310,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
case I2S_SP_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
reg_dma_size = ACP_I2S_TX_DMA_SIZE;
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
acp_fifo_addr = rsrc->sram_pte_offset +
SP_PB_FIFO_ADDR_OFFSET;
reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
@ -217,7 +319,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
} else {
reg_dma_size = ACP_I2S_RX_DMA_SIZE;
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
acp_fifo_addr = rsrc->sram_pte_offset +
SP_CAPT_FIFO_ADDR_OFFSET;
reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
@ -228,7 +330,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
case I2S_BT_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
reg_dma_size = ACP_BT_TX_DMA_SIZE;
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
acp_fifo_addr = rsrc->sram_pte_offset +
BT_PB_FIFO_ADDR_OFFSET;
reg_fifo_addr = ACP_BT_TX_FIFOADDR;
reg_fifo_size = ACP_BT_TX_FIFOSIZE;
@ -237,7 +339,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
} else {
reg_dma_size = ACP_BT_RX_DMA_SIZE;
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
acp_fifo_addr = rsrc->sram_pte_offset +
BT_CAPT_FIFO_ADDR_OFFSET;
reg_fifo_addr = ACP_BT_RX_FIFOADDR;
reg_fifo_size = ACP_BT_RX_FIFOSIZE;
@ -246,6 +348,27 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
}
break;
case I2S_HS_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
reg_dma_size = ACP_HS_TX_DMA_SIZE;
acp_fifo_addr = rsrc->sram_pte_offset +
HS_PB_FIFO_ADDR_OFFSET;
reg_fifo_addr = ACP_HS_TX_FIFOADDR;
reg_fifo_size = ACP_HS_TX_FIFOSIZE;
phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
} else {
reg_dma_size = ACP_HS_RX_DMA_SIZE;
acp_fifo_addr = rsrc->sram_pte_offset +
HS_CAPT_FIFO_ADDR_OFFSET;
reg_fifo_addr = ACP_HS_RX_FIFOADDR;
reg_fifo_size = ACP_HS_RX_FIFOSIZE;
phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
}
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
return -EINVAL;
@ -255,11 +378,15 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
ext_int_ctrl |= BIT(I2S_RX_THRESHOLD) | BIT(BT_RX_THRESHOLD)
| BIT(I2S_TX_THRESHOLD) | BIT(BT_TX_THRESHOLD);
ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
BIT(BT_RX_THRESHOLD(rsrc->offset)) |
BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
BIT(BT_TX_THRESHOLD(rsrc->offset)) |
BIT(HS_RX_THRESHOLD(rsrc->offset)) |
BIT(HS_TX_THRESHOLD(rsrc->offset));
writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
return 0;
}
@ -268,32 +395,45 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
{
struct acp_stream *stream = substream->runtime->private_data;
struct device *dev = dai->component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
struct acp_resource *rsrc = adata->rsrc;
unsigned int dir = substream->stream;
unsigned int irq_bit = 0;
switch (dai->driver->id) {
case I2S_SP_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
irq_bit = BIT(I2S_TX_THRESHOLD);
irq_bit = BIT(I2S_TX_THRESHOLD(rsrc->offset));
stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET;
stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET;
} else {
irq_bit = BIT(I2S_RX_THRESHOLD);
irq_bit = BIT(I2S_RX_THRESHOLD(rsrc->offset));
stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET;
stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET;
}
break;
case I2S_BT_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
irq_bit = BIT(BT_TX_THRESHOLD);
irq_bit = BIT(BT_TX_THRESHOLD(rsrc->offset));
stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET;
stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET;
} else {
irq_bit = BIT(BT_RX_THRESHOLD);
irq_bit = BIT(BT_RX_THRESHOLD(rsrc->offset));
stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET;
stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET;
}
break;
case I2S_HS_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
irq_bit = BIT(HS_TX_THRESHOLD(rsrc->offset));
stream->pte_offset = ACP_SRAM_HS_PB_PTE_OFFSET;
stream->fifo_offset = HS_PB_FIFO_ADDR_OFFSET;
} else {
irq_bit = BIT(HS_RX_THRESHOLD(rsrc->offset));
stream->pte_offset = ACP_SRAM_HS_CP_PTE_OFFSET;
stream->fifo_offset = HS_CAPT_FIFO_ADDR_OFFSET;
}
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
return -EINVAL;
@ -319,6 +459,7 @@ int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
{
struct device *dev = dai->component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
struct acp_resource *rsrc = adata->rsrc;
unsigned int val;
if (!adata->acp_base) {
@ -326,8 +467,8 @@ int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
return -EINVAL;
}
val = readl(adata->acp_base + ACP_I2S_PIN_CONFIG);
if (val != I2S_MODE) {
val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
if (val != rsrc->i2s_mode) {
dev_err(dev, "I2S Mode not supported val %x\n", val);
return -EINVAL;
}

View File

@ -47,6 +47,28 @@ static struct acp_card_drvdata rt5682s_rt1019_data = {
.dmic_codec_id = DMIC,
};
static struct acp_card_drvdata max_nau8825_data = {
.hs_cpu_id = I2S_HS,
.amp_cpu_id = I2S_HS,
.dmic_cpu_id = DMIC,
.hs_codec_id = NAU8825,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.soc_mclk = true,
.platform = REMBRANDT,
};
static struct acp_card_drvdata rt5682s_rt1019_rmb_data = {
.hs_cpu_id = I2S_HS,
.amp_cpu_id = I2S_HS,
.dmic_cpu_id = DMIC,
.hs_codec_id = RT5682S,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.soc_mclk = true,
.platform = REMBRANDT,
};
static const struct snd_kcontrol_new acp_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
@ -112,6 +134,14 @@ static const struct platform_device_id board_ids[] = {
.name = "acp3xalc5682s1019",
.driver_data = (kernel_ulong_t)&rt5682s_rt1019_data,
},
{
.name = "rmb-nau8825-max",
.driver_data = (kernel_ulong_t)&max_nau8825_data,
},
{
.name = "rmb-rt5682s-rt1019",
.driver_data = (kernel_ulong_t)&rt5682s_rt1019_rmb_data,
},
{ }
};
static struct platform_driver acp_asoc_audio = {
@ -130,4 +160,6 @@ MODULE_DESCRIPTION("ACP chrome audio support");
MODULE_ALIAS("platform:acp3xalc56821019");
MODULE_ALIAS("platform:acp3xalc5682sm98360");
MODULE_ALIAS("platform:acp3xalc5682s1019");
MODULE_ALIAS("platform:rmb-nau8825-max");
MODULE_ALIAS("platform:rmb-rt5682s-rt1019");
MODULE_LICENSE("GPL v2");

View File

@ -24,6 +24,7 @@
#include "../../codecs/rt5682.h"
#include "../../codecs/rt1019.h"
#include "../../codecs/rt5682s.h"
#include "../../codecs/nau8825.h"
#include "acp-mach.h"
#define PCO_PLAT_CLK 48000000
@ -148,9 +149,14 @@ static int acp_card_hs_startup(struct snd_pcm_substream *substream)
struct acp_card_drvdata *drvdata = card->drvdata;
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
int ret;
unsigned int fmt;
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP);
if (drvdata->soc_mclk)
fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
else
fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
ret = snd_soc_dai_set_fmt(codec_dai, fmt);
if (ret < 0) {
dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
return ret;
@ -161,10 +167,13 @@ static int acp_card_hs_startup(struct snd_pcm_substream *substream)
&constraints_channels);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
ret = acp_clk_enable(drvdata);
if (ret < 0)
dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);
if (!drvdata->soc_mclk) {
ret = acp_clk_enable(drvdata);
if (ret < 0) {
dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);
return ret;
}
}
return ret;
}
@ -175,7 +184,8 @@ static void acp_card_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata;
clk_disable_unprepare(drvdata->wclk);
if (!drvdata->soc_mclk)
clk_disable_unprepare(drvdata->wclk);
}
static const struct snd_soc_ops acp_card_rt5682_ops = {
@ -199,6 +209,7 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
struct acp_card_drvdata *drvdata = card->drvdata;
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_component *component = codec_dai->component;
unsigned int fmt;
int ret;
dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
@ -206,8 +217,12 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
if (drvdata->hs_codec_id != RT5682S)
return -EINVAL;
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP);
if (drvdata->soc_mclk)
fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
else
fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
ret = snd_soc_dai_set_fmt(codec_dai, fmt);
if (ret < 0) {
dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
return ret;
@ -234,8 +249,10 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
if (!drvdata->soc_mclk) {
drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
}
ret = snd_soc_card_jack_new(card, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_LINEOUT |
@ -363,7 +380,7 @@ static int acp_card_amp_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata;
int ret;
int ret = 0;
runtime->hw.channels_max = DUAL_CHANNEL;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
@ -371,10 +388,13 @@ static int acp_card_amp_startup(struct snd_pcm_substream *substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
ret = acp_clk_enable(drvdata);
if (ret < 0)
dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
if (!drvdata->soc_mclk) {
ret = acp_clk_enable(drvdata);
if (ret < 0) {
dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
return ret;
}
}
return ret;
}
@ -409,6 +429,104 @@ static const struct snd_soc_ops acp_card_maxim_ops = {
.shutdown = acp_card_shutdown,
};
/* Declare nau8825 codec components */
SND_SOC_DAILINK_DEF(nau8825,
DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", "nau8825-hifi")));
static const struct snd_soc_dapm_route nau8825_map[] = {
{ "Headphone Jack", NULL, "HPOL" },
{ "Headphone Jack", NULL, "HPOR" },
};
static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata;
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_component *component = codec_dai->component;
unsigned int fmt;
int ret;
dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
if (drvdata->hs_codec_id != NAU8825)
return -EINVAL;
if (drvdata->soc_mclk)
fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
else
fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
ret = snd_soc_dai_set_fmt(codec_dai, fmt);
if (ret < 0) {
dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
return ret;
}
ret = snd_soc_card_jack_new(card, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_LINEOUT |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&pco_jack);
if (ret) {
dev_err(card->dev, "HP jack creation failed %d\n", ret);
return ret;
}
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
if (ret) {
dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
return ret;
}
return snd_soc_dapm_add_routes(&rtd->card->dapm, nau8825_map, ARRAY_SIZE(nau8825_map));
}
static int acp_nau8825_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
int ret;
ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_FS,
(48000 * 256), SND_SOC_CLOCK_IN);
if (ret < 0)
dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
ret = snd_soc_dai_set_pll(codec_dai, 0, 0, params_rate(params),
params_rate(params) * 256);
if (ret < 0) {
dev_err(rtd->dev, "can't set FLL: %d\n", ret);
return ret;
}
return ret;
}
static int acp_nau8825_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw.channels_max = 2;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
return 0;
}
static const struct snd_soc_ops acp_card_nau8825_ops = {
.startup = acp_nau8825_startup,
.hw_params = acp_nau8825_hw_params,
};
/* Declare DMIC codec components */
SND_SOC_DAILINK_DEF(dmic_codec,
DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
@ -427,6 +545,12 @@ static struct snd_soc_dai_link_component platform_component[] = {
}
};
static struct snd_soc_dai_link_component platform_rmb_component[] = {
{
.name = "acp_asoc_rembrandt.0",
}
};
static struct snd_soc_dai_link_component sof_component[] = {
{
.name = "0000:04:00.5",
@ -435,8 +559,12 @@ static struct snd_soc_dai_link_component sof_component[] = {
SND_SOC_DAILINK_DEF(i2s_sp,
DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));
SND_SOC_DAILINK_DEF(i2s_hs,
DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-hs")));
SND_SOC_DAILINK_DEF(sof_sp,
DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
SND_SOC_DAILINK_DEF(sof_hs,
DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs")));
SND_SOC_DAILINK_DEF(sof_dmic,
DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
SND_SOC_DAILINK_DEF(pdm_dmic,
@ -491,6 +619,37 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
i++;
}
if (drv_data->hs_cpu_id == I2S_HS) {
links[i].name = "acp-headset-codec";
links[i].id = HEADSET_BE_ID;
links[i].cpus = sof_hs;
links[i].num_cpus = ARRAY_SIZE(sof_hs);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
links[i].dpcm_playback = 1;
links[i].dpcm_capture = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->hs_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = dummy_codec;
links[i].num_codecs = ARRAY_SIZE(dummy_codec);
}
if (drv_data->hs_codec_id == NAU8825) {
links[i].codecs = nau8825;
links[i].num_codecs = ARRAY_SIZE(nau8825);
links[i].init = acp_card_nau8825_init;
links[i].ops = &acp_card_nau8825_ops;
}
if (drv_data->hs_codec_id == RT5682S) {
links[i].codecs = rt5682s;
links[i].num_codecs = ARRAY_SIZE(rt5682s);
links[i].init = acp_card_rt5682s_init;
links[i].ops = &acp_card_rt5682s_ops;
}
i++;
}
if (drv_data->amp_cpu_id == I2S_SP) {
links[i].name = "acp-amp-codec";
links[i].id = AMP_BE_ID;
@ -523,6 +682,38 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
i++;
}
if (drv_data->amp_cpu_id == I2S_HS) {
links[i].name = "acp-amp-codec";
links[i].id = AMP_BE_ID;
links[i].cpus = sof_hs;
links[i].num_cpus = ARRAY_SIZE(sof_hs);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
links[i].dpcm_playback = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->amp_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = dummy_codec;
links[i].num_codecs = ARRAY_SIZE(dummy_codec);
}
if (drv_data->amp_codec_id == MAX98360A) {
links[i].codecs = max98360a;
links[i].num_codecs = ARRAY_SIZE(max98360a);
links[i].ops = &acp_card_maxim_ops;
links[i].init = acp_card_maxim_init;
}
if (drv_data->amp_codec_id == RT1019) {
links[i].codecs = rt1019;
links[i].num_codecs = ARRAY_SIZE(rt1019);
links[i].ops = &acp_card_rt1019_ops;
links[i].init = acp_card_rt1019_init;
card->codec_conf = rt1019_conf;
card->num_configs = ARRAY_SIZE(rt1019_conf);
}
i++;
}
if (drv_data->dmic_cpu_id == DMIC) {
links[i].name = "acp-dmic-codec";
links[i].id = DMIC_BE_ID;
@ -591,6 +782,40 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
i++;
}
if (drv_data->hs_cpu_id == I2S_HS) {
links[i].name = "acp-headset-codec";
links[i].id = HEADSET_BE_ID;
links[i].cpus = i2s_hs;
links[i].num_cpus = ARRAY_SIZE(i2s_hs);
if (drv_data->platform == REMBRANDT) {
links[i].platforms = platform_rmb_component;
links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
} else {
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
}
links[i].dpcm_playback = 1;
links[i].dpcm_capture = 1;
if (!drv_data->hs_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = dummy_codec;
links[i].num_codecs = ARRAY_SIZE(dummy_codec);
}
if (drv_data->hs_codec_id == NAU8825) {
links[i].codecs = nau8825;
links[i].num_codecs = ARRAY_SIZE(nau8825);
links[i].init = acp_card_nau8825_init;
links[i].ops = &acp_card_nau8825_ops;
}
if (drv_data->hs_codec_id == RT5682S) {
links[i].codecs = rt5682s;
links[i].num_codecs = ARRAY_SIZE(rt5682s);
links[i].init = acp_card_rt5682s_init;
links[i].ops = &acp_card_rt5682s_ops;
}
i++;
}
if (drv_data->amp_cpu_id == I2S_SP) {
links[i].name = "acp-amp-codec";
links[i].id = AMP_BE_ID;
@ -621,6 +846,41 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
i++;
}
if (drv_data->amp_cpu_id == I2S_HS) {
links[i].name = "acp-amp-codec";
links[i].id = AMP_BE_ID;
links[i].cpus = i2s_hs;
links[i].num_cpus = ARRAY_SIZE(i2s_hs);
if (drv_data->platform == REMBRANDT) {
links[i].platforms = platform_rmb_component;
links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
} else {
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
}
links[i].dpcm_playback = 1;
if (!drv_data->amp_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = dummy_codec;
links[i].num_codecs = ARRAY_SIZE(dummy_codec);
}
if (drv_data->amp_codec_id == MAX98360A) {
links[i].codecs = max98360a;
links[i].num_codecs = ARRAY_SIZE(max98360a);
links[i].ops = &acp_card_maxim_ops;
links[i].init = acp_card_maxim_init;
}
if (drv_data->amp_codec_id == RT1019) {
links[i].codecs = rt1019;
links[i].num_codecs = ARRAY_SIZE(rt1019);
links[i].ops = &acp_card_rt1019_ops;
links[i].init = acp_card_rt1019_init;
card->codec_conf = rt1019_conf;
card->num_configs = ARRAY_SIZE(rt1019_conf);
}
i++;
}
if (drv_data->dmic_cpu_id == DMIC) {
links[i].name = "acp-dmic-codec";
links[i].id = DMIC_BE_ID;
@ -634,8 +894,13 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
}
links[i].cpus = pdm_dmic;
links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
if (drv_data->platform == REMBRANDT) {
links[i].platforms = platform_rmb_component;
links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
} else {
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
}
links[i].ops = &acp_card_dmic_ops;
links[i].dpcm_capture = 1;
}

View File

@ -26,6 +26,7 @@ enum be_id {
enum cpu_endpoints {
NONE = 0,
I2S_HS,
I2S_SP,
I2S_BT,
DMIC,
@ -37,6 +38,12 @@ enum codec_endpoints {
RT1019,
MAX98360A,
RT5682S,
NAU8825,
};
enum platform_end_point {
RENOIR = 0,
REMBRANDT,
};
struct acp_card_drvdata {
@ -47,8 +54,10 @@ struct acp_card_drvdata {
unsigned int amp_codec_id;
unsigned int dmic_codec_id;
unsigned int dai_fmt;
unsigned int platform;
struct clk *wclk;
struct clk *bclk;
bool soc_mclk;
};
int acp_sofdsp_dai_links_create(struct snd_soc_card *card);

View File

@ -82,6 +82,12 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
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;

View File

@ -160,9 +160,9 @@ static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
stream->reg_offset = ACP_REGION2_OFFSET;
/* Enable DMIC Interrupts */
ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
ext_int_ctrl |= PDM_DMA_INTR_MASK;
writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
return 0;
}
@ -174,10 +174,10 @@ static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream,
struct acp_dev_data *adata = dev_get_drvdata(dev);
u32 ext_int_ctrl;
/* Disable DMIC interrrupts */
ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
/* Disable DMIC interrupts */
ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
ext_int_ctrl |= ~PDM_DMA_INTR_MASK;
writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
}
const struct snd_soc_dai_ops acp_dmic_dai_ops = {

View File

@ -91,25 +91,38 @@ EXPORT_SYMBOL_NS_GPL(acp_machine_select, SND_SOC_ACP_COMMON);
static irqreturn_t i2s_irq_handler(int irq, void *data)
{
struct acp_dev_data *adata = data;
struct acp_resource *rsrc = adata->rsrc;
struct acp_stream *stream;
u16 i2s_flag = 0;
u32 val, i;
u32 val, val1, i;
if (!adata)
return IRQ_NONE;
val = readl(adata->acp_base + ACP_EXTERNAL_INTR_STAT);
if (adata->rsrc->no_of_ctrls == 2)
val1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));
val = 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)) {
writel(stream->irq_bit, adata->acp_base + ACP_EXTERNAL_INTR_STAT);
writel(stream->irq_bit,
ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
snd_pcm_period_elapsed(stream->substream);
i2s_flag = 1;
break;
}
if (adata->rsrc->no_of_ctrls == 2) {
if (stream && (val1 & stream->irq_bit)) {
writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(adata,
(rsrc->irqp_used - 1)));
snd_pcm_period_elapsed(stream->substream);
i2s_flag = 1;
break;
}
}
}
if (i2s_flag)
return IRQ_HANDLED;
@ -118,6 +131,7 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
{
struct acp_resource *rsrc = adata->rsrc;
u32 pte_reg, pte_size, reg_val;
/* Use ATU base Group5 */
@ -126,15 +140,17 @@ static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream
stream->reg_offset = 0x02000000;
/* Group Enable */
reg_val = ACP_SRAM_PTE_OFFSET;
reg_val = rsrc->sram_pte_offset;
writel(reg_val | BIT(31), adata->acp_base + pte_reg);
writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + pte_size);
writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
}
static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
{
struct acp_stream *stream = adata->stream[cpu_id];
struct snd_pcm_substream *substream = stream->substream;
struct acp_resource *rsrc = adata->rsrc;
dma_addr_t addr = substream->dma_buffer.addr;
int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
u32 low, high, val;
@ -146,9 +162,9 @@ static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
/* Load the low address of page int ACP SRAM through SRBM */
low = lower_32_bits(addr);
high = upper_32_bits(addr);
writel(low, adata->acp_base + ACP_SCRATCH_REG_0 + val);
writel(low, adata->acp_base + rsrc->scratch_reg_offset + val);
high |= BIT(31);
writel(high, adata->acp_base + ACP_SCRATCH_REG_0 + val + 4);
writel(high, adata->acp_base + rsrc->scratch_reg_offset + val + 4);
/* Move to next physically contiguous page */
val += 8;
@ -187,7 +203,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
}
runtime->private_data = stream;
writel(1, adata->acp_base + ACP_EXTERNAL_INTR_ENB);
writel(1, ACP_EXTERNAL_INTR_ENB(adata));
return ret;
}
@ -267,13 +283,14 @@ static int acp_dma_close(struct snd_soc_component *component,
}
static const struct snd_soc_component_driver acp_pcm_component = {
.name = DRV_NAME,
.open = acp_dma_open,
.close = acp_dma_close,
.hw_params = acp_dma_hw_params,
.pointer = acp_dma_pointer,
.mmap = acp_dma_mmap,
.pcm_construct = acp_dma_new,
.name = DRV_NAME,
.open = acp_dma_open,
.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,
};
int acp_platform_register(struct device *dev)

View File

@ -0,0 +1,401 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
//
// This file is provided under a dual BSD/GPLv2 license. When using or
// redistributing this file, you may do so under either license.
//
// Copyright(c) 2022 Advanced Micro Devices, Inc.
//
// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
// V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>
/*
* Hardware interface for Renoir ACP block
*/
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/io.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#include <linux/dma-mapping.h>
#include "amd.h"
#define DRV_NAME "acp_asoc_rembrandt"
#define ACP6X_PGFSM_CONTROL 0x1024
#define ACP6X_PGFSM_STATUS 0x1028
#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001
#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01
#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00
#define ACP_PGFSM_STATUS_MASK 0x03
#define ACP_POWERED_ON 0x00
#define ACP_POWER_ON_IN_PROGRESS 0x01
#define ACP_POWERED_OFF 0x02
#define ACP_POWER_OFF_IN_PROGRESS 0x03
#define ACP_ERROR_MASK 0x20000000
#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
static int rmb_acp_init(void __iomem *base);
static int rmb_acp_deinit(void __iomem *base);
static struct acp_resource rsrc = {
.offset = 0,
.no_of_ctrls = 2,
.irqp_used = 1,
.soc_mclk = true,
.irq_reg_offset = 0x1a00,
.i2s_pin_cfg_offset = 0x1440,
.i2s_mode = 0x0a,
.scratch_reg_offset = 0x12800,
.sram_pte_offset = 0x03802800,
};
static struct snd_soc_acpi_codecs amp_rt1019 = {
.num_codecs = 1,
.codecs = {"10EC1019"}
};
static struct snd_soc_acpi_codecs amp_max = {
.num_codecs = 1,
.codecs = {"MX98360A"}
};
static struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = {
{
.id = "10508825",
.drv_name = "rmb-nau8825-max",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &amp_max,
},
{
.id = "AMDI0007",
.drv_name = "rembrandt-acp",
},
{
.id = "RTL5682",
.drv_name = "rmb-rt5682s-rt1019",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &amp_rt1019,
},
{},
};
static struct snd_soc_dai_driver acp_rmb_dai[] = {
{
.name = "acp-i2s-sp",
.id = I2S_SP_INSTANCE,
.playback = {
.stream_name = "I2S SP Playback",
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
.channels_max = 8,
.rate_min = 8000,
.rate_max = 96000,
},
.capture = {
.stream_name = "I2S SP Capture",
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
.channels_max = 2,
.rate_min = 8000,
.rate_max = 48000,
},
.ops = &asoc_acp_cpu_dai_ops,
.probe = &asoc_acp_i2s_probe,
},
{
.name = "acp-i2s-bt",
.id = I2S_BT_INSTANCE,
.playback = {
.stream_name = "I2S BT Playback",
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
.channels_max = 8,
.rate_min = 8000,
.rate_max = 96000,
},
.capture = {
.stream_name = "I2S BT Capture",
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
.channels_max = 2,
.rate_min = 8000,
.rate_max = 48000,
},
.ops = &asoc_acp_cpu_dai_ops,
.probe = &asoc_acp_i2s_probe,
},
{
.name = "acp-i2s-hs",
.id = I2S_HS_INSTANCE,
.playback = {
.stream_name = "I2S HS Playback",
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
.channels_max = 8,
.rate_min = 8000,
.rate_max = 96000,
},
.capture = {
.stream_name = "I2S HS Capture",
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
.channels_max = 8,
.rate_min = 8000,
.rate_max = 48000,
},
.ops = &asoc_acp_cpu_dai_ops,
.probe = &asoc_acp_i2s_probe,
},
{
.name = "acp-pdm-dmic",
.id = DMIC_INSTANCE,
.capture = {
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.channels_min = 2,
.channels_max = 2,
.rate_min = 8000,
.rate_max = 48000,
},
.ops = &acp_dmic_dai_ops,
},
};
static int acp6x_power_on(void __iomem *base)
{
u32 val;
int timeout;
val = readl(base + ACP6X_PGFSM_STATUS);
if (val == ACP_POWERED_ON)
return 0;
if ((val & ACP_PGFSM_STATUS_MASK) !=
ACP_POWER_ON_IN_PROGRESS)
writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
base + ACP6X_PGFSM_CONTROL);
timeout = 0;
while (++timeout < 500) {
val = readl(base + ACP6X_PGFSM_STATUS);
if (!val)
return 0;
udelay(1);
}
return -ETIMEDOUT;
}
static int acp6x_power_off(void __iomem *base)
{
u32 val;
int timeout;
writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
base + ACP6X_PGFSM_CONTROL);
timeout = 0;
while (++timeout < 500) {
val = readl(base + ACP6X_PGFSM_STATUS);
if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
return 0;
udelay(1);
}
return -ETIMEDOUT;
}
static int acp6x_reset(void __iomem *base)
{
u32 val;
int timeout;
writel(1, base + ACP_SOFT_RESET);
timeout = 0;
while (++timeout < 500) {
val = readl(base + ACP_SOFT_RESET);
if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK)
break;
cpu_relax();
}
writel(0, base + ACP_SOFT_RESET);
timeout = 0;
while (++timeout < 500) {
val = readl(base + ACP_SOFT_RESET);
if (!val)
return 0;
cpu_relax();
}
return -ETIMEDOUT;
}
static void acp6x_enable_interrupts(struct acp_dev_data *adata)
{
struct acp_resource *rsrc = adata->rsrc;
u32 ext_intr_ctrl;
writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
ext_intr_ctrl |= ACP_ERROR_MASK;
writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
}
static void acp6x_disable_interrupts(struct acp_dev_data *adata)
{
struct acp_resource *rsrc = adata->rsrc;
writel(ACP_EXT_INTR_STAT_CLEAR_MASK,
ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
}
static int rmb_acp_init(void __iomem *base)
{
int ret;
/* power on */
ret = acp6x_power_on(base);
if (ret) {
pr_err("ACP power on failed\n");
return ret;
}
writel(0x01, base + ACP_CONTROL);
/* Reset */
ret = acp6x_reset(base);
if (ret) {
pr_err("ACP reset failed\n");
return ret;
}
return 0;
}
static int rmb_acp_deinit(void __iomem *base)
{
int ret = 0;
/* Reset */
ret = acp6x_reset(base);
if (ret) {
pr_err("ACP reset failed\n");
return ret;
}
writel(0x00, base + ACP_CONTROL);
/* power off */
ret = acp6x_power_off(base);
if (ret) {
pr_err("ACP power off failed\n");
return ret;
}
return 0;
}
static int rembrandt_audio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acp_chip_info *chip;
struct acp_dev_data *adata;
struct resource *res;
chip = dev_get_platdata(&pdev->dev);
if (!chip || !chip->base) {
dev_err(&pdev->dev, "ACP chip data is NULL\n");
return -ENODEV;
}
if (chip->acp_rev != ACP6X_DEV) {
dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
return -ENODEV;
}
rmb_acp_init(chip->base);
adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
if (!adata)
return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
if (!res) {
dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
return -ENODEV;
}
adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!adata->acp_base)
return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
if (!res) {
dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
return -ENODEV;
}
adata->i2s_irq = res->start;
adata->dev = dev;
adata->dai_driver = acp_rmb_dai;
adata->num_dai = ARRAY_SIZE(acp_rmb_dai);
adata->rsrc = &rsrc;
adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
acp_machine_select(adata);
dev_set_drvdata(dev, adata);
acp6x_enable_interrupts(adata);
acp_platform_register(dev);
return 0;
}
static int rembrandt_audio_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
struct acp_chip_info *chip;
chip = dev_get_platdata(&pdev->dev);
if (!chip || !chip->base) {
dev_err(&pdev->dev, "ACP chip data is NULL\n");
return -ENODEV;
}
rmb_acp_deinit(chip->base);
acp6x_disable_interrupts(adata);
acp_platform_unregister(dev);
return 0;
}
static struct platform_driver rembrandt_driver = {
.probe = rembrandt_audio_probe,
.remove = rembrandt_audio_remove,
.driver = {
.name = "acp_asoc_rembrandt",
},
};
module_platform_driver(rembrandt_driver);
MODULE_DESCRIPTION("AMD ACP Rembrandt Driver");
MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:" DRV_NAME);

View File

@ -39,6 +39,17 @@
#define ACP_ERROR_MASK 0x20000000
#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
static struct acp_resource rsrc = {
.offset = 20,
.no_of_ctrls = 1,
.irqp_used = 0,
.irq_reg_offset = 0x1800,
.i2s_pin_cfg_offset = 0x1400,
.i2s_mode = 0x04,
.scratch_reg_offset = 0x12800,
.sram_pte_offset = 0x02052800,
};
static struct snd_soc_acpi_codecs amp_rt1019 = {
.num_codecs = 1,
.codecs = {"10EC1019"}
@ -186,20 +197,24 @@ static int acp3x_reset(void __iomem *base)
return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT);
}
static void acp3x_enable_interrupts(void __iomem *base)
static void acp3x_enable_interrupts(struct acp_dev_data *adata)
{
struct acp_resource *rsrc = adata->rsrc;
u32 ext_intr_ctrl;
writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
ext_intr_ctrl |= ACP_ERROR_MASK;
writel(ext_intr_ctrl, base + ACP_EXTERNAL_INTR_CNTL);
writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
}
static void acp3x_disable_interrupts(void __iomem *base)
static void acp3x_disable_interrupts(struct acp_dev_data *adata)
{
writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + ACP_EXTERNAL_INTR_STAT);
writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
struct acp_resource *rsrc = adata->rsrc;
writel(ACP_EXT_INTR_STAT_CLEAR_MASK,
ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
}
static int rn_acp_init(void __iomem *base)
@ -218,8 +233,6 @@ static int rn_acp_init(void __iomem *base)
if (ret)
return ret;
acp3x_enable_interrupts(base);
return 0;
}
@ -227,8 +240,6 @@ static int rn_acp_deinit(void __iomem *base)
{
int ret = 0;
acp3x_disable_interrupts(base);
/* Reset */
ret = acp3x_reset(base);
if (ret)
@ -290,11 +301,13 @@ static int renoir_audio_probe(struct platform_device *pdev)
adata->dev = dev;
adata->dai_driver = acp_renoir_dai;
adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
adata->rsrc = &rsrc;
adata->machines = snd_soc_acpi_amd_acp_machines;
acp_machine_select(adata);
dev_set_drvdata(dev, adata);
acp3x_enable_interrupts(adata);
acp_platform_register(dev);
return 0;
@ -303,20 +316,17 @@ static int renoir_audio_probe(struct platform_device *pdev)
static int renoir_audio_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
struct acp_chip_info *chip;
int ret;
chip = dev_get_platdata(&pdev->dev);
if (!chip || !chip->base) {
dev_err(&pdev->dev, "ACP chip data is NULL\n");
return -ENODEV;
}
acp3x_disable_interrupts(adata);
ret = rn_acp_deinit(chip->base);
if (ret) {
dev_err(&pdev->dev, "ACP de-init Failed\n");
return -EINVAL;
}
if (ret)
dev_err(&pdev->dev, "ACP de-init Failed (%pe)\n", ERR_PTR(ret));
acp_platform_unregister(dev);
return 0;

View File

@ -56,6 +56,26 @@ static struct acp_card_drvdata sof_rt5682s_max_data = {
.dmic_codec_id = DMIC,
};
static struct acp_card_drvdata sof_nau8825_data = {
.hs_cpu_id = I2S_HS,
.amp_cpu_id = I2S_HS,
.dmic_cpu_id = DMIC,
.hs_codec_id = NAU8825,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.soc_mclk = true,
};
static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = {
.hs_cpu_id = I2S_HS,
.amp_cpu_id = I2S_HS,
.dmic_cpu_id = DMIC,
.hs_codec_id = RT5682S,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.soc_mclk = true,
};
static const struct snd_kcontrol_new acp_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
@ -124,6 +144,14 @@ static const struct platform_device_id board_ids[] = {
.name = "rt5682s-rt1019",
.driver_data = (kernel_ulong_t)&sof_rt5682s_rt1019_data
},
{
.name = "nau8825-max",
.driver_data = (kernel_ulong_t)&sof_nau8825_data
},
{
.name = "rt5682s-hs-rt1019",
.driver_data = (kernel_ulong_t)&sof_rt5682s_hs_rt1019_data
},
{ }
};
static struct platform_driver acp_asoc_audio = {
@ -143,4 +171,6 @@ MODULE_ALIAS("platform:rt5682-rt1019");
MODULE_ALIAS("platform:rt5682-max");
MODULE_ALIAS("platform:rt5682s-max");
MODULE_ALIAS("platform:rt5682s-rt1019");
MODULE_ALIAS("platform:nau8825-max");
MODULE_ALIAS("platform:rt5682s-hs-rt1019");
MODULE_LICENSE("GPL v2");

View File

@ -19,10 +19,12 @@
#include "chip_offset_byte.h"
#define ACP3X_DEV 3
#define ACP6X_DEV 6
#define I2S_SP_INSTANCE 0x00
#define I2S_BT_INSTANCE 0x01
#define DMIC_INSTANCE 0x02
#define I2S_HS_INSTANCE 0x03
#define MEM_WINDOW_START 0x4080000
@ -32,30 +34,37 @@
#define ACP3x_I2STDM_REG_END 0x1242410
#define ACP3x_BT_TDM_REG_START 0x1242800
#define ACP3x_BT_TDM_REG_END 0x1242810
#define I2S_MODE 0x04
#define I2S_RX_THRESHOLD 27
#define I2S_TX_THRESHOLD 28
#define BT_TX_THRESHOLD 26
#define BT_RX_THRESHOLD 25
#define ACP_SRAM_PTE_OFFSET 0x02052800
#define THRESHOLD(bit, base) ((bit) + (base))
#define I2S_RX_THRESHOLD(base) THRESHOLD(7, base)
#define I2S_TX_THRESHOLD(base) THRESHOLD(8, base)
#define BT_TX_THRESHOLD(base) THRESHOLD(6, base)
#define BT_RX_THRESHOLD(base) THRESHOLD(5, base)
#define HS_TX_THRESHOLD(base) THRESHOLD(4, base)
#define HS_RX_THRESHOLD(base) THRESHOLD(3, base)
#define ACP_SRAM_SP_PB_PTE_OFFSET 0x0
#define ACP_SRAM_SP_CP_PTE_OFFSET 0x100
#define ACP_SRAM_BT_PB_PTE_OFFSET 0x200
#define ACP_SRAM_BT_CP_PTE_OFFSET 0x300
#define ACP_SRAM_PDM_PTE_OFFSET 0x400
#define ACP_SRAM_HS_PB_PTE_OFFSET 0x500
#define ACP_SRAM_HS_CP_PTE_OFFSET 0x600
#define PAGE_SIZE_4K_ENABLE 0x2
#define I2S_SP_TX_MEM_WINDOW_START 0x4000000
#define I2S_SP_RX_MEM_WINDOW_START 0x4020000
#define I2S_BT_TX_MEM_WINDOW_START 0x4040000
#define I2S_BT_RX_MEM_WINDOW_START 0x4060000
#define I2S_HS_TX_MEM_WINDOW_START 0x40A0000
#define I2S_HS_RX_MEM_WINDOW_START 0x40C0000
#define SP_PB_FIFO_ADDR_OFFSET 0x500
#define SP_CAPT_FIFO_ADDR_OFFSET 0x700
#define BT_PB_FIFO_ADDR_OFFSET 0x900
#define BT_CAPT_FIFO_ADDR_OFFSET 0xB00
#define HS_PB_FIFO_ADDR_OFFSET 0xD00
#define HS_CAPT_FIFO_ADDR_OFFSET 0xF00
#define PLAYBACK_MIN_NUM_PERIODS 2
#define PLAYBACK_MAX_NUM_PERIODS 8
#define PLAYBACK_MAX_PERIOD_SIZE 8192
@ -73,7 +82,7 @@
#define ACP3x_ITER_IRER_SAMP_LEN_MASK 0x38
#define ACP_MAX_STREAM 6
#define ACP_MAX_STREAM 8
struct acp_chip_info {
char *name; /* Platform name */
@ -92,6 +101,18 @@ struct acp_stream {
u32 fifo_offset;
};
struct acp_resource {
int offset;
int no_of_ctrls;
int irqp_used;
bool soc_mclk;
u32 irq_reg_offset;
u32 i2s_pin_cfg_offset;
int i2s_mode;
u64 scratch_reg_offset;
u64 sram_pte_offset;
};
struct acp_dev_data {
char *name;
struct device *dev;
@ -106,6 +127,22 @@ struct acp_dev_data {
struct snd_soc_acpi_mach *machines;
struct platform_device *mach_dev;
u32 bclk_div;
u32 lrclk_div;
struct acp_resource *rsrc;
};
union acp_i2stdm_mstrclkgen {
struct {
u32 i2stdm_master_mode : 1;
u32 i2stdm_format_mode : 1;
u32 i2stdm_lrclk_div_val : 9;
u32 i2stdm_bclk_div_val : 11;
u32:10;
} bitfields, bits;
u32 u32_all;
};
extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
@ -134,6 +171,10 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH);
low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW);
break;
case I2S_HS_INSTANCE:
high = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH);
low = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_LOW);
break;
default:
dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
return -EINVAL;
@ -148,6 +189,10 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH);
low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW);
break;
case I2S_HS_INSTANCE:
high = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH);
low = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_LOW);
break;
case DMIC_INSTANCE:
high = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH);
low = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW);
@ -163,4 +208,31 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
return byte_count;
}
static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id)
{
union acp_i2stdm_mstrclkgen mclkgen;
u32 master_reg;
switch (dai_id) {
case I2S_SP_INSTANCE:
master_reg = ACP_I2STDM0_MSTRCLKGEN;
break;
case I2S_BT_INSTANCE:
master_reg = ACP_I2STDM1_MSTRCLKGEN;
break;
case I2S_HS_INSTANCE:
master_reg = ACP_I2STDM2_MSTRCLKGEN;
break;
default:
master_reg = ACP_I2STDM0_MSTRCLKGEN;
break;
}
mclkgen.bits.i2stdm_master_mode = 0x1;
mclkgen.bits.i2stdm_format_mode = 0x00;
mclkgen.bits.i2stdm_bclk_div_val = adata->bclk_div;
mclkgen.bits.i2stdm_lrclk_div_val = adata->lrclk_div;
writel(mclkgen.u32_all, adata->acp_base + master_reg);
}
#endif

View File

@ -20,11 +20,13 @@
#define ACP_SOFT_RESET 0x1000
#define ACP_CONTROL 0x1004
#define ACP_EXTERNAL_INTR_ENB 0x1800
#define ACP_EXTERNAL_INTR_CNTL 0x1804
#define ACP_EXTERNAL_INTR_STAT 0x1808
#define ACP_I2S_PIN_CONFIG 0x1400
#define ACP_SCRATCH_REG_0 0x12800
#define ACP_EXTERNAL_INTR_REG_ADDR(adata, offset, ctrl) \
(adata->acp_base + adata->rsrc->irq_reg_offset + offset + (ctrl * 0x04))
#define ACP_EXTERNAL_INTR_ENB(adata) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x0, 0x0)
#define ACP_EXTERNAL_INTR_CNTL(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x4, ctrl)
#define ACP_EXTERNAL_INTR_STAT(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, \
(0x4 + (adata->rsrc->no_of_ctrls * 0x04)), ctrl)
/* Registers from ACP_AUDIO_BUFFERS block */
@ -64,6 +66,24 @@
#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x2084
#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x2088
#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x208C
#define ACP_HS_RX_RINGBUFADDR 0x3A90
#define ACP_HS_RX_RINGBUFSIZE 0x3A94
#define ACP_HS_RX_LINKPOSITIONCNTR 0x3A98
#define ACP_HS_RX_FIFOADDR 0x3A9C
#define ACP_HS_RX_FIFOSIZE 0x3AA0
#define ACP_HS_RX_DMA_SIZE 0x3AA4
#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x3AA8
#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x3AAC
#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x3AB0
#define ACP_HS_TX_RINGBUFADDR 0x3AB4
#define ACP_HS_TX_RINGBUFSIZE 0x3AB8
#define ACP_HS_TX_LINKPOSITIONCNTR 0x3ABC
#define ACP_HS_TX_FIFOADDR 0x3AC0
#define ACP_HS_TX_FIFOSIZE 0x3AC4
#define ACP_HS_TX_DMA_SIZE 0x3AC8
#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x3ACC
#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x3AD0
#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x3AD4
#define ACP_I2STDM_IER 0x2400
#define ACP_I2STDM_IRER 0x2404
@ -79,6 +99,13 @@
#define ACP_BTTDM_ITER 0x280C
#define ACP_BTTDM_TXFRMT 0x2810
/* Registers from ACP_HS_TDM block */
#define ACP_HSTDM_IER 0x2814
#define ACP_HSTDM_IRER 0x2818
#define ACP_HSTDM_RXFRMT 0x281C
#define ACP_HSTDM_ITER 0x2820
#define ACP_HSTDM_TXFRMT 0x2824
/* Registers from ACP_WOV_PDM block */
#define ACP_WOV_PDM_ENABLE 0x2C04
@ -99,4 +126,7 @@
#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x2C64
#define ACP_WOV_ERROR_STATUS_REGISTER 0x2C68
#define ACP_I2STDM0_MSTRCLKGEN 0x2414
#define ACP_I2STDM1_MSTRCLKGEN 0x2418
#define ACP_I2STDM2_MSTRCLKGEN 0x241C
#endif

View File

@ -19,6 +19,7 @@
#define ACP_PCI_DEV_ID 0x15E2
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[];
struct config_entry {
u32 flags;

View File

@ -257,7 +257,8 @@ static const struct snd_soc_dai_ops acp3x_i2s_dai_ops = {
};
static const struct snd_soc_component_driver acp3x_dai_component = {
.name = DRV_NAME,
.name = DRV_NAME,
.legacy_dai_naming = 1,
};
static struct snd_soc_dai_driver acp3x_i2s_dai = {

View File

@ -363,12 +363,13 @@ static struct snd_soc_dai_driver acp_pdm_dai_driver = {
};
static const struct snd_soc_component_driver acp_pdm_component = {
.name = DRV_NAME,
.open = acp_pdm_dma_open,
.close = acp_pdm_dma_close,
.hw_params = acp_pdm_dma_hw_params,
.pointer = acp_pdm_dma_pointer,
.pcm_construct = acp_pdm_dma_new,
.name = DRV_NAME,
.open = acp_pdm_dma_open,
.close = acp_pdm_dma_close,
.hw_params = acp_pdm_dma_hw_params,
.pointer = acp_pdm_dma_pointer,
.pcm_construct = acp_pdm_dma_new,
.legacy_dai_naming = 1,
};
static int acp_pdm_audio_probe(struct platform_device *pdev)

View File

@ -37,10 +37,10 @@ static int acp5x_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
}
mode = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
switch (mode) {
case SND_SOC_DAIFMT_CBC_CFC:
case SND_SOC_DAIFMT_BP_FP:
adata->master_mode = I2S_MASTER_MODE_ENABLE;
break;
case SND_SOC_DAIFMT_CBP_CFP:
case SND_SOC_DAIFMT_BC_FC:
adata->master_mode = I2S_MASTER_MODE_DISABLE;
break;
}
@ -345,6 +345,7 @@ static const struct snd_soc_dai_ops acp5x_i2s_dai_ops = {
static const struct snd_soc_component_driver acp5x_dai_component = {
.name = "acp5x-i2s",
.legacy_dai_naming = 1,
};
static struct snd_soc_dai_driver acp5x_i2s_dai = {

View File

@ -335,12 +335,13 @@ static struct snd_soc_dai_driver acp6x_pdm_dai_driver = {
};
static const struct snd_soc_component_driver acp6x_pdm_component = {
.name = DRV_NAME,
.open = acp6x_pdm_dma_open,
.close = acp6x_pdm_dma_close,
.hw_params = acp6x_pdm_dma_hw_params,
.pointer = acp6x_pdm_dma_pointer,
.pcm_construct = acp6x_pdm_dma_new,
.name = DRV_NAME,
.open = acp6x_pdm_dma_open,
.close = acp6x_pdm_dma_close,
.hw_params = acp6x_pdm_dma_hw_params,
.pointer = acp6x_pdm_dma_pointer,
.pcm_construct = acp6x_pdm_dma_new,
.legacy_dai_naming = 1,
};
static int acp6x_pdm_audio_probe(struct platform_device *pdev)

View File

@ -458,6 +458,7 @@ static const struct snd_soc_component_driver atmel_classd_cpu_dai_component = {
.num_controls = ARRAY_SIZE(atmel_classd_snd_controls),
.idle_bias_on = 1,
.use_pmdown_time = 1,
.legacy_dai_naming = 1,
};
/* ASoC sound card */

View File

@ -343,7 +343,7 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
}
switch (dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBC_CFC:
case SND_SOC_DAIFMT_BP_FP:
/* codec is slave, so cpu is master */
mr |= ATMEL_I2SC_MR_MODE_MASTER;
ret = atmel_i2s_get_gck_param(dev, params_rate(params));
@ -351,7 +351,7 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
return ret;
break;
case SND_SOC_DAIFMT_CBP_CFP:
case SND_SOC_DAIFMT_BC_FC:
/* codec is master, so cpu is slave */
mr |= ATMEL_I2SC_MR_MODE_SLAVE;
dev->gck_param = NULL;
@ -564,7 +564,8 @@ static struct snd_soc_dai_driver atmel_i2s_dai = {
};
static const struct snd_soc_component_driver atmel_i2s_component = {
.name = "atmel-i2s",
.name = "atmel-i2s",
.legacy_dai_naming = 1,
};
static int atmel_i2s_sama5d2_mck_init(struct atmel_i2s_dev *dev,

View File

@ -481,6 +481,7 @@ static const struct snd_soc_component_driver atmel_pdmic_cpu_dai_component = {
.num_controls = ARRAY_SIZE(atmel_pdmic_snd_controls),
.idle_bias_on = 1,
.use_pmdown_time = 1,
.legacy_dai_naming = 1,
};
/* ASoC sound card */

View File

@ -210,7 +210,7 @@ static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params,
return frame_size;
switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBP_CFC:
case SND_SOC_DAIFMT_BC_FP:
if ((ssc_p->dir_mask & SSC_DIR_MASK_CAPTURE)
&& ssc->clk_from_rk_pin)
/* Receiver Frame Synchro (i.e. capture)
@ -220,7 +220,7 @@ static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params,
mck_div = 3;
break;
case SND_SOC_DAIFMT_CBP_CFP:
case SND_SOC_DAIFMT_BC_FC:
if ((ssc_p->dir_mask & SSC_DIR_MASK_PLAYBACK)
&& !ssc->clk_from_rk_pin)
/* Transmit Frame Synchro (i.e. playback)
@ -233,7 +233,7 @@ static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params,
}
switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBC_CFC:
case SND_SOC_DAIFMT_BP_FP:
r.num = ssc_p->mck_rate / mck_div / frame_size;
ret = snd_interval_ratnum(i, 1, &r, &num, &den);
@ -243,8 +243,8 @@ static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params,
}
break;
case SND_SOC_DAIFMT_CBP_CFC:
case SND_SOC_DAIFMT_CBP_CFP:
case SND_SOC_DAIFMT_BC_FP:
case SND_SOC_DAIFMT_BC_FC:
t.min = 8000;
t.max = ssc_p->mck_rate / mck_div / frame_size;
t.openmin = t.openmax = 0;
@ -433,8 +433,8 @@ static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
static int atmel_ssc_cfs(struct atmel_ssc_info *ssc_p)
{
switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBP_CFC:
case SND_SOC_DAIFMT_CBC_CFC:
case SND_SOC_DAIFMT_BC_FP:
case SND_SOC_DAIFMT_BP_FP:
return 1;
}
return 0;
@ -444,8 +444,8 @@ static int atmel_ssc_cfs(struct atmel_ssc_info *ssc_p)
static int atmel_ssc_cbs(struct atmel_ssc_info *ssc_p)
{
switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBC_CFP:
case SND_SOC_DAIFMT_CBC_CFC:
case SND_SOC_DAIFMT_BP_FC:
case SND_SOC_DAIFMT_BP_FP:
return 1;
}
return 0;
@ -858,9 +858,10 @@ 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,
.name = "atmel-ssc",
.suspend = atmel_ssc_suspend,
.resume = atmel_ssc_resume,
.legacy_dai_naming = 1,
};
static int asoc_ssc_init(struct device *dev)

View File

@ -350,7 +350,7 @@ static int mchp_i2s_mcc_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return -EINVAL;
/* We can't generate only FSYNC */
if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) == SND_SOC_DAIFMT_CBP_CFC)
if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) == SND_SOC_DAIFMT_BC_FP)
return -EINVAL;
/* We can only reconfigure the IP when it's stopped */
@ -547,19 +547,19 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
}
switch (dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBC_CFC:
case SND_SOC_DAIFMT_BP_FP:
/* cpu is BCLK and LRC master */
mra |= MCHP_I2SMCC_MRA_MODE_MASTER;
if (dev->sysclk)
mra |= MCHP_I2SMCC_MRA_IMCKMODE_GEN;
set_divs = 1;
break;
case SND_SOC_DAIFMT_CBC_CFP:
case SND_SOC_DAIFMT_BP_FC:
/* cpu is BCLK master */
mrb |= MCHP_I2SMCC_MRB_CLKSEL_INT;
set_divs = 1;
fallthrough;
case SND_SOC_DAIFMT_CBP_CFP:
case SND_SOC_DAIFMT_BC_FC:
/* cpu is slave */
mra |= MCHP_I2SMCC_MRA_MODE_SLAVE;
if (dev->sysclk)
@ -928,7 +928,8 @@ static struct snd_soc_dai_driver mchp_i2s_mcc_dai = {
};
static const struct snd_soc_component_driver mchp_i2s_mcc_component = {
.name = "mchp-i2s-mcc",
.name = "mchp-i2s-mcc",
.legacy_dai_naming = 1,
};
#ifdef CONFIG_OF

View File

@ -423,6 +423,7 @@ static const struct snd_soc_component_driver mchp_pdmc_dai_component = {
.num_controls = ARRAY_SIZE(mchp_pdmc_snd_controls),
.open = &mchp_pdmc_open,
.close = &mchp_pdmc_close,
.legacy_dai_naming = 1,
};
static const unsigned int mchp_pdmc_1mic[] = {1};
@ -492,8 +493,8 @@ static int mchp_pdmc_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
unsigned int fmt_format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
/* IP needs to be bitclock master */
if (fmt_master != SND_SOC_DAIFMT_CBS_CFS &&
fmt_master != SND_SOC_DAIFMT_CBS_CFM)
if (fmt_master != SND_SOC_DAIFMT_BP_FP &&
fmt_master != SND_SOC_DAIFMT_BP_FC)
return -EINVAL;
/* IP supports only PDM interface */
@ -984,7 +985,7 @@ static int mchp_pdmc_probe(struct platform_device *pdev)
return -ENOMEM;
dd->dev = &pdev->dev;
ret = mchp_pdmc_dt_init(dd);
ret = mchp_pdmc_dt_init(dd);
if (ret < 0)
return ret;

View File

@ -846,7 +846,8 @@ static struct snd_soc_dai_driver mchp_spdifrx_dai = {
};
static const struct snd_soc_component_driver mchp_spdifrx_component = {
.name = "mchp-spdifrx",
.name = "mchp-spdifrx",
.legacy_dai_naming = 1,
};
static const struct of_device_id mchp_spdifrx_dt_ids[] = {

View File

@ -753,7 +753,8 @@ static struct snd_soc_dai_driver mchp_spdiftx_dai = {
};
static const struct snd_soc_component_driver mchp_spdiftx_component = {
.name = "mchp-spdiftx",
.name = "mchp-spdiftx",
.legacy_dai_naming = 1,
};
static const struct of_device_id mchp_spdiftx_dt_ids[] = {

View File

@ -157,7 +157,9 @@ put_codec_node:
static int snd_proto_remove(struct platform_device *pdev)
{
return snd_soc_unregister_card(&snd_proto);
snd_soc_unregister_card(&snd_proto);
return 0;
}
static const struct of_device_id snd_proto_of_match[] = {

View File

@ -223,7 +223,8 @@ static struct snd_soc_dai_driver au1xac97c_dai_driver = {
};
static const struct snd_soc_component_driver au1xac97c_component = {
.name = "au1xac97c",
.name = "au1xac97c",
.legacy_dai_naming = 1,
};
static int au1xac97c_drvprobe(struct platform_device *pdev)

View File

@ -121,7 +121,7 @@ static int au1xi2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
/* I2S controller only supports provider */
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBC_CFC: /* CODEC consumer */
case SND_SOC_DAIFMT_BP_FP: /* CODEC consumer */
break;
default:
goto out;
@ -227,7 +227,8 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
};
static const struct snd_soc_component_driver au1xi2s_component = {
.name = "au1xi2s",
.name = "au1xi2s",
.legacy_dai_naming = 1,
};
static int au1xi2s_drvprobe(struct platform_device *pdev)

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