ASoC: Updates for v6.3

There's been quite a lot of activity this release, but not really
 one big feature - lots of new devices, plus a lot of cleanup and
 modernisation work spread throughout the subsystem:
 
  - More factoring out of common operations into helper functions
    by Morimoto-san.
  - DT schema conversons and stylistic nits.
  - Continued work on building out the new SOF IPC4 scheme.
  - Support for Awinc AT88395, Infineon PEB2466, Iron Device
    SMA1303, Mediatek MT8188, Realtek RT712, Renesas IDT821034,
    Samsung/Tesla FSD SoC I2S, and TI TAS5720A-Q1.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmPuKzoACgkQJNaLcl1U
 h9AO6wf/Us32gNLnLhT+YaPKouVq4KYpEXDeaIOdOCgs8RtonuCgURZ/D2TkzBVL
 EHLPp4QgqdIWo3FKkWgsXIOpO7R0//cj/vpccJ0PBe4VmvDinXq3dzGPPy6ZbHAS
 SatE5zItBKRUHaDliRk6S7IFEqJKwwlBqEzV0K41Q4EstYlIe+No0XIVDj3oRjHb
 jPmAD9XRPqsDaFFFb0NrVl9M/8HwBlc3j/Gnt19eJB/07IdgIr0S8mJn3qlFfGqu
 O8KgBo4+tvVMCQAxTVZ5exb/qTtK3gEPDuMi0eOKJz+g9wMJ4tRz+D8/8TQSmxmW
 lWORmNTx8jml7G4KirxIV4q4Lr0hRQ==
 =mB3t
 -----END PGP SIGNATURE-----

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

ASoC: Updates for v6.3

There's been quite a lot of activity this release, but not really
one big feature - lots of new devices, plus a lot of cleanup and
modernisation work spread throughout the subsystem:

 - More factoring out of common operations into helper functions
   by Morimoto-san.
 - DT schema conversons and stylistic nits.
 - Continued work on building out the new SOF IPC4 scheme.
 - Support for Awinc AT88395, Infineon PEB2466, Iron Device
   SMA1303, Mediatek MT8188, Realtek RT712, Renesas IDT821034,
   Samsung/Tesla FSD SoC I2S, and TI TAS5720A-Q1.
This commit is contained in:
Takashi Iwai 2023-02-16 14:32:04 +01:00
commit 1bdb78368f
326 changed files with 32251 additions and 3395 deletions

View File

@ -15,7 +15,9 @@ description: |
properties:
compatible:
const: mediatek,mt8186-dsp
enum:
- mediatek,mt8186-dsp
- mediatek,mt8188-dsp
reg:
items:

View File

@ -1,19 +0,0 @@
Analog Devices ADAU7002 Stereo PDM-to-I2S/TDM Converter
Required properties:
- compatible: Must be "adi,adau7002"
Optional properties:
- IOVDD-supply: Phandle and specifier for the power supply providing the IOVDD
supply as covered in Documentation/devicetree/bindings/regulator/regulator.txt
If this property is not present it is assumed that the supply pin is
hardwired to always on.
Example:
adau7002: pdm-to-i2s {
compatible = "adi,adau7002";
IOVDD-supply = <&supply>;
};

View File

@ -0,0 +1,40 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/adi,adau7002.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices ADAU7002 Stereo PDM-to-I2S/TDM Converter
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: adi,adau7002
IOVDD-supply:
description:
IOVDD power supply, if skipped then it is assumed that the supply pin is
hardwired to always on.
wakeup-delay-ms:
description:
Delay after power up needed for device to settle.
required:
- compatible
unevaluatedProperties: false
examples:
- |
audio-codec {
compatible = "adi,adau7002";
IOVDD-supply = <&pp1800_l15a>;
#sound-dai-cells = <0>;
wakeup-delay-ms = <80>;
};

View File

@ -25,6 +25,13 @@ properties:
"#sound-dai-cells":
const: 0
ports:
$ref: audio-graph-port.yaml#/definitions/ports
port:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
patternProperties:
"^asahi-kasei,in[1-2]-single-end$":
description: Input Pin 1 - 2.

View File

@ -1,34 +0,0 @@
* Amlogic Audio FIFO controllers
Required properties:
- compatible: 'amlogic,axg-toddr' or
'amlogic,axg-toddr' or
'amlogic,g12a-frddr' or
'amlogic,g12a-toddr' or
'amlogic,sm1-frddr' or
'amlogic,sm1-toddr'
- reg: physical base address of the controller and length of memory
mapped region.
- interrupts: interrupt specifier for the fifo.
- clocks: phandle to the fifo peripheral clock provided by the audio
clock controller.
- resets: list of reset phandle, one for each entry reset-names.
- reset-names: should contain the following:
* "arb" : memory ARB line (required)
* "rst" : dedicated device reset line (optional)
- #sound-dai-cells: must be 0.
- amlogic,fifo-depth: The size of the controller's fifo in bytes. This
is useful for determining certain configuration such
as the flush threshold of the fifo
Example of FRDDR A on the A113 SoC:
frddr_a: audio-controller@1c0 {
compatible = "amlogic,axg-frddr";
reg = <0x0 0x1c0 0x0 0x1c>;
#sound-dai-cells = <0>;
interrupts = <GIC_SPI 88 IRQ_TYPE_EDGE_RISING>;
clocks = <&clkc_audio AUD_CLKID_FRDDR_A>;
resets = <&arb AXG_ARB_FRDDR_A>;
fifo-depth = <512>;
};

View File

@ -0,0 +1,112 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/amlogic,axg-fifo.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic AXG Audio FIFO controllers
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
properties:
compatible:
oneOf:
- enum:
- amlogic,axg-toddr
- amlogic,axg-frddr
- items:
- enum:
- amlogic,g12a-toddr
- amlogic,sm1-toddr
- const: amlogic,axg-toddr
- items:
- enum:
- amlogic,g12a-frddr
- amlogic,sm1-frddr
- const: amlogic,axg-frddr
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
clocks:
items:
- description: Peripheral clock
interrupts:
maxItems: 1
resets:
minItems: 1
maxItems: 2
reset-names:
minItems: 1
maxItems: 2
amlogic,fifo-depth:
$ref: /schemas/types.yaml#/definitions/uint32
description: Size of the controller's fifo in bytes
required:
- compatible
- reg
- "#sound-dai-cells"
- clocks
- interrupts
- resets
- amlogic,fifo-depth
allOf:
- $ref: dai-common.yaml#
- if:
properties:
compatible:
contains:
enum:
- amlogic,g12a-toddr
- amlogic,sm1-toddr
- amlogic,g12a-frddr
- amlogic,sm1-frddr
then:
properties:
resets:
minItems: 2
reset-names:
items:
- const: arb
- const: rst
required:
- reset-names
else:
properties:
resets:
maxItems: 1
reset-names:
const: arb
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/axg-audio-clkc.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
#include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h>
audio-controller@1c0 {
compatible = "amlogic,g12a-frddr", "amlogic,axg-frddr";
reg = <0x1c0 0x1c>;
#sound-dai-cells = <0>;
clocks = <&clkc_audio AUD_CLKID_FRDDR_A>;
interrupts = <GIC_SPI 88 IRQ_TYPE_EDGE_RISING>;
resets = <&arb>, <&clkc_audio AUD_RESET_FRDDR_A>;
reset-names = "arb", "rst";
amlogic,fifo-depth = <512>;
};

View File

@ -1,29 +0,0 @@
* Amlogic Audio PDM input
Required properties:
- compatible: 'amlogic,axg-pdm' or
'amlogic,g12a-pdm' or
'amlogic,sm1-pdm'
- reg: physical base address of the controller and length of memory
mapped region.
- clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following:
* "pclk" : peripheral clock.
* "dclk" : pdm digital clock
* "sysclk" : dsp system clock
- #sound-dai-cells: must be 0.
Optional property:
- resets: phandle to the dedicated reset line of the pdm input.
Example of PDM on the A113 SoC:
pdm: audio-controller@ff632000 {
compatible = "amlogic,axg-pdm";
reg = <0x0 0xff632000 0x0 0x34>;
#sound-dai-cells = <0>;
clocks = <&clkc_audio AUD_CLKID_PDM>,
<&clkc_audio AUD_CLKID_PDM_DCLK>,
<&clkc_audio AUD_CLKID_PDM_SYSCLK>;
clock-names = "pclk", "dclk", "sysclk";
};

View File

@ -0,0 +1,82 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/amlogic,axg-pdm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic Audio AXG PDM input
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
properties:
compatible:
oneOf:
- items:
- enum:
- amlogic,g12a-pdm
- amlogic,sm1-pdm
- const: amlogic,axg-pdm
- const: amlogic,axg-pdm
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
clocks:
items:
- description: Peripheral clock
- description: PDM digital clock
- description: DSP system clock
clock-names:
items:
- const: pclk
- const: dclk
- const: sysclk
resets:
maxItems: 1
required:
- compatible
- reg
- "#sound-dai-cells"
- clocks
- clock-names
allOf:
- $ref: dai-common.yaml#
- if:
properties:
compatible:
contains:
enum:
- amlogic,g12a-pdm
- amlogic,sm1-pdm
then:
required:
- resets
else:
properties:
resets: false
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/axg-audio-clkc.h>
audio-controller@ff632000 {
compatible = "amlogic,axg-pdm";
reg = <0xff632000 0x34>;
#sound-dai-cells = <0>;
clocks = <&clkc_audio AUD_CLKID_PDM>,
<&clkc_audio AUD_CLKID_PDM_DCLK>,
<&clkc_audio AUD_CLKID_PDM_SYSCLK>;
clock-names = "pclk", "dclk", "sysclk";
};

View File

@ -1,124 +0,0 @@
Amlogic AXG sound card:
Required properties:
- compatible: "amlogic,axg-sound-card"
- model : User specified audio sound card name, one string
Optional properties:
- audio-aux-devs : List of phandles pointing to auxiliary devices
- audio-widgets : Please refer to widgets.txt.
- audio-routing : A list of the connections between audio components.
Subnodes:
- dai-link: Container for dai-link level properties and the CODEC
sub-nodes. There should be at least one (and probably more)
subnode of this type.
Required dai-link properties:
- sound-dai: phandle and port of the CPU DAI.
Required TDM Backend dai-link properties:
- dai-format : CPU/CODEC common audio format
Optional TDM Backend dai-link properties:
- dai-tdm-slot-rx-mask-{0,1,2,3}: Receive direction slot masks
- dai-tdm-slot-tx-mask-{0,1,2,3}: Transmit direction slot masks
When omitted, mask is assumed to have to no
slots. A valid must have at one slot, so at
least one these mask should be provided with
an enabled slot.
- dai-tdm-slot-num : Please refer to tdm-slot.txt.
If omitted, slot number is set to accommodate the largest
mask provided.
- dai-tdm-slot-width : Please refer to tdm-slot.txt. default to 32 if omitted.
- mclk-fs : Multiplication factor between stream rate and mclk
Backend dai-link subnodes:
- codec: dai-link representing backend links should have at least one subnode.
One subnode for each codec of the dai-link.
dai-link representing frontend links have no codec, therefore have no
subnodes
Required codec subnodes properties:
- sound-dai: phandle and port of the CODEC DAI.
Optional codec subnodes properties:
- dai-tdm-slot-tx-mask : Please refer to tdm-slot.txt.
- dai-tdm-slot-rx-mask : Please refer to tdm-slot.txt.
Example:
sound {
compatible = "amlogic,axg-sound-card";
model = "AXG-S420";
audio-aux-devs = <&tdmin_a>, <&tdmout_c>;
audio-widgets = "Line", "Lineout",
"Line", "Linein",
"Speaker", "Speaker1 Left",
"Speaker", "Speaker1 Right";
"Speaker", "Speaker2 Left",
"Speaker", "Speaker2 Right";
audio-routing = "TDMOUT_C IN 0", "FRDDR_A OUT 2",
"SPDIFOUT IN 0", "FRDDR_A OUT 3",
"TDM_C Playback", "TDMOUT_C OUT",
"TDMIN_A IN 2", "TDM_C Capture",
"TDMIN_A IN 5", "TDM_C Loopback",
"TODDR_A IN 0", "TDMIN_A OUT",
"Lineout", "Lineout AOUTL",
"Lineout", "Lineout AOUTR",
"Speaker1 Left", "SPK1 OUT_A",
"Speaker2 Left", "SPK2 OUT_A",
"Speaker1 Right", "SPK1 OUT_B",
"Speaker2 Right", "SPK2 OUT_B",
"Linein AINL", "Linein",
"Linein AINR", "Linein";
dai-link@0 {
sound-dai = <&frddr_a>;
};
dai-link@1 {
sound-dai = <&toddr_a>;
};
dai-link@2 {
sound-dai = <&tdmif_c>;
dai-format = "i2s";
dai-tdm-slot-tx-mask-2 = <1 1>;
dai-tdm-slot-tx-mask-3 = <1 1>;
dai-tdm-slot-rx-mask-1 = <1 1>;
mclk-fs = <256>;
codec@0 {
sound-dai = <&lineout>;
};
codec@1 {
sound-dai = <&speaker_amp1>;
};
codec@2 {
sound-dai = <&speaker_amp2>;
};
codec@3 {
sound-dai = <&linein>;
};
};
dai-link@3 {
sound-dai = <&spdifout>;
codec {
sound-dai = <&spdif_dit>;
};
};
};

View File

@ -0,0 +1,183 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/amlogic,axg-sound-card.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic AXG sound card
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
properties:
compatible:
const: amlogic,axg-sound-card
audio-aux-devs:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: list of auxiliary devices
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description:
A list of the connections between audio components. Each entry is a
pair of strings, the first being the connection's sink, the second
being the connection's source.
audio-widgets:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description:
A list off component DAPM widget. Each entry is a pair of strings,
the first being the widget type, the second being the widget name
model:
$ref: /schemas/types.yaml#/definitions/string
description: User specified audio sound card name
patternProperties:
"^dai-link-[0-9]+$":
type: object
additionalProperties: false
description:
Container for dai-link level properties and the CODEC sub-nodes.
There should be at least one (and probably more) subnode of this type
properties:
dai-format:
$ref: /schemas/types.yaml#/definitions/string
enum: [ i2s, left-j, dsp_a ]
dai-tdm-slot-num:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Number of slots in use. If omitted, slot number is set to
accommodate the largest mask provided.
maximum: 32
dai-tdm-slot-width:
$ref: /schemas/types.yaml#/definitions/uint32
description: Width in bits for each slot
enum: [ 8, 16, 20, 24, 32 ]
default: 32
mclk-fs:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Multiplication factor between the frame rate and master clock
rate
sound-dai:
maxItems: 1
description: phandle of the CPU DAI
patternProperties:
"^dai-tdm-slot-(t|r)x-mask-[0-3]$":
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 32
description:
Transmit and receive cpu slot masks of each TDM lane
When omitted, mask is assumed to have to no slots. A valid
interface must have at least one slot, so at least one these
mask should be provided with an enabled slot.
"^codec(-[0-9]+)?$":
type: object
additionalProperties: false
description:
dai-link representing backend links should have at least one subnode.
One subnode for each codec of the dai-link. dai-link representing
frontend links have no codec, therefore have no subnodes
properties:
sound-dai:
maxItems: 1
description: phandle of the codec DAI
patternProperties:
"^dai-tdm-slot-(t|r)x-mask$":
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 32
description: Transmit and receive codec slot masks
required:
- sound-dai
required:
- sound-dai
required:
- model
- dai-link-0
unevaluatedProperties: false
examples:
- |
sound {
compatible = "amlogic,axg-sound-card";
model = "AXG-S420";
audio-aux-devs = <&tdmin_a>, <&tdmout_c>;
audio-widgets = "Line", "Lineout",
"Line", "Linein",
"Speaker", "Speaker1 Left",
"Speaker", "Speaker1 Right",
"Speaker", "Speaker2 Left",
"Speaker", "Speaker2 Right";
audio-routing = "TDMOUT_C IN 0", "FRDDR_A OUT 2",
"SPDIFOUT IN 0", "FRDDR_A OUT 3",
"TDM_C Playback", "TDMOUT_C OUT",
"TDMIN_A IN 2", "TDM_C Capture",
"TDMIN_A IN 5", "TDM_C Loopback",
"TODDR_A IN 0", "TDMIN_A OUT",
"Lineout", "Lineout AOUTL",
"Lineout", "Lineout AOUTR",
"Speaker1 Left", "SPK1 OUT_A",
"Speaker2 Left", "SPK2 OUT_A",
"Speaker1 Right", "SPK1 OUT_B",
"Speaker2 Right", "SPK2 OUT_B",
"Linein AINL", "Linein",
"Linein AINR", "Linein";
dai-link-0 {
sound-dai = <&frddr_a>;
};
dai-link-1 {
sound-dai = <&toddr_a>;
};
dai-link-2 {
sound-dai = <&tdmif_c>;
dai-format = "i2s";
dai-tdm-slot-tx-mask-2 = <1 1>;
dai-tdm-slot-tx-mask-3 = <1 1>;
dai-tdm-slot-rx-mask-1 = <1 1>;
mclk-fs = <256>;
codec-0 {
sound-dai = <&lineout>;
};
codec-1 {
sound-dai = <&speaker_amp1>;
};
codec-2 {
sound-dai = <&speaker_amp2>;
};
codec-3 {
sound-dai = <&linein>;
};
};
dai-link-3 {
sound-dai = <&spdifout>;
codec {
sound-dai = <&spdif_dit>;
};
};
};

View File

@ -1,27 +0,0 @@
* Amlogic Audio SPDIF Input
Required properties:
- compatible: 'amlogic,axg-spdifin' or
'amlogic,g12a-spdifin' or
'amlogic,sm1-spdifin'
- interrupts: interrupt specifier for the spdif input.
- clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following:
* "pclk" : peripheral clock.
* "refclk" : spdif input reference clock
- #sound-dai-cells: must be 0.
Optional property:
- resets: phandle to the dedicated reset line of the spdif input.
Example on the A113 SoC:
spdifin: audio-controller@400 {
compatible = "amlogic,axg-spdifin";
reg = <0x0 0x400 0x0 0x30>;
#sound-dai-cells = <0>;
interrupts = <GIC_SPI 87 IRQ_TYPE_EDGE_RISING>;
clocks = <&clkc_audio AUD_CLKID_SPDIFIN>,
<&clkc_audio AUD_CLKID_SPDIFIN_CLK>;
clock-names = "pclk", "refclk";
};

View File

@ -0,0 +1,86 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/amlogic,axg-spdifin.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic Audio AXG SPDIF Input
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
properties:
compatible:
oneOf:
- const: amlogic,axg-spdifin
- items:
- enum:
- amlogic,g12a-spdifin
- amlogic,sm1-spdifin
- const: amlogic,axg-spdifin
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
clocks:
items:
- description: Peripheral clock
- description: SPDIF input reference clock
clock-names:
items:
- const: pclk
- const: refclk
interrupts:
maxItems: 1
resets:
maxItems: 1
required:
- compatible
- reg
- "#sound-dai-cells"
- clocks
- clock-names
- interrupts
allOf:
- $ref: dai-common.yaml#
- if:
properties:
compatible:
contains:
enum:
- amlogic,g12a-spdifin
- amlogic,sm1-spdifin
then:
required:
- resets
else:
properties:
resets: false
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/axg-audio-clkc.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
audio-controller@400 {
compatible = "amlogic,axg-spdifin";
reg = <0x400 0x30>;
#sound-dai-cells = <0>;
interrupts = <GIC_SPI 87 IRQ_TYPE_EDGE_RISING>;
clocks = <&clkc_audio AUD_CLKID_SPDIFIN>,
<&clkc_audio AUD_CLKID_SPDIFIN_CLK>;
clock-names = "pclk", "refclk";
};

View File

@ -1,25 +0,0 @@
* Amlogic Audio SPDIF Output
Required properties:
- compatible: 'amlogic,axg-spdifout' or
'amlogic,g12a-spdifout' or
'amlogic,sm1-spdifout'
- clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following:
* "pclk" : peripheral clock.
* "mclk" : master clock
- #sound-dai-cells: must be 0.
Optional property:
- resets: phandle to the dedicated reset line of the spdif output.
Example on the A113 SoC:
spdifout: audio-controller@480 {
compatible = "amlogic,axg-spdifout";
reg = <0x0 0x480 0x0 0x50>;
#sound-dai-cells = <0>;
clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>,
<&clkc_audio AUD_CLKID_SPDIFOUT_CLK>;
clock-names = "pclk", "mclk";
};

View File

@ -0,0 +1,79 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/amlogic,axg-spdifout.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic Audio AXG SPDIF Output
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
properties:
compatible:
oneOf:
- const: amlogic,axg-spdifout
- items:
- enum:
- amlogic,g12a-spdifout
- amlogic,sm1-spdifout
- const: amlogic,axg-spdifout
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
clocks:
items:
- description: Peripheral clock
- description: SPDIF output master clock
clock-names:
items:
- const: pclk
- const: mclk
resets:
maxItems: 1
required:
- compatible
- reg
- "#sound-dai-cells"
- clocks
- clock-names
allOf:
- $ref: dai-common.yaml#
- if:
properties:
compatible:
contains:
enum:
- amlogic,g12a-spdifout
- amlogic,sm1-spdifout
then:
required:
- resets
else:
properties:
resets: false
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/axg-audio-clkc.h>
audio-controller@480 {
compatible = "amlogic,axg-spdifout";
reg = <0x480 0x50>;
#sound-dai-cells = <0>;
clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>,
<&clkc_audio AUD_CLKID_SPDIFOUT_CLK>;
clock-names = "pclk", "mclk";
};

View File

@ -1,36 +0,0 @@
* Amlogic Audio TDM formatters
Required properties:
- compatible: 'amlogic,axg-tdmin' or
'amlogic,axg-tdmout' or
'amlogic,g12a-tdmin' or
'amlogic,g12a-tdmout' or
'amlogic,sm1-tdmin' or
'amlogic,sm1-tdmout
- reg: physical base address of the controller and length of memory
mapped region.
- clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following:
* "pclk" : peripheral clock.
* "sclk" : bit clock.
* "sclk_sel" : bit clock input multiplexer.
* "lrclk" : sample clock
* "lrclk_sel": sample clock input multiplexer
Optional property:
- resets: phandle to the dedicated reset line of the tdm formatter.
Example of TDMOUT_A on the S905X2 SoC:
tdmout_a: audio-controller@500 {
compatible = "amlogic,axg-tdmout";
reg = <0x0 0x500 0x0 0x40>;
resets = <&clkc_audio AUD_RESET_TDMOUT_A>;
clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>,
<&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>,
<&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>,
<&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>,
<&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>;
clock-names = "pclk", "sclk", "sclk_sel",
"lrclk", "lrclk_sel";
};

View File

@ -0,0 +1,88 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/amlogic,axg-tdm-formatters.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic Audio AXG TDM formatters
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
properties:
compatible:
enum:
- amlogic,g12a-tdmout
- amlogic,sm1-tdmout
- amlogic,axg-tdmout
- amlogic,g12a-tdmin
- amlogic,sm1-tdmin
- amlogic,axg-tdmin
clocks:
items:
- description: Peripheral clock
- description: Bit clock
- description: Bit clock input multiplexer
- description: Sample clock
- description: Sample clock input multiplexer
clock-names:
items:
- const: pclk
- const: sclk
- const: sclk_sel
- const: lrclk
- const: lrclk_sel
reg:
maxItems: 1
resets:
maxItems: 1
required:
- compatible
- reg
- clocks
- clock-names
allOf:
- $ref: component-common.yaml#
- if:
properties:
compatible:
contains:
enum:
- amlogic,g12a-tdmin
- amlogic,sm1-tdmin
- amlogic,g12a-tdmout
- amlogic,sm1-tdmout
then:
required:
- resets
else:
properties:
resets: false
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/axg-audio-clkc.h>
#include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h>
audio-controller@500 {
compatible = "amlogic,g12a-tdmout";
reg = <0x500 0x40>;
resets = <&clkc_audio AUD_RESET_TDMOUT_A>;
clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>,
<&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>,
<&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>,
<&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>,
<&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>;
clock-names = "pclk", "sclk", "sclk_sel",
"lrclk", "lrclk_sel";
};

View File

@ -1,22 +0,0 @@
* Amlogic Audio TDM Interfaces
Required properties:
- compatible: 'amlogic,axg-tdm-iface'
- clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following:
* "sclk" : bit clock.
* "lrclk": sample clock
* "mclk" : master clock
-> optional if the interface is in clock slave mode.
- #sound-dai-cells: must be 0.
Example of TDM_A on the A113 SoC:
tdmif_a: audio-controller@0 {
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>,
<&clkc_audio AUD_CLKID_MST_A_SCLK>,
<&clkc_audio AUD_CLKID_MST_A_LRCLK>;
clock-names = "mclk", "sclk", "lrclk";
};

View File

@ -0,0 +1,55 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/amlogic,axg-tdm-iface.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic Audio TDM Interfaces
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: amlogic,axg-tdm-iface
"#sound-dai-cells":
const: 0
clocks:
minItems: 2
items:
- description: Bit clock
- description: Sample clock
- description: Master clock #optional
clock-names:
minItems: 2
items:
- const: sclk
- const: lrclk
- const: mclk
required:
- compatible
- "#sound-dai-cells"
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/axg-audio-clkc.h>
audio-controller {
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
<&clkc_audio AUD_CLKID_MST_A_LRCLK>,
<&clkc_audio AUD_CLKID_MST_A_MCLK>;
clock-names = "sclk", "lrclk", "mclk";
};

View File

@ -62,7 +62,7 @@ patternProperties:
description: phandle of the CPU DAI
patternProperties:
"^codec-[0-9]+$":
"^codec(-[0-9]+)?$":
type: object
additionalProperties: false
description: |-

View File

@ -11,32 +11,24 @@ maintainers:
select: false
allOf:
- $ref: /schemas/graph.yaml#/$defs/port-base
definitions:
port-base:
$ref: /schemas/graph.yaml#/$defs/port-base
properties:
convert-rate:
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate"
convert-channels:
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels"
convert-sample-format:
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format"
mclk-fs:
$ref: "simple-card.yaml#/definitions/mclk-fs"
properties:
prefix:
description: "device name prefix"
$ref: /schemas/types.yaml#/definitions/string
convert-rate:
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate"
convert-channels:
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels"
convert-sample-format:
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format"
patternProperties:
"^endpoint(@[0-9a-f]+)?":
endpoint-base:
$ref: /schemas/graph.yaml#/$defs/endpoint-base
unevaluatedProperties: false
properties:
mclk-fs:
description: |
Multiplication factor between stream rate and codec mclk.
When defined, mclk-fs property defined in dai-link sub nodes are
ignored.
$ref: /schemas/types.yaml#/definitions/uint32
$ref: "simple-card.yaml#/definitions/mclk-fs"
frame-inversion:
description: dai-link uses frame clock inversion
$ref: /schemas/types.yaml#/definitions/flag
@ -53,6 +45,15 @@ patternProperties:
oneOf:
- $ref: /schemas/types.yaml#/definitions/flag
- $ref: /schemas/types.yaml#/definitions/phandle
clocks:
description: Indicates system clock
$ref: /schemas/types.yaml#/definitions/phandle
system-clock-frequency:
$ref: "simple-card.yaml#/definitions/system-clock-frequency"
system-clock-direction-out:
$ref: "simple-card.yaml#/definitions/system-clock-direction-out"
system-clock-fixed:
$ref: "simple-card.yaml#/definitions/system-clock-fixed"
dai-format:
description: audio format.
@ -100,4 +101,24 @@ patternProperties:
minimum: 1
maximum: 64
ports:
$ref: "#/definitions/port-base"
unevaluatedProperties: false
patternProperties:
"^port(@[0-9a-f]+)?$":
$ref: "#/definitions/port-base"
unevaluatedProperties: false
patternProperties:
"^endpoint(@[0-9a-f]+)?":
$ref: "#/definitions/endpoint-base"
unevaluatedProperties: false
allOf:
- $ref: "#/definitions/port-base"
patternProperties:
"^endpoint(@[0-9a-f]+)?":
$ref: "#/definitions/endpoint-base"
unevaluatedProperties: false
additionalProperties: true

View File

@ -0,0 +1,53 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/awinic,aw88395.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Awinic AW88395 Smart Audio Amplifier
maintainers:
- Weidong Wang <wangweidong.a@awinic.com>
description:
The Awinic AW88395 is an I2S/TDM input, high efficiency
digital Smart K audio amplifier with an integrated 10.25V
smart boost convert.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: awinic,aw88395
reg:
maxItems: 1
'#sound-dai-cells':
const: 0
reset-gpios:
maxItems: 1
required:
- compatible
- reg
- '#sound-dai-cells'
- reset-gpios
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@34 {
compatible = "awinic,aw88395";
reg = <0x34>;
#sound-dai-cells = <0>;
reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
};
};

View File

@ -22,6 +22,9 @@ properties:
reg:
maxItems: 1
interrupts:
maxItems: 1
'#sound-dai-cells':
description:
The first cell indicating the audio interface.
@ -42,7 +45,7 @@ properties:
Configures the peak current by monitoring the current through the boost FET.
Range starts at 1600 mA and goes to a maximum of 4500 mA with increments
of 50 mA. See section 4.3.6 of the datasheet for details.
$ref: "/schemas/types.yaml#/definitions/uint32"
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1600
maximum: 4500
default: 4500
@ -51,7 +54,7 @@ properties:
description:
Boost inductor value, expressed in nH. Valid
values include 1000, 1200, 1500 and 2200.
$ref: "/schemas/types.yaml#/definitions/uint32"
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1000
maximum: 2200
@ -60,7 +63,7 @@ properties:
Total equivalent boost capacitance on the VBST
and VAMP pins, derated at 11 volts DC. The value must be rounded to the
nearest integer and expressed in uF.
$ref: "/schemas/types.yaml#/definitions/uint32"
$ref: /schemas/types.yaml#/definitions/uint32
cirrus,asp-sdout-hiz:
description:
@ -70,7 +73,7 @@ properties:
1 = Hi-Z during unused slots but logic 0 while all transmit channels disabled
2 = (Default) Logic 0 during unused slots, but Hi-Z while all transmit channels disabled
3 = Hi-Z during unused slots and while all transmit channels disabled
$ref: "/schemas/types.yaml#/definitions/uint32"
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 3
default: 2
@ -84,7 +87,7 @@ properties:
enable boost voltage.
0 = Internal Boost
1 = External Boost
$ref: "/schemas/types.yaml#/definitions/uint32"
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 1
@ -109,7 +112,7 @@ properties:
1 = GPIO
2 = Sync
3 = MCLK input
$ref: "/schemas/types.yaml#/definitions/uint32"
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 3
@ -136,7 +139,7 @@ properties:
3 = MCLK input
4 = Push-pull INTB (active low)
5 = Push-pull INT (active high)
$ref: "/schemas/types.yaml#/definitions/uint32"
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 5
@ -176,21 +179,23 @@ unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
cs35l41: cs35l41@2 {
#sound-dai-cells = <1>;
compatible = "cirrus,cs35l41";
reg = <2>;
VA-supply = <&dummy_vreg>;
VP-supply = <&dummy_vreg>;
reset-gpios = <&gpio 110 0>;
cs35l41: speaker-amp@2 {
#sound-dai-cells = <1>;
compatible = "cirrus,cs35l41";
reg = <2>;
VA-supply = <&dummy_vreg>;
VP-supply = <&dummy_vreg>;
reset-gpios = <&gpio 110 GPIO_ACTIVE_HIGH>;
cirrus,boost-type = <0>;
cirrus,boost-peak-milliamp = <4500>;
cirrus,boost-ind-nanohenry = <1000>;
cirrus,boost-cap-microfarad = <15>;
cirrus,boost-type = <0>;
cirrus,boost-peak-milliamp = <4500>;
cirrus,boost-ind-nanohenry = <1000>;
cirrus,boost-cap-microfarad = <15>;
};
};

View File

@ -0,0 +1,21 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/component-common.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Audio Component Common Properties
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
properties:
sound-name-prefix:
$ref: /schemas/types.yaml#/definitions/string
description: |
Card implementing the routing property define the connection between
audio components as list of string pair. Component using the same
sink/source names may use this property to prepend the name of their
sinks/sources with the provided string.
additionalProperties: true

View File

@ -9,15 +9,10 @@ title: Digital Audio Interface Common Properties
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
properties:
sound-name-prefix:
$ref: /schemas/types.yaml#/definitions/string
description: |
Card implementing the routing property define the connection between
audio components as list of string pair. Component using the same
sink/source names may use this property to prepend the name of their
sinks/sources with the provided string.
allOf:
- $ref: component-common.yaml#
properties:
'#sound-dai-cells': true
additionalProperties: true

View File

@ -76,10 +76,14 @@ properties:
minItems: 4
dmas:
maxItems: 2
items:
- description: DMA controller phandle and request line for RX
- description: DMA controller phandle and request line for TX
dma-names:
maxItems: 2
items:
- const: rx
- const: tx
interrupts:
items:
@ -142,31 +146,6 @@ properties:
allOf:
- $ref: dai-common.yaml#
- if:
properties:
compatible:
contains:
const: fsl,vf610-sai
then:
properties:
dmas:
items:
- description: DMA controller phandle and request line for TX
- description: DMA controller phandle and request line for RX
dma-names:
items:
- const: tx
- const: rx
else:
properties:
dmas:
items:
- description: DMA controller phandle and request line for RX
- description: DMA controller phandle and request line for TX
dma-names:
items:
- const: rx
- const: tx
- if:
required:
- fsl,sai-asynchronous
@ -199,9 +178,8 @@ examples:
<&clks VF610_CLK_SAI2>,
<&clks 0>, <&clks 0>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
dma-names = "tx", "rx";
dmas = <&edma0 0 21>,
<&edma0 0 20>;
dma-names = "rx", "tx";
dmas = <&edma0 0 20>, <&edma0 0 21>;
big-endian;
lsb-first;
};

View File

@ -21,6 +21,7 @@ properties:
compatible:
enum:
- fsl,imx8mp-xcvr
- fsl,imx93-xcvr
reg:
items:

View File

@ -75,6 +75,18 @@ patternProperties:
additionalProperties: false
platform:
description: Holds subnode which includes the phandle of q6apm platform device.
type: object
properties:
sound-dai:
maxItems: 1
required:
- sound-dai
additionalProperties: false
required:
- link-name
- cpu

View File

@ -0,0 +1,91 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/infineon,peb2466.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Infineon PEB2466 codec
maintainers:
- Herve Codina <herve.codina@bootlin.com>
description: |
The Infineon PEB2466 codec is a programmable DSP-based four channels codec
with filters capabilities.
The time-slots used by the codec must be set and so, the properties
'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
'dai-tdm-slot-rx-mask' must be present in the sound card node for sub-nodes
that involve the codec. The codec uses one 8bit time-slot per channel.
'dai-tdm-tdm-slot-with' must be set to 8.
The PEB2466 codec also supports 28 gpios (signaling pins).
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml
- $ref: dai-common.yaml#
properties:
compatible:
const: infineon,peb2466
reg:
description:
SPI device address.
maxItems: 1
clocks:
items:
- description: Master clock
clock-names:
items:
- const: mclk
spi-max-frequency:
maximum: 8192000
reset-gpios:
description:
GPIO used to reset the device.
maxItems: 1
firmware-name:
$ref: /schemas/types.yaml#/definitions/string
description:
Filters coefficients file to load. If this property is omitted, internal
filters are disabled.
'#sound-dai-cells':
const: 0
'#gpio-cells':
const: 2
gpio-controller: true
required:
- compatible
- reg
- '#sound-dai-cells'
- gpio-controller
- '#gpio-cells'
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@0 {
compatible = "infineon,peb2466";
reg = <0>;
spi-max-frequency = <8192000>;
reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
#sound-dai-cells = <0>;
gpio-controller;
#gpio-cells = <2>;
};
};

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/irondevice,sma1303.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Iron Device SMA1303 Audio Amplifier
maintainers:
- Kiseok Jo <kiseok.jo@irondevice.com>
description:
SMA1303 digital class-D audio amplifier
with an integrated boost converter.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
enum:
- irondevice,sma1303
reg:
maxItems: 1
'#sound-dai-cells':
const: 1
required:
- compatible
- reg
- '#sound-dai-cells'
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
amplifier@1e {
compatible = "irondevice,sma1303";
reg = <0x1e>;
#sound-dai-cells = <1>;
};
};

View File

@ -1,59 +0,0 @@
MAX98090 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "maxim,max98090" or "maxim,max98091".
- reg : The I2C address of the device.
- interrupts : The CODEC's interrupt output.
Optional properties:
- clocks: The phandle of the master clock to the CODEC
- clock-names: Should be "mclk"
- #sound-dai-cells : should be 0.
- maxim,dmic-freq: Frequency at which to clock DMIC
- maxim,micbias: Micbias voltage applies to the analog mic, valid voltages value are:
0 - 2.2v
1 - 2.55v
2 - 2.4v
3 - 2.8v
Pins on the device (for linking into audio routes):
* MIC1
* MIC2
* DMICL
* DMICR
* IN1
* IN2
* IN3
* IN4
* IN5
* IN6
* IN12
* IN34
* IN56
* HPL
* HPR
* SPKL
* SPKR
* RCVL
* RCVR
* MICBIAS
Example:
audio-codec@10 {
compatible = "maxim,max98090";
reg = <0x10>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(H, 4) IRQ_TYPE_LEVEL_HIGH>;
};

View File

@ -1,22 +0,0 @@
MAX98095 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "maxim,max98095".
- reg : The I2C address of the device.
Optional properties:
- clocks: The phandle of the master clock to the CODEC
- clock-names: Should be "mclk"
Example:
max98095: codec@11 {
compatible = "maxim,max98095";
reg = <0x11>;
};

View File

@ -0,0 +1,84 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/maxim,max98090.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim Integrated MAX98090/MAX98091 audio codecs
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
description: |
Pins on the device (for linking into audio routes):
MIC1, MIC2, DMICL, DMICR, IN1, IN2, IN3, IN4, IN5, IN6, IN12, IN34, IN56,
HPL, HPR, SPKL, SPKR, RCVL, RCVR, MICBIAS
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
enum:
- maxim,max98090
- maxim,max98091
reg:
maxItems: 1
clocks:
items:
- description: master clock
clock-names:
items:
- const: mclk
interrupts:
maxItems: 1
maxim,dmic-freq:
$ref: /schemas/types.yaml#/definitions/uint32
default: 2500000
description:
DMIC clock frequency
maxim,micbias:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [ 0, 1, 2, 3 ]
default: 3
description: |
Micbias voltage applied to the analog mic, valid voltages value are:
0 - 2.2v
1 - 2.55v
2 - 2.4v
3 - 2.8v
'#sound-dai-cells':
const: 0
required:
- compatible
- reg
- interrupts
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@10 {
compatible = "maxim,max98090";
reg = <0x10>;
interrupt-parent = <&gpx3>;
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
clocks = <&i2s0 0>;
clock-names = "mclk";
#sound-dai-cells = <0>;
};
};

View File

@ -0,0 +1,54 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/maxim,max98095.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim Integrated MAX98095 audio codec
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
enum:
- maxim,max98095
reg:
maxItems: 1
clocks:
items:
- description: master clock
clock-names:
items:
- const: mclk
'#sound-dai-cells':
const: 1
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@11 {
compatible = "maxim,max98095";
reg = <0x11>;
clocks = <&i2s0 0>;
clock-names = "mclk";
};
};

View File

@ -0,0 +1,208 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mediatek,mt8188-afe.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek AFE PCM controller for mt8188
maintainers:
- Trevor Wu <trevor.wu@mediatek.com>
properties:
compatible:
const: mediatek,mt8188-afe
reg:
maxItems: 1
interrupts:
maxItems: 1
resets:
maxItems: 1
reset-names:
const: audiosys
mediatek,topckgen:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of the mediatek topckgen controller
power-domains:
maxItems: 1
clocks:
items:
- description: 26M clock
- description: audio pll1 clock
- description: audio pll2 clock
- description: clock divider for i2si1_mck
- description: clock divider for i2si2_mck
- description: clock divider for i2so1_mck
- description: clock divider for i2so2_mck
- description: clock divider for dptx_mck
- description: a1sys hoping clock
- description: audio intbus clock
- description: audio hires clock
- description: audio local bus clock
- description: mux for dptx_mck
- description: mux for i2so1_mck
- description: mux for i2so2_mck
- description: mux for i2si1_mck
- description: mux for i2si2_mck
- description: audio 26m clock
clock-names:
items:
- const: clk26m
- const: apll1
- const: apll2
- const: apll12_div0
- const: apll12_div1
- const: apll12_div2
- const: apll12_div3
- const: apll12_div9
- const: a1sys_hp_sel
- const: aud_intbus_sel
- const: audio_h_sel
- const: audio_local_bus_sel
- const: dptx_m_sel
- const: i2so1_m_sel
- const: i2so2_m_sel
- const: i2si1_m_sel
- const: i2si2_m_sel
- const: adsp_audio_26m
mediatek,etdm-in1-cowork-source:
$ref: /schemas/types.yaml#/definitions/uint32
description:
etdm modules can share the same external clock pin. Specify
which etdm clock source is required by this etdm in module.
enum:
- 1 # etdm2_in
- 2 # etdm1_out
- 3 # etdm2_out
mediatek,etdm-in2-cowork-source:
$ref: /schemas/types.yaml#/definitions/uint32
description:
etdm modules can share the same external clock pin. Specify
which etdm clock source is required by this etdm in module.
enum:
- 0 # etdm1_in
- 2 # etdm1_out
- 3 # etdm2_out
mediatek,etdm-out1-cowork-source:
$ref: /schemas/types.yaml#/definitions/uint32
description:
etdm modules can share the same external clock pin. Specify
which etdm clock source is required by this etdm out module.
enum:
- 0 # etdm1_in
- 1 # etdm2_in
- 3 # etdm2_out
mediatek,etdm-out2-cowork-source:
$ref: /schemas/types.yaml#/definitions/uint32
description:
etdm modules can share the same external clock pin. Specify
which etdm clock source is required by this etdm out module.
enum:
- 0 # etdm1_in
- 1 # etdm2_in
- 2 # etdm1_out
patternProperties:
"^mediatek,etdm-in[1-2]-chn-disabled$":
$ref: /schemas/types.yaml#/definitions/uint8-array
minItems: 1
maxItems: 16
description:
This is a list of channel IDs which should be disabled.
By default, all data received from ETDM pins will be outputed to
memory. etdm in supports disable_out in direct mode(w/o interconn),
so user can disable the specified channels by the property.
uniqueItems: true
items:
minimum: 0
maximum: 15
"^mediatek,etdm-in[1-2]-multi-pin-mode$":
type: boolean
description: if present, the etdm data mode is I2S.
"^mediatek,etdm-out[1-3]-multi-pin-mode$":
type: boolean
description: if present, the etdm data mode is I2S.
required:
- compatible
- reg
- interrupts
- resets
- reset-names
- mediatek,topckgen
- power-domains
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
afe@10b10000 {
compatible = "mediatek,mt8188-afe";
reg = <0x10b10000 0x10000>;
interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
resets = <&watchdog 14>;
reset-names = "audiosys";
mediatek,topckgen = <&topckgen>;
power-domains = <&spm 13>; //MT8188_POWER_DOMAIN_AUDIO
mediatek,etdm-in2-cowork-source = <2>;
mediatek,etdm-out2-cowork-source = <0>;
mediatek,etdm-in1-multi-pin-mode;
mediatek,etdm-in1-chn-disabled = /bits/ 8 <0x0 0x2>;
clocks = <&clk26m>,
<&apmixedsys 9>, //CLK_APMIXED_APLL1
<&apmixedsys 10>, //CLK_APMIXED_APLL2
<&topckgen 186>, //CLK_TOP_APLL12_CK_DIV0
<&topckgen 187>, //CLK_TOP_APLL12_CK_DIV1
<&topckgen 188>, //CLK_TOP_APLL12_CK_DIV2
<&topckgen 189>, //CLK_TOP_APLL12_CK_DIV3
<&topckgen 191>, //CLK_TOP_APLL12_CK_DIV9
<&topckgen 83>, //CLK_TOP_A1SYS_HP
<&topckgen 31>, //CLK_TOP_AUD_INTBUS
<&topckgen 32>, //CLK_TOP_AUDIO_H
<&topckgen 69>, //CLK_TOP_AUDIO_LOCAL_BUS
<&topckgen 81>, //CLK_TOP_DPTX
<&topckgen 77>, //CLK_TOP_I2SO1
<&topckgen 78>, //CLK_TOP_I2SO2
<&topckgen 79>, //CLK_TOP_I2SI1
<&topckgen 80>, //CLK_TOP_I2SI2
<&adsp_audio26m 0>; //CLK_AUDIODSP_AUDIO26M
clock-names = "clk26m",
"apll1",
"apll2",
"apll12_div0",
"apll12_div1",
"apll12_div2",
"apll12_div3",
"apll12_div9",
"a1sys_hp_sel",
"aud_intbus_sel",
"audio_h_sel",
"audio_local_bus_sel",
"dptx_m_sel",
"i2so1_m_sel",
"i2so2_m_sel",
"i2si1_m_sel",
"i2si2_m_sel",
"adsp_audio_26m";
};
...

View File

@ -0,0 +1,97 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mediatek,mt8188-mt6359.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MT8188 ASoC sound card
maintainers:
- Trevor Wu <trevor.wu@mediatek.com>
properties:
compatible:
const: mediatek,mt8188-mt6359-evb
model:
$ref: /schemas/types.yaml#/definitions/string
description: User specified audio sound card name
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description:
A list of the connections between audio components. Each entry is a
sink/source pair of strings. Valid names could be the input or output
widgets of audio components, power supplies, MicBias of codec and the
software switch.
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8188 ASoC platform.
patternProperties:
"^dai-link-[0-9]+$":
type: object
description:
Container for dai-link level properties and CODEC sub-nodes.
properties:
link-name:
description:
This property corresponds to the name of the BE dai-link to which
we are going to update parameters in this node.
items:
enum:
- ADDA_BE
- DPTX_BE
- ETDM1_IN_BE
- ETDM2_IN_BE
- ETDM1_OUT_BE
- ETDM2_OUT_BE
- ETDM3_OUT_BE
- PCM1_BE
codec:
description: Holds subnode which indicates codec dai.
type: object
additionalProperties: false
properties:
sound-dai:
minItems: 1
maxItems: 2
required:
- sound-dai
additionalProperties: false
required:
- link-name
- codec
additionalProperties: false
required:
- compatible
- mediatek,platform
examples:
- |
sound {
compatible = "mediatek,mt8188-mt6359-evb";
mediatek,platform = <&afe>;
pinctrl-names = "default";
pinctrl-0 = <&aud_pins_default>;
audio-routing =
"Headphone", "Headphone L",
"Headphone", "Headphone R",
"AIN1", "Headset Mic";
dai-link-0 {
link-name = "ETDM3_OUT_BE";
codec {
sound-dai = <&hdmi0>;
};
};
};
...

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mchp,i2s-mcc.yaml#
$id: http://devicetree.org/schemas/sound/microchip,sama7g5-i2smcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip I2S Multi-Channel Controller

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/microchip,pdmc.yaml#
$id: http://devicetree.org/schemas/sound/microchip,sama7g5-pdmc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip Pulse Density Microphone Controller

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mchp,spdifrx.yaml#
$id: http://devicetree.org/schemas/sound/microchip,sama7g5-spdifrx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip S/PDIF Rx Controller

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mchp,spdiftx.yaml#
$id: http://devicetree.org/schemas/sound/microchip,sama7g5-spdiftx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip S/PDIF Tx Controller

View File

@ -1,16 +0,0 @@
NAU8822 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "nuvoton,nau8822"
- reg : the I2C address of the device.
Example:
codec: nau8822@1a {
compatible = "nuvoton,nau8822";
reg = <0x1a>;
};

View File

@ -0,0 +1,46 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nuvoton,nau8822.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NAU8822 audio CODEC
description: |
24 bit stereo audio codec with speaker driver.
This device supports I2C/SPI.
maintainers:
- David Lin <CTLIN0@nuvoton.com>
properties:
compatible:
enum:
- nuvoton,nau8822
reg:
maxItems: 1
nuvoton,spk-btl:
description:
If set, configure the two loudspeaker outputs as a Bridge Tied Load output
to drive a high power external loudspeaker.
$ref: /schemas/types.yaml#/definitions/flag
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
codec@1a {
compatible = "nuvoton,nau8822";
reg = <0x1a>;
};
};

View File

@ -35,7 +35,7 @@ properties:
clocks:
minItems: 3
maxItems: 7
maxItems: 10
clock-names:
minItems: 1
@ -65,6 +65,9 @@ properties:
power-domain-names:
maxItems: 1
required-opps:
maxItems: 1
'#sound-dai-cells':
const: 1
@ -75,7 +78,7 @@ properties:
const: 0
patternProperties:
"^dai-link@[0-9a-f]$":
"^dai-link@[0-9a-f]+$":
type: object
description: |
LPASS CPU dai node for each I2S device or Soundwire device. Bindings of each node
@ -121,6 +124,8 @@ allOf:
then:
properties:
clocks:
maxItems: 3
clock-names:
items:
- const: ahbix-clk
@ -135,6 +140,9 @@ allOf:
then:
properties:
clocks:
minItems: 7
maxItems: 7
clock-names:
items:
- const: ahbix-clk
@ -153,33 +161,31 @@ allOf:
then:
properties:
clocks:
minItems: 6
maxItems: 6
clock-names:
oneOf:
- items: #for I2S
- const: pcnoc-sway-clk
- const: audio-core
- const: mclk0
- const: pcnoc-mport-clk
- const: mi2s-bit-clk0
- const: mi2s-bit-clk1
- items: #for HDMI
- const: pcnoc-sway-clk
- const: audio-core
- const: pcnoc-mport-clk
items:
- const: pcnoc-sway-clk
- const: audio-core
- const: mclk0
- const: pcnoc-mport-clk
- const: mi2s-bit-clk0
- const: mi2s-bit-clk1
reg:
minItems: 2
maxItems: 2
reg-names:
anyOf:
- items: #for I2S
- const: lpass-lpaif
- items: #for I2S and HDMI
- const: lpass-hdmiif
- const: lpass-lpaif
items:
- const: lpass-hdmiif
- const: lpass-lpaif
interrupts:
minItems: 2
maxItems: 2
interrupt-names:
anyOf:
- items: #for I2S
- const: lpass-irq-lpaif
- items: #for I2S and HDMI
- const: lpass-irq-lpaif
- const: lpass-irq-hdmi
items:
- const: lpass-irq-lpaif
- const: lpass-irq-hdmi
required:
- iommus
- power-domains
@ -192,54 +198,44 @@ allOf:
then:
properties:
clocks:
minItems: 10
maxItems: 10
clock-names:
oneOf:
- items: #for I2S
- const: aon_cc_audio_hm_h
- const: audio_cc_ext_mclk0
- const: core_cc_sysnoc_mport_core
- const: core_cc_ext_if0_ibit
- const: core_cc_ext_if1_ibit
- items: #for Soundwire
- const: aon_cc_audio_hm_h
- const: audio_cc_codec_mem
- const: audio_cc_codec_mem0
- const: audio_cc_codec_mem1
- const: audio_cc_codec_mem2
- const: aon_cc_va_mem0
- items: #for HDMI
- const: core_cc_sysnoc_mport_core
items:
- const: aon_cc_audio_hm_h
- const: audio_cc_ext_mclk0
- const: core_cc_sysnoc_mport_core
- const: core_cc_ext_if0_ibit
- const: core_cc_ext_if1_ibit
- const: audio_cc_codec_mem
- const: audio_cc_codec_mem0
- const: audio_cc_codec_mem1
- const: audio_cc_codec_mem2
- const: aon_cc_va_mem0
reg:
minItems: 6
maxItems: 6
reg-names:
anyOf:
- items: #for I2S
- const: lpass-lpaif
- items: #for I2S and HDMI
- const: lpass-hdmiif
- const: lpass-lpaif
- items: #for I2S, soundwire and HDMI
- const: lpass-hdmiif
- const: lpass-lpaif
- const: lpass-rxtx-cdc-dma-lpm
- const: lpass-rxtx-lpaif
- const: lpass-va-lpaif
- const: lpass-va-cdc-dma-lpm
items:
- const: lpass-hdmiif
- const: lpass-lpaif
- const: lpass-rxtx-cdc-dma-lpm
- const: lpass-rxtx-lpaif
- const: lpass-va-lpaif
- const: lpass-va-cdc-dma-lpm
interrupts:
minItems: 4
maxItems: 4
interrupt-names:
anyOf:
- items: #for I2S
- const: lpass-irq-lpaif
- items: #for I2S and HDMI
- const: lpass-irq-lpaif
- const: lpass-irq-hdmi
- items: #for I2S, soundwire and HDMI
- const: lpass-irq-lpaif
- const: lpass-irq-hdmi
- const: lpass-irq-vaif
- const: lpass-irq-rxtxif
items:
- const: lpass-irq-lpaif
- const: lpass-irq-hdmi
- const: lpass-irq-vaif
- const: lpass-irq-rxtxif
power-domain-names:
allOf:
- items:
- const: lcx
items:
- const: lcx
required:
- iommus

View File

@ -36,7 +36,7 @@ properties:
oneOf:
- items: #for ADSP based platforms
- const: mclk
- const: core
- const: macro
- const: dcodec
- items: #for ADSP bypass based platforms
- const: mclk
@ -77,7 +77,7 @@ examples:
clocks = <&aoncc 0>,
<&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
clock-names = "mclk", "core", "dcodec";
clock-names = "mclk", "macro", "dcodec";
clock-output-names = "fsgen";
qcom,dmic-sample-rate = <600000>;
vdd-micb-supply = <&vreg_s4a_1p8>;

View File

@ -17,7 +17,8 @@ properties:
const: qcom,q6apm-dais
iommus:
maxItems: 1
minItems: 1
maxItems: 2
required:
- compatible

View File

@ -15,16 +15,20 @@ description:
properties:
compatible:
enum:
- lenovo,yoga-c630-sndcard
- qcom,apq8016-sbc-sndcard
- qcom,db845c-sndcard
- qcom,msm8916-qdsp6-sndcard
- qcom,qrb5165-rb5-sndcard
- qcom,sc8280xp-sndcard
- qcom,sdm845-sndcard
- qcom,sm8250-sndcard
- qcom,sm8450-sndcard
oneOf:
- items:
- enum:
- lenovo,yoga-c630-sndcard
- qcom,db845c-sndcard
- const: qcom,sdm845-sndcard
- enum:
- qcom,apq8016-sbc-sndcard
- qcom,msm8916-qdsp6-sndcard
- qcom,qrb5165-rb5-sndcard
- qcom,sc8280xp-sndcard
- qcom,sdm845-sndcard
- qcom,sm8250-sndcard
- qcom,sm8450-sndcard
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array

View File

@ -28,7 +28,9 @@ properties:
description: GPIO spec for reset line to use
maxItems: 1
slim-ifc-dev: true
slim-ifc-dev:
description: IFC device interface
$ref: /schemas/types.yaml#/definitions/phandle
clocks:
maxItems: 1
@ -147,21 +149,49 @@ patternProperties:
required:
- compatible
- reg
- reset-gpios
- slim-ifc-dev
- interrupts
- interrupt-controller
- clock-frequency
- clock-output-names
- qcom,micbias1-microvolt
- qcom,micbias2-microvolt
- qcom,micbias3-microvolt
- qcom,micbias4-microvolt
- "#interrupt-cells"
- "#clock-cells"
- "#sound-dai-cells"
- "#address-cells"
- "#size-cells"
allOf:
- if:
required:
- slim-ifc-dev
then:
required:
- reset-gpios
- slim-ifc-dev
- interrupt-controller
- clock-frequency
- clock-output-names
- qcom,micbias1-microvolt
- qcom,micbias2-microvolt
- qcom,micbias3-microvolt
- qcom,micbias4-microvolt
- "#interrupt-cells"
- "#clock-cells"
- "#sound-dai-cells"
- "#address-cells"
- "#size-cells"
oneOf:
- required:
- interrupts-extended
- required:
- interrupts
else:
properties:
reset-gpios: false
slim-ifc-dev: false
interrupts: false
interrupt-controller: false
clock-frequency: false
clock-output-names: false
qcom,micbias1-microvolt: false
qcom,micbias2-microvolt: false
qcom,micbias3-microvolt: false
qcom,micbias4-microvolt: false
"#interrupt-cells": false
"#clock-cells": false
"#sound-dai-cells": false
"#address-cells": false
"#size-cells": false
additionalProperties: false

View File

@ -15,6 +15,9 @@ description: |
Their primary operating mode uses a SoundWire digital audio
interface. This binding is for SoundWire interface.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: sdw10217201000
@ -39,7 +42,7 @@ required:
- "#thermal-sensor-cells"
- "#sound-dai-cells"
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -0,0 +1,75 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/renesas,idt821034.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas IDT821034 codec device
maintainers:
- Herve Codina <herve.codina@bootlin.com>
description: |
The IDT821034 codec is a four channel PCM codec with onchip filters and
programmable gain setting.
The time-slots used by the codec must be set and so, the properties
'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
sub-nodes that involve the codec. The codec uses one 8bit time-slot per
channel.
'dai-tdm-tdm-slot-with' must be set to 8.
The IDT821034 codec also supports 5 gpios (SLIC signals) per channel.
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
- $ref: dai-common.yaml#
properties:
compatible:
const: renesas,idt821034
reg:
description:
SPI device address.
maxItems: 1
spi-max-frequency:
maximum: 8192000
spi-cpha: true
'#sound-dai-cells':
const: 0
'#gpio-cells':
const: 2
gpio-controller: true
required:
- compatible
- reg
- spi-cpha
- '#sound-dai-cells'
- gpio-controller
- '#gpio-cells'
unevaluatedProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@0 {
compatible = "renesas,idt821034";
reg = <0>;
spi-max-frequency = <8192000>;
spi-cpha;
#sound-dai-cells = <0>;
gpio-controller;
#gpio-cells = <2>;
};
};

View File

@ -18,8 +18,7 @@ properties:
- enum:
- renesas,rcar_sound-r8a7778 # R-Car M1A
- renesas,rcar_sound-r8a7779 # R-Car H1
- enum:
- renesas,rcar_sound-gen1
- const: renesas,rcar_sound-gen1
# for Gen2 SoC
- items:
- enum:
@ -32,8 +31,7 @@ properties:
- renesas,rcar_sound-r8a7791 # R-Car M2-W
- renesas,rcar_sound-r8a7793 # R-Car M2-N
- renesas,rcar_sound-r8a7794 # R-Car E2
- enum:
- renesas,rcar_sound-gen2
- const: renesas,rcar_sound-gen2
# for Gen3 SoC
- items:
- enum:
@ -47,14 +45,16 @@ properties:
- renesas,rcar_sound-r8a77965 # R-Car M3-N
- renesas,rcar_sound-r8a77990 # R-Car E3
- renesas,rcar_sound-r8a77995 # R-Car D3
- enum:
- renesas,rcar_sound-gen3
# for Generic
- const: renesas,rcar_sound-gen3
# for Gen4 SoC
- items:
- enum:
- renesas,rcar_sound-gen1
- renesas,rcar_sound-gen2
- renesas,rcar_sound-gen3
- const: renesas,rcar_sound-r8a779g0 # R-Car V4H
- const: renesas,rcar_sound-gen4
# for Generic
- enum:
- renesas,rcar_sound-gen1
- renesas,rcar_sound-gen2
- renesas,rcar_sound-gen3
reg:
minItems: 1
@ -68,6 +68,7 @@ properties:
description: |
it must be 0 if your system is using single DAI
it must be 1 if your system is using multi DAIs
This is used on simple-audio-card
enum: [0, 1]
"#clock-cells":
@ -113,15 +114,34 @@ properties:
- pattern: '^clk_(a|b|c|i)$'
ports:
$ref: /schemas/graph.yaml#/properties/ports
$ref: audio-graph-port.yaml#/definitions/port-base
unevaluatedProperties: false
patternProperties:
'^port(@[0-9a-f]+)?$':
$ref: audio-graph-port.yaml#
$ref: audio-graph-port.yaml#/definitions/port-base
unevaluatedProperties: false
patternProperties:
"^endpoint(@[0-9a-f]+)?":
$ref: audio-graph-port.yaml#/definitions/endpoint-base
properties:
playback:
$ref: /schemas/types.yaml#/definitions/phandle-array
capture:
$ref: /schemas/types.yaml#/definitions/phandle-array
unevaluatedProperties: false
port:
$ref: audio-graph-port.yaml#
$ref: audio-graph-port.yaml#/definitions/port-base
unevaluatedProperties: false
patternProperties:
"^endpoint(@[0-9a-f]+)?":
$ref: audio-graph-port.yaml#/definitions/endpoint-base
properties:
playback:
$ref: /schemas/types.yaml#/definitions/phandle-array
capture:
$ref: /schemas/types.yaml#/definitions/phandle-array
unevaluatedProperties: false
rcar_sound,dvc:
description: DVC subnode.
@ -178,10 +198,6 @@ properties:
enum:
- tx
- rx
required:
- interrupts
- dmas
- dma-names
additionalProperties: false
rcar_sound,ssiu:
@ -240,8 +256,6 @@ properties:
$ref: /schemas/types.yaml#/definitions/flag
required:
- interrupts
- dmas
- dma-names
additionalProperties: false
# For DAI base
@ -271,7 +285,6 @@ required:
- reg-names
- clocks
- clock-names
- "#sound-dai-cells"
allOf:
- $ref: dai-common.yaml#
@ -285,7 +298,6 @@ allOf:
reg:
maxItems: 3
reg-names:
maxItems: 3
items:
enum:
- scu
@ -294,9 +306,8 @@ allOf:
else:
properties:
reg:
maxItems: 5
minItems: 5
reg-names:
maxItems: 5
items:
enum:
- scu

View File

@ -20,6 +20,9 @@ Optional properties:
- realtek,in3-differential
Boolean. Indicate MIC1/2/3 input are differential, rather than single-ended.
- realtek,lout-differential
Boolean. Indicate LOUT output is differential, rather than stereo.
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
- realtek,dmic1-data-pin

View File

@ -43,9 +43,10 @@ properties:
type: object
properties:
sound-dai:
minItems: 1
items:
- description: phandle of the MAX98090 CODEC
- description: phandle of the HDMI IP block node
- description: phandle of the MAX98090 CODEC
samsung,audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array

View File

@ -37,12 +37,20 @@ properties:
samsung,exynos7-i2s1: I2S1 on previous samsung platforms supports
stereo channels. Exynos7 I2S1 upgraded to 5.1 multichannel with
slightly modified bit offsets.
tesla,fsd-i2s: for 8/16/24bit stereo channel I2S for playback and
capture, secondary FIFO using external DMA, s/w reset control,
internal mux for root clock source with all root clock sampling
frequencies supported by Exynos7 I2S and 7.1 channel TDM support
for playback and capture TDM (Time division multiplexing) to allow
transfer of multiple channel audio data on single data line.
enum:
- samsung,s3c6410-i2s
- samsung,s5pv210-i2s
- samsung,exynos5420-i2s
- samsung,exynos7-i2s
- samsung,exynos7-i2s1
- tesla,fsd-i2s
'#address-cells':
const: 1
@ -67,9 +75,6 @@ properties:
- const: rx
- const: tx-sec
assigned-clock-parents: true
assigned-clocks: true
clocks:
minItems: 1
maxItems: 3

View File

@ -205,6 +205,8 @@ patternProperties:
$ref: "#/definitions/dai"
"^simple-audio-card,codec(@[0-9a-f]+)?$":
$ref: "#/definitions/dai"
"^simple-audio-card,plat(@[0-9a-f]+)?$":
$ref: "#/definitions/dai"
"^simple-audio-card,dai-link(@[0-9a-f]+)?$":
description: |
@ -215,6 +217,10 @@ patternProperties:
reg:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 0
# common properties
frame-master:
$ref: "#/definitions/frame-master"
@ -244,9 +250,9 @@ patternProperties:
maxItems: 1
patternProperties:
"^cpu(@[0-9a-f]+)?":
"^cpu(-[0-9]+)?$":
$ref: "#/definitions/dai"
"^codec(@[0-9a-f]+)?":
"^codec(-[0-9]+)?$":
$ref: "#/definitions/dai"
additionalProperties: false
@ -462,16 +468,16 @@ examples:
convert-channels = <8>; /* TDM Split */
sndcpu1: cpu0 {
sndcpu1: cpu-0 {
sound-dai = <&rcar_sound 1>;
};
cpu1 {
cpu-1 {
sound-dai = <&rcar_sound 2>;
};
cpu2 {
cpu-2 {
sound-dai = <&rcar_sound 3>;
};
cpu3 {
cpu-3 {
sound-dai = <&rcar_sound 4>;
};
codec {

View File

@ -6,11 +6,13 @@ audio playback. For more product information please see the links below:
https://www.ti.com/product/TAS5720L
https://www.ti.com/product/TAS5720M
https://www.ti.com/product/TAS5720A-Q1
https://www.ti.com/product/TAS5722L
Required properties:
- compatible : "ti,tas5720",
"ti,tas5720a-q1",
"ti,tas5722"
- reg : I2C slave address
- dvdd-supply : phandle to a 3.3-V supply for the digital circuitry

View File

@ -1,56 +0,0 @@
Texas Instruments pcm3168a DT bindings
This driver supports both SPI and I2C bus access for this codec
Required properties:
- compatible: "ti,pcm3168a"
- clocks : Contains an entry for each entry in clock-names
- clock-names : Includes the following entries:
"scki" The system clock
- VDD1-supply : Digital power supply regulator 1 (+3.3V)
- VDD2-supply : Digital power supply regulator 2 (+3.3V)
- VCCAD1-supply : ADC power supply regulator 1 (+5V)
- VCCAD2-supply : ADC power supply regulator 2 (+5V)
- VCCDA1-supply : DAC power supply regulator 1 (+5V)
- VCCDA2-supply : DAC power supply regulator 2 (+5V)
For required properties on SPI/I2C, consult SPI/I2C device tree documentation
Optional properties:
- reset-gpios : Optional reset gpio line connected to RST pin of the codec.
The RST line is low active:
RST = low: device power-down
RST = high: device is enabled
Examples:
i2c0: i2c0@0 {
...
pcm3168a: audio-codec@44 {
compatible = "ti,pcm3168a";
reg = <0x44>;
reset-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
clocks = <&clk_core CLK_AUDIO>;
clock-names = "scki";
VDD1-supply = <&supply3v3>;
VDD2-supply = <&supply3v3>;
VCCAD1-supply = <&supply5v0>;
VCCAD2-supply = <&supply5v0>;
VCCDA1-supply = <&supply5v0>;
VCCDA2-supply = <&supply5v0>;
pinctrl-names = "default";
pinctrl-0 = <&dac_clk_pin>;
};
};

View File

@ -0,0 +1,107 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,pcm3168a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments PCM3168A Audio Codec
maintainers:
- Damien Horsley <Damien.Horsley@imgtec.com>
- Geert Uytterhoeven <geert+renesas@glider.be>
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
description:
The Texas Instruments PCM3168A is a 24-bit Multi-channel Audio CODEC with
96/192kHz sampling rate, supporting both SPI and I2C bus access.
properties:
compatible:
const: ti,pcm3168a
reg:
maxItems: 1
clocks:
items:
- description: System clock input
clock-names:
items:
- const: scki
reset-gpios:
items:
- description: |
GPIO line connected to the active-low RST pin of the codec.
RST = low: device power-down
RST = high: device is enabled
"#sound-dai-cells":
enum: [0, 1]
VDD1-supply:
description: Digital power supply regulator 1 (+3.3V)
VDD2-supply:
description: Digital power supply regulator 2 (+3.3V)
VCCAD1-supply:
description: ADC power supply regulator 1 (+5V)
VCCAD2-supply:
description: ADC power supply regulator 2 (+5V)
VCCDA1-supply:
description: DAC power supply regulator 1 (+5V)
VCCDA2-supply:
description: DAC power supply regulator 2 (+5V)
ports:
$ref: audio-graph-port.yaml#/definitions/port-base
properties:
port@0:
$ref: audio-graph-port.yaml#
description: Audio input port.
port@1:
$ref: audio-graph-port.yaml#
description: Audio output port.
required:
- compatible
- reg
- clocks
- clock-names
- VDD1-supply
- VDD2-supply
- VCCAD1-supply
- VCCAD2-supply
- VCCDA1-supply
- VCCDA2-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pcm3168a: audio-codec@44 {
compatible = "ti,pcm3168a";
reg = <0x44>;
reset-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
clocks = <&clk_core 42>;
clock-names = "scki";
VDD1-supply = <&supply3v3>;
VDD2-supply = <&supply3v3>;
VCCAD1-supply = <&supply5v0>;
VCCAD2-supply = <&supply5v0>;
VCCDA1-supply = <&supply5v0>;
VCCDA2-supply = <&supply5v0>;
};
};

View File

@ -0,0 +1,165 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
# Copyright (C) 2022 Texas Instruments Incorporated
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,tlv320aic3x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TLV320AIC3x Codec
description: |
TLV320AIC3x are a series of low-power stereo audio codecs with stereo
headphone amplifier, as well as multiple inputs and outputs programmable in
single-ended or fully differential configurations.
The serial control bus supports SPI or I2C protocols, while the serial audio
data bus is programmable for I2S, left/right-justified, DSP, or TDM modes.
The following pins can be referred in the sound node's audio routing property:
CODEC output pins:
LLOUT
RLOUT
MONO_LOUT
HPLOUT
HPROUT
HPLCOM
HPRCOM
CODEC input pins for TLV320AIC3104:
MIC2L
MIC2R
LINE1L
LINE1R
CODEC input pins for other compatible codecs:
MIC3L
MIC3R
LINE1L
LINE2L
LINE1R
LINE2R
maintainers:
- Jai Luthra <j-luthra@ti.com>
properties:
compatible:
enum:
- ti,tlv320aic3x
- ti,tlv320aic33
- ti,tlv320aic3007
- ti,tlv320aic3106
- ti,tlv320aic3104
reg:
maxItems: 1
reset-gpios:
maxItems: 1
description:
GPIO specification for the active low RESET input.
gpio-reset:
maxItems: 1
description:
Deprecated, please use reset-gpios instead.
deprecated: true
ai3x-gpio-func:
description: AIC3X_GPIO1 & AIC3X_GPIO2 Functionality
$ref: /schemas/types.yaml#/definitions/uint32-array
maxItems: 2
ai3x-micbias-vg:
description: MicBias required voltage. If node is omitted then MicBias is powered down.
$ref: /schemas/types.yaml#/definitions/uint32
oneOf:
- const: 1
description: MICBIAS output is powered to 2.0V.
- const: 2
description: MICBIAS output is powered to 2.5V.
- const: 3
description: MICBIAS output is connected to AVDD.
ai3x-ocmv:
description: Output Common-Mode Voltage selection.
$ref: /schemas/types.yaml#/definitions/uint32
oneOf:
- const: 0
description: 1.35V
- const: 1
description: 1.5V
- const: 2
description: 1.65V
- const: 3
description: 1.8V
AVDD-supply:
description: Analog DAC voltage.
IOVDD-supply:
description: I/O voltage.
DRVDD-supply:
description: ADC analog and output driver voltage.
DVDD-supply:
description: Digital core voltage.
'#sound-dai-cells':
const: 0
clocks:
maxItems: 1
port:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
required:
- compatible
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
tlv320aic3x_i2c: audio-codec@1b {
compatible = "ti,tlv320aic3x";
reg = <0x1b>;
reset-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
AVDD-supply = <&regulator>;
IOVDD-supply = <&regulator>;
DRVDD-supply = <&regulator>;
DVDD-supply = <&regulator>;
};
};
- |
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
tlv320aic3x_spi: audio-codec@0 {
compatible = "ti,tlv320aic3x";
reg = <0>; /* CS number */
#sound-dai-cells = <0>;
AVDD-supply = <&regulator>;
IOVDD-supply = <&regulator>;
DRVDD-supply = <&regulator>;
DVDD-supply = <&regulator>;
ai3x-ocmv = <0>;
};
};
...

View File

@ -1,97 +0,0 @@
Texas Instruments - tlv320aic3x Codec module
The tlv320aic3x serial control bus communicates through both I2C and SPI bus protocols
Required properties:
- compatible - "string" - One of:
"ti,tlv320aic3x" - Generic TLV320AIC3x device
"ti,tlv320aic33" - TLV320AIC33
"ti,tlv320aic3007" - TLV320AIC3007
"ti,tlv320aic3106" - TLV320AIC3106
"ti,tlv320aic3104" - TLV320AIC3104
- reg - <int> - I2C slave address
Optional properties:
- reset-gpios - GPIO specification for the active low RESET input.
- ai3x-gpio-func - <array of 2 int> - AIC3X_GPIO1 & AIC3X_GPIO2 Functionality
- Not supported on tlv320aic3104
- ai3x-micbias-vg - MicBias Voltage required.
1 - MICBIAS output is powered to 2.0V,
2 - MICBIAS output is powered to 2.5V,
3 - MICBIAS output is connected to AVDD,
If this node is not mentioned or if the value is incorrect, then MicBias
is powered down.
- ai3x-ocmv - Output Common-Mode Voltage selection:
0 - 1.35V,
1 - 1.5V,
2 - 1.65V,
3 - 1.8V
- AVDD-supply, IOVDD-supply, DRVDD-supply, DVDD-supply : power supplies for the
device as covered in Documentation/devicetree/bindings/regulator/regulator.txt
Deprecated properties:
- gpio-reset - gpio pin number used for codec reset
CODEC output pins:
* LLOUT
* RLOUT
* MONO_LOUT
* HPLOUT
* HPROUT
* HPLCOM
* HPRCOM
CODEC input pins for TLV320AIC3104:
* MIC2L
* MIC2R
* LINE1L
* LINE1R
CODEC input pins for other compatible codecs:
* MIC3L
* MIC3R
* LINE1L
* LINE2L
* LINE1R
* LINE2R
The pins can be used in referring sound node's audio-routing property.
I2C example:
#include <dt-bindings/gpio/gpio.h>
tlv320aic3x: tlv320aic3x@1b {
compatible = "ti,tlv320aic3x";
reg = <0x1b>;
reset-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
AVDD-supply = <&regulator>;
IOVDD-supply = <&regulator>;
DRVDD-supply = <&regulator>;
DVDD-supply = <&regulator>;
};
SPI example:
spi0: spi@f0000000 {
tlv320aic3x: codec@0 {
compatible = "ti,tlv320aic3x";
reg = <0>; /* CS number */
#sound-dai-cells = <0>;
spi-max-frequency = <1000000>;
AVDD-supply = <&regulator>;
IOVDD-supply = <&regulator>;
DRVDD-supply = <&regulator>;
DVDD-supply = <&regulator>;
ai3x-ocmv = <0>;
};
};

View File

@ -635,6 +635,8 @@ patternProperties:
description: Inverse Path
"^iom,.*":
description: Iomega Corporation
"^irondevice,.*":
description: Iron Device Corporation
"^isee,.*":
description: ISEE 2007 S.L.
"^isil,.*":

View File

@ -10166,6 +10166,13 @@ L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/pressure/dps310.c
INFINEON PEB2466 ASoC CODEC
M: Herve Codina <herve.codina@bootlin.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/infineon,peb2466.yaml
F: sound/soc/codecs/peb2466.c
INFINIBAND SUBSYSTEM
M: Jason Gunthorpe <jgg@nvidia.com>
M: Leon Romanovsky <leonro@nvidia.com>
@ -10927,6 +10934,13 @@ M: David Sterba <dsterba@suse.com>
S: Odd Fixes
F: drivers/tty/ipwireless/
IRON DEVICE AUDIO CODEC DRIVERS
M: Kiseok Jo <kiseok.jo@irondevice.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/irondevice,*
F: sound/soc/codecs/sma*
IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
M: Marc Zyngier <maz@kernel.org>
S: Maintained
@ -17803,6 +17817,13 @@ F: Documentation/devicetree/bindings/net/renesas,*.yaml
F: drivers/net/ethernet/renesas/
F: include/linux/sh_eth.h
RENESAS IDT821034 ASoC CODEC
M: Herve Codina <herve.codina@bootlin.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/renesas,idt821034.yaml
F: sound/soc/codecs/idt821034.c
RENESAS R-CAR GYROADC DRIVER
M: Marek Vasut <marek.vasut@gmail.com>
L: linux-iio@vger.kernel.org

View File

@ -469,7 +469,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
}
/* Inform slave about the impending port prepare */
sdw_do_port_prep(s_rt, prep_ch, SDW_OPS_PORT_PRE_PREP);
sdw_do_port_prep(s_rt, prep_ch, prep ? SDW_OPS_PORT_PRE_PREP : SDW_OPS_PORT_PRE_DEPREP);
/* Prepare Slave port implementing CP_SM */
if (!dpn_prop->simple_ch_prep_sm) {
@ -501,7 +501,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
}
/* Inform slaves about ports prepared */
sdw_do_port_prep(s_rt, prep_ch, SDW_OPS_PORT_POST_PREP);
sdw_do_port_prep(s_rt, prep_ch, prep ? SDW_OPS_PORT_POST_PREP : SDW_OPS_PORT_POST_DEPREP);
/* Disable interrupt after Port de-prepare */
if (!prep && intr)

View File

@ -1,20 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
*/
#ifndef __MSP_H
#define __MSP_H
#include <linux/platform_data/dma-ste-dma40.h>
/* Platform data structure for a MSP I2S-device */
struct msp_i2s_platform_data {
int id;
struct stedma40_chan_cfg *msp_i2s_dma_rx;
struct stedma40_chan_cfg *msp_i2s_dma_tx;
};
#endif

View File

@ -566,13 +566,15 @@ struct sdw_prepare_ch {
* enum sdw_port_prep_ops: Prepare operations for Data Port
*
* @SDW_OPS_PORT_PRE_PREP: Pre prepare operation for the Port
* @SDW_OPS_PORT_PREP: Prepare operation for the Port
* @SDW_OPS_PORT_PRE_DEPREP: Pre deprepare operation for the Port
* @SDW_OPS_PORT_POST_PREP: Post prepare operation for the Port
* @SDW_OPS_PORT_POST_DEPREP: Post deprepare operation for the Port
*/
enum sdw_port_prep_ops {
SDW_OPS_PORT_PRE_PREP = 0,
SDW_OPS_PORT_PREP = 1,
SDW_OPS_PORT_POST_PREP = 2,
SDW_OPS_PORT_PRE_DEPREP,
SDW_OPS_PORT_POST_PREP,
SDW_OPS_PORT_POST_DEPREP,
};
/**

View File

@ -126,24 +126,24 @@
#define ACP_PAD_PULLDOWN_CTRL 0x0001448
#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x000144C
#define ACP_PAD_SCHMEN_CTRL 0x0001450
#define ACP_SW_PAD_KEEPER_EN 0x0001454
#define ACP_SW_WAKE_EN 0x0001458
#define ACP_SW0_PAD_KEEPER_EN 0x0001454
#define ACP_SW0_WAKE_EN 0x0001458
#define ACP_I2S_WAKE_EN 0x000145C
#define ACP_SW1_WAKE_EN 0x0001460
#define ACP_SW_I2S_ERROR_REASON 0x00018B4
#define ACP_SW_POS_TRACK_I2S_TX_CTRL 0x00018B8
#define ACP_SW_I2S_TX_DMA_POS 0x00018BC
#define ACP_SW_POS_TRACK_BT_TX_CTRL 0x00018C0
#define ACP_SW_BT_TX_DMA_POS 0x00018C4
#define ACP_SW_POS_TRACK_HS_TX_CTRL 0x00018C8
#define ACP_SW_HS_TX_DMA_POS 0x00018CC
#define ACP_SW_POS_TRACK_I2S_RX_CTRL 0x00018D0
#define ACP_SW_I2S_RX_DMA_POS 0x00018D4
#define ACP_SW_POS_TRACK_BT_RX_CTRL 0x00018D8
#define ACP_SW_BT_RX_DMA_POS 0x00018DC
#define ACP_SW_POS_TRACK_HS_RX_CTRL 0x00018E0
#define ACP_SW_HS_RX_DMA_POS 0x00018E4
#define ACP_SW0_I2S_ERROR_REASON 0x00018B4
#define ACP_SW0_POS_TRACK_AUDIO0_TX_CTRL 0x00018B8
#define ACP_SW0_AUDIO0_TX_DMA_POS 0x00018BC
#define ACP_SW0_POS_TRACK_AUDIO1_TX_CTRL 0x00018C0
#define ACP_SW0_AUDIO1_TX_DMA_POS 0x00018C4
#define ACP_SW0_POS_TRACK_AUDIO2_TX_CTRL 0x00018C8
#define ACP_SW0_AUDIO2_TX_DMA_POS 0x00018CC
#define ACP_SW0_POS_TRACK_AUDIO0_RX_CTRL 0x00018D0
#define ACP_SW0_AUDIO0_DMA_POS 0x00018D4
#define ACP_SW0_POS_TRACK_AUDIO1_RX_CTRL 0x00018D8
#define ACP_SW0_AUDIO1_RX_DMA_POS 0x00018DC
#define ACP_SW0_POS_TRACK_AUDIO2_RX_CTRL 0x00018E0
#define ACP_SW0_AUDIO2_RX_DMA_POS 0x00018E4
#define ACP_ERROR_INTR_MASK1 0X0001974
#define ACP_ERROR_INTR_MASK2 0X0001978
#define ACP_ERROR_INTR_MASK3 0X000197C
@ -155,98 +155,80 @@
#define ACP_EXTERNAL_INTR_STAT 0x0001A0C
#define ACP_EXTERNAL_INTR_STAT1 0x0001A10
#define ACP_ERROR_STATUS 0x0001A4C
#define ACP_P1_SW_I2S_ERROR_REASON 0x0001A50
#define ACP_P1_SW_POS_TRACK_I2S_TX_CTRL 0x0001A6C
#define ACP_P1_SW_I2S_TX_DMA_POS 0x0001A70
#define ACP_P1_SW_POS_TRACK_I2S_RX_CTRL 0x0001A74
#define ACP_P1_SW_I2S_RX_DMA_POS 0x0001A78
#define ACP_SW1_I2S_ERROR_REASON 0x0001A50
#define ACP_SW1_POS_TRACK_AUDIO0_TX_CTRL 0x0001A6C
#define ACP_SW1_AUDIO0_TX_DMA_POS 0x0001A70
#define ACP_SW1_POS_TRACK_AUDIO0_RX_CTRL 0x0001A74
#define ACP_SW1_AUDIO0_RX_DMA_POS 0x0001A78
#define ACP_P1_DMIC_I2S_GPIO_INTR_CTRL 0x0001A7C
#define ACP_P1_DMIC_I2S_GPIO_INTR_STATUS 0x0001A80
#define ACP_SCRATCH_REG_BASE_ADDR 0x0001A84
#define ACP_P1_SW_POS_TRACK_BT_TX_CTRL 0x0001A88
#define ACP_P1_SW_BT_TX_DMA_POS 0x0001A8C
#define ACP_P1_SW_POS_TRACK_HS_TX_CTRL 0x0001A90
#define ACP_P1_SW_HS_TX_DMA_POS 0x0001A94
#define ACP_P1_SW_POS_TRACK_BT_RX_CTRL 0x0001A98
#define ACP_P1_SW_BT_RX_DMA_POS 0x0001A9C
#define ACP_P1_SW_POS_TRACK_HS_RX_CTRL 0x0001AA0
#define ACP_P1_SW_HS_RX_DMA_POS 0x0001AA4
#define ACP_SW1_POS_TRACK_AUDIO1_TX_CTRL 0x0001A88
#define ACP_SW1_AUDIO1_TX_DMA_POS 0x0001A8C
#define ACP_SW1_POS_TRACK_AUDIO2_TX_CTRL 0x0001A90
#define ACP_SW1_AUDIO2_TX_DMA_POS 0x0001A94
#define ACP_SW1_POS_TRACK_AUDIO1_RX_CTRL 0x0001A98
#define ACP_SW1_AUDIO1_RX_DMA_POS 0x0001A9C
#define ACP_SW1_POS_TRACK_AUDIO2_RX_CTRL 0x0001AA0
#define ACP_SW1_AUDIO2_RX_DMA_POS 0x0001AA4
#define ACP_ERROR_INTR_MASK4 0X0001AEC
#define ACP_ERROR_INTR_MASK5 0X0001AF0
/* Registers from ACP_AUDIO_BUFFERS block */
#define ACP_I2S_RX_RINGBUFADDR 0x0002000
#define ACP_I2S_RX_RINGBUFSIZE 0x0002004
#define ACP_I2S_RX_LINKPOSITIONCNTR 0x0002008
#define ACP_I2S_RX_FIFOADDR 0x000200C
#define ACP_I2S_RX_FIFOSIZE 0x0002010
#define ACP_I2S_RX_DMA_SIZE 0x0002014
#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x0002018
#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x000201C
#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x0002020
#define ACP_I2S_TX_RINGBUFADDR 0x0002024
#define ACP_I2S_TX_RINGBUFSIZE 0x0002028
#define ACP_I2S_TX_LINKPOSITIONCNTR 0x000202C
#define ACP_I2S_TX_FIFOADDR 0x0002030
#define ACP_I2S_TX_FIFOSIZE 0x0002034
#define ACP_I2S_TX_DMA_SIZE 0x0002038
#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x000203C
#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x0002040
#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x0002044
#define ACP_BT_RX_RINGBUFADDR 0x0002048
#define ACP_BT_RX_RINGBUFSIZE 0x000204C
#define ACP_BT_RX_LINKPOSITIONCNTR 0x0002050
#define ACP_BT_RX_FIFOADDR 0x0002054
#define ACP_BT_RX_FIFOSIZE 0x0002058
#define ACP_BT_RX_DMA_SIZE 0x000205C
#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x0002060
#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x0002064
#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x0002068
#define ACP_BT_TX_RINGBUFADDR 0x000206C
#define ACP_BT_TX_RINGBUFSIZE 0x0002070
#define ACP_BT_TX_LINKPOSITIONCNTR 0x0002074
#define ACP_BT_TX_FIFOADDR 0x0002078
#define ACP_BT_TX_FIFOSIZE 0x000207C
#define ACP_BT_TX_DMA_SIZE 0x0002080
#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x0002084
#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x0002088
#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x000208C
#define ACP_HS_RX_RINGBUFADDR 0x0002090
#define ACP_HS_RX_RINGBUFSIZE 0x0002094
#define ACP_HS_RX_LINKPOSITIONCNTR 0x0002098
#define ACP_HS_RX_FIFOADDR 0x000209C
#define ACP_HS_RX_FIFOSIZE 0x00020A0
#define ACP_HS_RX_DMA_SIZE 0x00020A4
#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x00020A8
#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x00020AC
#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x00020B0
#define ACP_HS_TX_RINGBUFADDR 0x00020B4
#define ACP_HS_TX_RINGBUFSIZE 0x00020B8
#define ACP_HS_TX_LINKPOSITIONCNTR 0x00020BC
#define ACP_HS_TX_FIFOADDR 0x00020C0
#define ACP_HS_TX_FIFOSIZE 0x00020C4
#define ACP_HS_TX_DMA_SIZE 0x00020C8
#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x00020CC
#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x00020D0
#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x00020D4
#define ACP_AUDIO_RX_RINGBUFADDR ACP_I2S_RX_RINGBUFADDR
#define ACP_AUDIO_RX_RINGBUFSIZE ACP_I2S_RX_RINGBUFSIZE
#define ACP_AUDIO_RX_LINKPOSITIONCNTR ACP_I2S_RX_LINKPOSITIONCNTR
#define ACP_AUDIO_RX_FIFOADDR ACP_I2S_RX_FIFOADDR
#define ACP_AUDIO_RX_FIFOSIZE ACP_I2S_RX_FIFOSIZE
#define ACP_AUDIO_RX_DMA_SIZE ACP_I2S_RX_DMA_SIZE
#define ACP_AUDIO_RX_LINEARPOSITIONCNTR_HIGH ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH
#define ACP_AUDIO_RX_LINEARPOSITIONCNTR_LOW ACP_I2S_RX_LINEARPOSITIONCNTR_LOW
#define ACP_AUDIO_RX_INTR_WATERMARK_SIZE ACP_I2S_RX_INTR_WATERMARK_SIZE
#define ACP_AUDIO_TX_RINGBUFADDR ACP_I2S_TX_RINGBUFADDR
#define ACP_AUDIO_TX_RINGBUFSIZE ACP_I2S_TX_RINGBUFSIZE
#define ACP_AUDIO_TX_LINKPOSITIONCNTR ACP_I2S_TX_LINKPOSITIONCNTR
#define ACP_AUDIO_TX_FIFOADDR ACP_I2S_TX_FIFOADDR
#define ACP_AUDIO_TX_FIFOSIZE ACP_I2S_TX_FIFOSIZE
#define ACP_AUDIO_TX_DMA_SIZE ACP_I2S_TX_DMA_SIZE
#define ACP_AUDIO_TX_LINEARPOSITIONCNTR_HIGH ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH
#define ACP_AUDIO_TX_LINEARPOSITIONCNTR_LOW ACP_I2S_TX_LINEARPOSITIONCNTR_LOW
#define ACP_AUDIO_TX_INTR_WATERMARK_SIZE ACP_I2S_TX_INTR_WATERMARK_SIZE
#define ACP_AUDIO0_RX_RINGBUFADDR 0x0002000
#define ACP_AUDIO0_RX_RINGBUFSIZE 0x0002004
#define ACP_AUDIO0_RX_LINKPOSITIONCNTR 0x0002008
#define ACP_AUDIO0_RX_FIFOADDR 0x000200C
#define ACP_AUDIO0_RX_FIFOSIZE 0x0002010
#define ACP_AUDIO0_RX_DMA_SIZE 0x0002014
#define ACP_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH 0x0002018
#define ACP_AUDIO0_RX_LINEARPOSITIONCNTR_LOW 0x000201C
#define ACP_AUDIO0_RX_INTR_WATERMARK_SIZE 0x0002020
#define ACP_AUDIO0_TX_RINGBUFADDR 0x0002024
#define ACP_AUDIO0_TX_RINGBUFSIZE 0x0002028
#define ACP_AUDIO0_TX_LINKPOSITIONCNTR 0x000202C
#define ACP_AUDIO0_TX_FIFOADDR 0x0002030
#define ACP_AUDIO0_TX_FIFOSIZE 0x0002034
#define ACP_AUDIO0_TX_DMA_SIZE 0x0002038
#define ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH 0x000203C
#define ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW 0x0002040
#define ACP_AUDIO0_TX_INTR_WATERMARK_SIZE 0x0002044
#define ACP_AUDIO1_RX_RINGBUFADDR 0x0002048
#define ACP_AUDIO1_RX_RINGBUFSIZE 0x000204C
#define ACP_AUDIO1_RX_LINKPOSITIONCNTR 0x0002050
#define ACP_AUDIO1_RX_FIFOADDR 0x0002054
#define ACP_AUDIO1_RX_FIFOSIZE 0x0002058
#define ACP_AUDIO1_RX_DMA_SIZE 0x000205C
#define ACP_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH 0x0002060
#define ACP_AUDIO1_RX_LINEARPOSITIONCNTR_LOW 0x0002064
#define ACP_AUDIO1_RX_INTR_WATERMARK_SIZE 0x0002068
#define ACP_AUDIO1_TX_RINGBUFADDR 0x000206C
#define ACP_AUDIO1_TX_RINGBUFSIZE 0x0002070
#define ACP_AUDIO1_TX_LINKPOSITIONCNTR 0x0002074
#define ACP_AUDIO1_TX_FIFOADDR 0x0002078
#define ACP_AUDIO1_TX_FIFOSIZE 0x000207C
#define ACP_AUDIO1_TX_DMA_SIZE 0x0002080
#define ACP_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH 0x0002084
#define ACP_AUDIO1_TX_LINEARPOSITIONCNTR_LOW 0x0002088
#define ACP_AUDIO1_TX_INTR_WATERMARK_SIZE 0x000208C
#define ACP_AUDIO2_RX_RINGBUFADDR 0x0002090
#define ACP_AUDIO2_RX_RINGBUFSIZE 0x0002094
#define ACP_AUDIO2_RX_LINKPOSITIONCNTR 0x0002098
#define ACP_AUDIO2_RX_FIFOADDR 0x000209C
#define ACP_AUDIO2_RX_FIFOSIZE 0x00020A0
#define ACP_AUDIO2_RX_DMA_SIZE 0x00020A4
#define ACP_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH 0x00020A8
#define ACP_AUDIO2_RX_LINEARPOSITIONCNTR_LOW 0x00020AC
#define ACP_AUDIO2_RX_INTR_WATERMARK_SIZE 0x00020B0
#define ACP_AUDIO2_TX_RINGBUFADDR 0x00020B4
#define ACP_AUDIO2_TX_RINGBUFSIZE 0x00020B8
#define ACP_AUDIO2_TX_LINKPOSITIONCNTR 0x00020BC
#define ACP_AUDIO2_TX_FIFOADDR 0x00020C0
#define ACP_AUDIO2_TX_FIFOSIZE 0x00020C4
#define ACP_AUDIO2_TX_DMA_SIZE 0x00020C8
#define ACP_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH 0x00020CC
#define ACP_AUDIO2_TX_LINEARPOSITIONCNTR_LOW 0x00020D0
#define ACP_AUDIO2_TX_INTR_WATERMARK_SIZE 0x00020D4
/* Registers from ACP_I2S_TDM block */
#define ACP_I2STDM_IER 0x0002400
@ -292,367 +274,222 @@
#define ACP_WOV_ERROR_STATUS_REGISTER 0x0002C68
#define ACP_PDM_CLKDIV 0x0002C6C
/* Registers from ACP_SW_SWCLK block */
#define ACP_SW_EN 0x0003000
#define ACP_SW_EN_STATUS 0x0003004
#define ACP_SW_FRAMESIZE 0x0003008
#define ACP_SW_SSP_COUNTER 0x000300C
#define ACP_SW_AUDIO_TX_EN 0x0003010
#define ACP_SW_AUDIO_TX_EN_STATUS 0x0003014
#define ACP_SW_AUDIO_TX_FRAME_FORMAT 0x0003018
#define ACP_SW_AUDIO_TX_SAMPLEINTERVAL 0x000301C
#define ACP_SW_AUDIO_TX_HCTRL_DP0 0x0003020
#define ACP_SW_AUDIO_TX_HCTRL_DP1 0x0003024
#define ACP_SW_AUDIO_TX_HCTRL_DP2 0x0003028
#define ACP_SW_AUDIO_TX_HCTRL_DP3 0x000302C
#define ACP_SW_AUDIO_TX_OFFSET_DP0 0x0003030
#define ACP_SW_AUDIO_TX_OFFSET_DP1 0x0003034
#define ACP_SW_AUDIO_TX_OFFSET_DP2 0x0003038
#define ACP_SW_AUDIO_TX_OFFSET_DP3 0x000303C
#define ACP_SW_AUDIO_TX_CHANNEL_ENABLE_DP0 0x0003040
#define ACP_SW_AUDIO_TX_CHANNEL_ENABLE_DP1 0x0003044
#define ACP_SW_AUDIO_TX_CHANNEL_ENABLE_DP2 0x0003048
#define ACP_SW_AUDIO_TX_CHANNEL_ENABLE_DP3 0x000304C
#define ACP_SW_BT_TX_EN 0x0003050
#define ACP_SW_BT_TX_EN_STATUS 0x0003054
#define ACP_SW_BT_TX_FRAME_FORMAT 0x0003058
#define ACP_SW_BT_TX_SAMPLEINTERVAL 0x000305C
#define ACP_SW_BT_TX_HCTRL 0x0003060
#define ACP_SW_BT_TX_OFFSET 0x0003064
#define ACP_SW_BT_TX_CHANNEL_ENABLE_DP0 0x0003068
#define ACP_SW_HEADSET_TX_EN 0x000306C
#define ACP_SW_HEADSET_TX_EN_STATUS 0x0003070
#define ACP_SW_HEADSET_TX_FRAME_FORMAT 0x0003074
#define ACP_SW_HEADSET_TX_SAMPLEINTERVAL 0x0003078
#define ACP_SW_HEADSET_TX_HCTRL 0x000307C
#define ACP_SW_HEADSET_TX_OFFSET 0x0003080
#define ACP_SW_HEADSET_TX_CHANNEL_ENABLE_DP0 0x0003084
#define ACP_SW_AUDIO_RX_EN 0x0003088
#define ACP_SW_AUDIO_RX_EN_STATUS 0x000308C
#define ACP_SW_AUDIO_RX_FRAME_FORMAT 0x0003090
#define ACP_SW_AUDIO_RX_SAMPLEINTERVAL 0x0003094
#define ACP_SW_AUDIO_RX_HCTRL_DP0 0x0003098
#define ACP_SW_AUDIO_RX_HCTRL_DP1 0x000309C
#define ACP_SW_AUDIO_RX_HCTRL_DP2 0x0003100
#define ACP_SW_AUDIO_RX_HCTRL_DP3 0x0003104
#define ACP_SW_AUDIO_RX_OFFSET_DP0 0x0003108
#define ACP_SW_AUDIO_RX_OFFSET_DP1 0x000310C
#define ACP_SW_AUDIO_RX_OFFSET_DP2 0x0003110
#define ACP_SW_AUDIO_RX_OFFSET_DP3 0x0003114
#define ACP_SW_AUDIO_RX_CHANNEL_ENABLE_DP0 0x0003118
#define ACP_SW_AUDIO_RX_CHANNEL_ENABLE_DP1 0x000311C
#define ACP_SW_AUDIO_RX_CHANNEL_ENABLE_DP2 0x0003120
#define ACP_SW_AUDIO_RX_CHANNEL_ENABLE_DP3 0x0003124
#define ACP_SW_BT_RX_EN 0x0003128
#define ACP_SW_BT_RX_EN_STATUS 0x000312C
#define ACP_SW_BT_RX_FRAME_FORMAT 0x0003130
#define ACP_SW_BT_RX_SAMPLEINTERVAL 0x0003134
#define ACP_SW_BT_RX_HCTRL 0x0003138
#define ACP_SW_BT_RX_OFFSET 0x000313C
#define ACP_SW_BT_RX_CHANNEL_ENABLE_DP0 0x0003140
#define ACP_SW_HEADSET_RX_EN 0x0003144
#define ACP_SW_HEADSET_RX_EN_STATUS 0x0003148
#define ACP_SW_HEADSET_RX_FRAME_FORMAT 0x000314C
#define ACP_SW_HEADSET_RX_SAMPLEINTERVAL 0x0003150
#define ACP_SW_HEADSET_RX_HCTRL 0x0003154
#define ACP_SW_HEADSET_RX_OFFSET 0x0003158
#define ACP_SW_HEADSET_RX_CHANNEL_ENABLE_DP0 0x000315C
#define ACP_SW_BPT_PORT_EN 0x0003160
#define ACP_SW_BPT_PORT_EN_STATUS 0x0003164
#define ACP_SW_BPT_PORT_FRAME_FORMAT 0x0003168
#define ACP_SW_BPT_PORT_SAMPLEINTERVAL 0x000316C
#define ACP_SW_BPT_PORT_HCTRL 0x0003170
#define ACP_SW_BPT_PORT_OFFSET 0x0003174
#define ACP_SW_BPT_PORT_CHANNEL_ENABLE 0x0003178
#define ACP_SW_BPT_PORT_FIRST_BYTE_ADDR 0x000317C
#define ACP_SW_CLK_RESUME_CTRL 0x0003180
#define ACP_SW_CLK_RESUME_DELAY_CNTR 0x0003184
#define ACP_SW_BUS_RESET_CTRL 0x0003188
#define ACP_SW_PRBS_ERR_STATUS 0x000318C
#define SW_IMM_CMD_UPPER_WORD 0x0003230
#define SW_IMM_CMD_LOWER_QWORD 0x0003234
#define SW_IMM_RESP_UPPER_WORD 0x0003238
#define SW_IMM_RESP_LOWER_QWORD 0x000323C
#define SW_IMM_CMD_STS 0x0003240
#define SW_BRA_BASE_ADDRESS 0x0003244
#define SW_BRA_TRANSFER_SIZE 0x0003248
#define SW_BRA_DMA_BUSY 0x000324C
#define SW_BRA_RESP 0x0003250
#define SW_BRA_RESP_FRAME_ADDR 0x0003254
#define SW_BRA_CURRENT_TRANSFER_SIZE 0x0003258
#define SW_STATE_CHANGE_STATUS_0TO7 0x000325C
#define SW_STATE_CHANGE_STATUS_8TO11 0x0003260
#define SW_STATE_CHANGE_STATUS_MASK_0TO7 0x0003264
#define SW_STATE_CHANGE_STATUS_MASK_8TO11 0x0003268
#define SW_CLK_FREQUENCY_CTRL 0x000326C
#define SW_ERROR_INTR_MASK 0x0003270
#define SW_PHY_TEST_MODE_DATA_OFF 0x0003274
/* Registers from ACP_SW0_SWCLK block */
#define ACP_SW0_EN 0x0003000
#define ACP_SW0_EN_STATUS 0x0003004
#define ACP_SW0_FRAMESIZE 0x0003008
#define ACP_SW0_SSP_COUNTER 0x000300C
#define ACP_SW0_AUDIO0_TX_EN 0x0003010
#define ACP_SW0_AUDIO0_TX_EN_STATUS 0x0003014
#define ACP_SW0_AUDIO0_TX_FRAME_FORMAT 0x0003018
#define ACP_SW0_AUDIO0_TX_SAMPLEINTERVAL 0x000301C
#define ACP_SW0_AUDIO0_TX_HCTRL_DP0 0x0003020
#define ACP_SW0_AUDIO0_TX_HCTRL_DP1 0x0003024
#define ACP_SW0_AUDIO0_TX_HCTRL_DP2 0x0003028
#define ACP_SW0_AUDIO0_TX_HCTRL_DP3 0x000302C
#define ACP_SW0_AUDIO0_TX_OFFSET_DP0 0x0003030
#define ACP_SW0_AUDIO0_TX_OFFSET_DP1 0x0003034
#define ACP_SW0_AUDIO0_TX_OFFSET_DP2 0x0003038
#define ACP_SW0_AUDIO0_TX_OFFSET_DP3 0x000303C
#define ACP_SW0_AUDIO0_TX_CHANNEL_ENABLE_DP0 0x0003040
#define ACP_SW0_AUDIO0_TX_CHANNEL_ENABLE_DP1 0x0003044
#define ACP_SW0_AUDIO0_TX_CHANNEL_ENABLE_DP2 0x0003048
#define ACP_SW0_AUDIO0_TX_CHANNEL_ENABLE_DP3 0x000304C
#define ACP_SW0_AUDIO1_TX_EN 0x0003050
#define ACP_SW0_AUDIO1_TX_EN_STATUS 0x0003054
#define ACP_SW0_AUDIO1_TX_FRAME_FORMAT 0x0003058
#define ACP_SW0_AUDIO1_TX_SAMPLEINTERVAL 0x000305C
#define ACP_SW0_AUDIO1_TX_HCTRL 0x0003060
#define ACP_SW0_AUDIO1_TX_OFFSET 0x0003064
#define ACP_SW0_AUDIO1_TX_CHANNEL_ENABLE_DP0 0x0003068
#define ACP_SW0_AUDIO2_TX_EN 0x000306C
#define ACP_SW0_AUDIO2_TX_EN_STATUS 0x0003070
#define ACP_SW0_AUDIO2_TX_FRAME_FORMAT 0x0003074
#define ACP_SW0_AUDIO2_TX_SAMPLEINTERVAL 0x0003078
#define ACP_SW0_AUDIO2_TX_HCTRL 0x000307C
#define ACP_SW0_AUDIO2_TX_OFFSET 0x0003080
#define ACP_SW0_AUDIO2_TX_CHANNEL_ENABLE_DP0 0x0003084
#define ACP_SW0_AUDIO0_RX_EN 0x0003088
#define ACP_SW0_AUDIO0_RX_EN_STATUS 0x000308C
#define ACP_SW0_AUDIO0_RX_FRAME_FORMAT 0x0003090
#define ACP_SW0_AUDIO0_RX_SAMPLEINTERVAL 0x0003094
#define ACP_SW0_AUDIO0_RX_HCTRL_DP0 0x0003098
#define ACP_SW0_AUDIO0_RX_HCTRL_DP1 0x000309C
#define ACP_SW0_AUDIO0_RX_HCTRL_DP2 0x0003100
#define ACP_SW0_AUDIO0_RX_HCTRL_DP3 0x0003104
#define ACP_SW0_AUDIO0_RX_OFFSET_DP0 0x0003108
#define ACP_SW0_AUDIO0_RX_OFFSET_DP1 0x000310C
#define ACP_SW0_AUDIO0_RX_OFFSET_DP2 0x0003110
#define ACP_SW0_AUDIO0_RX_OFFSET_DP3 0x0003114
#define ACP_SW0_AUDIO0_RX_CHANNEL_ENABLE_DP0 0x0003118
#define ACP_SW0_AUDIO0_RX_CHANNEL_ENABLE_DP1 0x000311C
#define ACP_SW0_AUDIO0_RX_CHANNEL_ENABLE_DP2 0x0003120
#define ACP_SW0_AUDIO0_RX_CHANNEL_ENABLE_DP3 0x0003124
#define ACP_SW0_AUDIO1_RX_EN 0x0003128
#define ACP_SW0_AUDIO1_RX_EN_STATUS 0x000312C
#define ACP_SW0_AUDIO1_RX_FRAME_FORMAT 0x0003130
#define ACP_SW0_AUDIO1_RX_SAMPLEINTERVAL 0x0003134
#define ACP_SW0_AUDIO1_RX_HCTRL 0x0003138
#define ACP_SW0_AUDIO1_RX_OFFSET 0x000313C
#define ACP_SW0_AUDIO1_RX_CHANNEL_ENABLE_DP0 0x0003140
#define ACP_SW0_AUDIO2_RX_EN 0x0003144
#define ACP_SW0_AUDIO2_RX_EN_STATUS 0x0003148
#define ACP_SW0_AUDIO2_RX_FRAME_FORMAT 0x000314C
#define ACP_SW0_AUDIO2_RX_SAMPLEINTERVAL 0x0003150
#define ACP_SW0_AUDIO2_RX_HCTRL 0x0003154
#define ACP_SW0_AUDIO2_RX_OFFSET 0x0003158
#define ACP_SW0_AUDIO2_RX_CHANNEL_ENABLE_DP0 0x000315C
#define ACP_SW0_BPT_PORT_EN 0x0003160
#define ACP_SW0_BPT_PORT_EN_STATUS 0x0003164
#define ACP_SW0_BPT_PORT_FRAME_FORMAT 0x0003168
#define ACP_SW0_BPT_PORT_SAMPLEINTERVAL 0x000316C
#define ACP_SW0_BPT_PORT_HCTRL 0x0003170
#define ACP_SW0_BPT_PORT_OFFSET 0x0003174
#define ACP_SW0_BPT_PORT_CHANNEL_ENABLE 0x0003178
#define ACP_SW0_BPT_PORT_FIRST_BYTE_ADDR 0x000317C
#define ACP_SW0_CLK_RESUME_CTRL 0x0003180
#define ACP_SW0_CLK_RESUME_DELAY_CNTR 0x0003184
#define ACP_SW0_BUS_RESET_CTRL 0x0003188
#define ACP_SW0_PRBS_ERR_STATUS 0x000318C
#define ACP_SW0_IMM_CMD_UPPER_WORD 0x0003230
#define ACP_SW0_IMM_CMD_LOWER_QWORD 0x0003234
#define ACP_SW0_IMM_RESP_UPPER_WORD 0x0003238
#define ACP_SW0_IMM_RESP_LOWER_QWORD 0x000323C
#define ACP_SW0_IMM_CMD_STS 0x0003240
#define ACP_SW0_BRA_BASE_ADDRESS 0x0003244
#define ACP_SW0_BRA_TRANSFER_SIZE 0x0003248
#define ACP_SW0_BRA_DMA_BUSY 0x000324C
#define ACP_SW0_BRA_RESP 0x0003250
#define ACP_SW0_BRA_RESP_FRAME_ADDR 0x0003254
#define ACP_SW0_BRA_CURRENT_TRANSFER_SIZE 0x0003258
#define ACP_SW0_STATECHANGE_STATUS_0TO7 0x000325C
#define ACP_SW0_STATECHANGE_STATUS_8TO11 0x0003260
#define ACP_SW0_STATECHANGE_STATUS_MASK_0TO7 0x0003264
#define ACP_SW0_STATECHANGE_STATUS_MASK_8TO11 0x0003268
#define ACP_SW0_CLK_FREQUENCY_CTRL 0x000326C
#define ACP_SW0_ERROR_INTR_MASK 0x0003270
#define ACP_SW0_PHY_TEST_MODE_DATA_OFF 0x0003274
/* Registers from ACP_P1_AUDIO_BUFFERS block */
#define ACP_P1_I2S_RX_RINGBUFADDR 0x0003A00
#define ACP_P1_I2S_RX_RINGBUFSIZE 0x0003A04
#define ACP_P1_I2S_RX_LINKPOSITIONCNTR 0x0003A08
#define ACP_P1_I2S_RX_FIFOADDR 0x0003A0C
#define ACP_P1_I2S_RX_FIFOSIZE 0x0003A10
#define ACP_P1_I2S_RX_DMA_SIZE 0x0003A14
#define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x0003A18
#define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_LOW 0x0003A1C
#define ACP_P1_I2S_RX_INTR_WATERMARK_SIZE 0x0003A20
#define ACP_P1_I2S_TX_RINGBUFADDR 0x0003A24
#define ACP_P1_I2S_TX_RINGBUFSIZE 0x0003A28
#define ACP_P1_I2S_TX_LINKPOSITIONCNTR 0x0003A2C
#define ACP_P1_I2S_TX_FIFOADDR 0x0003A30
#define ACP_P1_I2S_TX_FIFOSIZE 0x0003A34
#define ACP_P1_I2S_TX_DMA_SIZE 0x0003A38
#define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x0003A3C
#define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_LOW 0x0003A40
#define ACP_P1_I2S_TX_INTR_WATERMARK_SIZE 0x0003A44
#define ACP_P1_BT_RX_RINGBUFADDR 0x0003A48
#define ACP_P1_BT_RX_RINGBUFSIZE 0x0003A4C
#define ACP_P1_BT_RX_LINKPOSITIONCNTR 0x0003A50
#define ACP_P1_BT_RX_FIFOADDR 0x0003A54
#define ACP_P1_BT_RX_FIFOSIZE 0x0003A58
#define ACP_P1_BT_RX_DMA_SIZE 0x0003A5C
#define ACP_P1_BT_RX_LINEARPOSITIONCNTR_HIGH 0x0003A60
#define ACP_P1_BT_RX_LINEARPOSITIONCNTR_LOW 0x0003A64
#define ACP_P1_BT_RX_INTR_WATERMARK_SIZE 0x0003A68
#define ACP_P1_BT_TX_RINGBUFADDR 0x0003A6C
#define ACP_P1_BT_TX_RINGBUFSIZE 0x0003A70
#define ACP_P1_BT_TX_LINKPOSITIONCNTR 0x0003A74
#define ACP_P1_BT_TX_FIFOADDR 0x0003A78
#define ACP_P1_BT_TX_FIFOSIZE 0x0003A7C
#define ACP_P1_BT_TX_DMA_SIZE 0x0003A80
#define ACP_P1_BT_TX_LINEARPOSITIONCNTR_HIGH 0x0003A84
#define ACP_P1_BT_TX_LINEARPOSITIONCNTR_LOW 0x0003A88
#define ACP_P1_BT_TX_INTR_WATERMARK_SIZE 0x0003A8C
#define ACP_P1_HS_RX_RINGBUFADDR 0x0003A90
#define ACP_P1_HS_RX_RINGBUFSIZE 0x0003A94
#define ACP_P1_HS_RX_LINKPOSITIONCNTR 0x0003A98
#define ACP_P1_HS_RX_FIFOADDR 0x0003A9C
#define ACP_P1_HS_RX_FIFOSIZE 0x0003AA0
#define ACP_P1_HS_RX_DMA_SIZE 0x0003AA4
#define ACP_P1_HS_RX_LINEARPOSITIONCNTR_HIGH 0x0003AA8
#define ACP_P1_HS_RX_LINEARPOSITIONCNTR_LOW 0x0003AAC
#define ACP_P1_HS_RX_INTR_WATERMARK_SIZE 0x0003AB0
#define ACP_P1_HS_TX_RINGBUFADDR 0x0003AB4
#define ACP_P1_HS_TX_RINGBUFSIZE 0x0003AB8
#define ACP_P1_HS_TX_LINKPOSITIONCNTR 0x0003ABC
#define ACP_P1_HS_TX_FIFOADDR 0x0003AC0
#define ACP_P1_HS_TX_FIFOSIZE 0x0003AC4
#define ACP_P1_HS_TX_DMA_SIZE 0x0003AC8
#define ACP_P1_HS_TX_LINEARPOSITIONCNTR_HIGH 0x0003ACC
#define ACP_P1_HS_TX_LINEARPOSITIONCNTR_LOW 0x0003AD0
#define ACP_P1_HS_TX_INTR_WATERMARK_SIZE 0x0003AD4
#define ACP_P1_AUDIO_RX_RINGBUFADDR ACP_P1_I2S_RX_RINGBUFADDR
#define ACP_P1_AUDIO_RX_RINGBUFSIZE ACP_P1_I2S_RX_RINGBUFSIZE
#define ACP_P1_AUDIO_RX_LINKPOSITIONCNTR ACP_P1_I2S_RX_LINKPOSITIONCNTR
#define ACP_P1_AUDIO_RX_FIFOADDR ACP_P1_I2S_RX_FIFOADDR
#define ACP_P1_AUDIO_RX_FIFOSIZE ACP_P1_I2S_RX_FIFOSIZE
#define ACP_P1_AUDIO_RX_DMA_SIZE ACP_P1_I2S_RX_DMA_SIZE
#define ACP_P1_AUDIO_RX_LINEARPOSITIONCNTR_HIGH ACP_P1_I2S_RX_LINEARPOSITIONCNTR_HIGH
#define ACP_P1_AUDIO_RX_LINEARPOSITIONCNTR_LOW ACP_P1_I2S_RX_LINEARPOSITIONCNTR_LOW
#define ACP_P1_AUDIO_RX_INTR_WATERMARK_SIZE ACP_P1_I2S_RX_INTR_WATERMARK_SIZE
#define ACP_P1_AUDIO_TX_RINGBUFADDR ACP_P1_I2S_TX_RINGBUFADDR
#define ACP_P1_AUDIO_TX_RINGBUFSIZE ACP_P1_I2S_TX_RINGBUFSIZE
#define ACP_P1_AUDIO_TX_LINKPOSITIONCNTR ACP_P1_I2S_TX_LINKPOSITIONCNTR
#define ACP_P1_AUDIO_TX_FIFOADDR ACP_P1_I2S_TX_FIFOADDR
#define ACP_P1_AUDIO_TX_FIFOSIZE ACP_P1_I2S_TX_FIFOSIZE
#define ACP_P1_AUDIO_TX_DMA_SIZE ACP_P1_I2S_TX_DMA_SIZE
#define ACP_P1_AUDIO_TX_LINEARPOSITIONCNTR_HIGH ACP_P1_I2S_TX_LINEARPOSITIONCNTR_HIGH
#define ACP_P1_AUDIO_TX_LINEARPOSITIONCNTR_LOW ACP_P1_I2S_TX_LINEARPOSITIONCNTR_LOW
#define ACP_P1_AUDIO_TX_INTR_WATERMARK_SIZE ACP_P1_I2S_TX_INTR_WATERMARK_SIZE
#define ACP_P1_AUDIO0_RX_RINGBUFADDR 0x0003A00
#define ACP_P1_AUDIO0_RX_RINGBUFSIZE 0x0003A04
#define ACP_P1_AUDIO0_RX_LINKPOSITIONCNTR 0x0003A08
#define ACP_P1_AUDIO0_RX_FIFOADDR 0x0003A0C
#define ACP_P1_AUDIO0_RX_FIFOSIZE 0x0003A10
#define ACP_P1_AUDIO0_RX_DMA_SIZE 0x0003A14
#define ACP_P1_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH 0x0003A18
#define ACP_P1_AUDIO0_RX_LINEARPOSITIONCNTR_LOW 0x0003A1C
#define ACP_P1_AUDIO0_RX_INTR_WATERMARK_SIZE 0x0003A20
#define ACP_P1_AUDIO0_TX_RINGBUFADDR 0x0003A24
#define ACP_P1_AUDIO0_TX_RINGBUFSIZE 0x0003A28
#define ACP_P1_AUDIO0_TX_LINKPOSITIONCNTR 0x0003A2C
#define ACP_P1_AUDIO0_TX_FIFOADDR 0x0003A30
#define ACP_P1_AUDIO0_TX_FIFOSIZE 0x0003A34
#define ACP_P1_AUDIO0_TX_DMA_SIZE 0x0003A38
#define ACP_P1_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH 0x0003A3C
#define ACP_P1_AUDIO0_TX_LINEARPOSITIONCNTR_LOW 0x0003A40
#define ACP_P1_AUDIO0_TX_INTR_WATERMARK_SIZE 0x0003A44
#define ACP_P1_AUDIO1_RX_RINGBUFADDR 0x0003A48
#define ACP_P1_AUDIO1_RX_RINGBUFSIZE 0x0003A4C
#define ACP_P1_AUDIO1_RX_LINKPOSITIONCNTR 0x0003A50
#define ACP_P1_AUDIO1_RX_FIFOADDR 0x0003A54
#define ACP_P1_AUDIO1_RX_FIFOSIZE 0x0003A58
#define ACP_P1_AUDIO1_RX_DMA_SIZE 0x0003A5C
#define ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH 0x0003A60
#define ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW 0x0003A64
#define ACP_P1_AUDIO1_RX_INTR_WATERMARK_SIZE 0x0003A68
#define ACP_P1_AUDIO1_TX_RINGBUFADDR 0x0003A6C
#define ACP_P1_AUDIO1_TX_RINGBUFSIZE 0x0003A70
#define ACP_P1_AUDIO1_TX_LINKPOSITIONCNTR 0x0003A74
#define ACP_P1_AUDIO1_TX_FIFOADDR 0x0003A78
#define ACP_P1_AUDIO1_TX_FIFOSIZE 0x0003A7C
#define ACP_P1_AUDIO1_TX_DMA_SIZE 0x0003A80
#define ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH 0x0003A84
#define ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_LOW 0x0003A88
#define ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE 0x0003A8C
#define ACP_P1_AUDIO2_RX_RINGBUFADDR 0x0003A90
#define ACP_P1_AUDIO2_RX_RINGBUFSIZE 0x0003A94
#define ACP_P1_AUDIO2_RX_LINKPOSITIONCNTR 0x0003A98
#define ACP_P1_AUDIO2_RX_FIFOADDR 0x0003A9C
#define ACP_P1_AUDIO2_RX_FIFOSIZE 0x0003AA0
#define ACP_P1_AUDIO2_RX_DMA_SIZE 0x0003AA4
#define ACP_P1_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH 0x0003AA8
#define ACP_P1_AUDIO2_RX_LINEARPOSITIONCNTR_LOW 0x0003AAC
#define ACP_P1_AUDIO2_RX_INTR_WATERMARK_SIZE 0x0003AB0
#define ACP_P1_AUDIO2_TX_RINGBUFADDR 0x0003AB4
#define ACP_P1_AUDIO2_TX_RINGBUFSIZE 0x0003AB8
#define ACP_P1_AUDIO2_TX_LINKPOSITIONCNTR 0x0003ABC
#define ACP_P1_AUDIO2_TX_FIFOADDR 0x0003AC0
#define ACP_P1_AUDIO2_TX_FIFOSIZE 0x0003AC4
#define ACP_P1_AUDIO2_TX_DMA_SIZE 0x0003AC8
#define ACP_P1_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH 0x0003ACC
#define ACP_P1_AUDIO2_TX_LINEARPOSITIONCNTR_LOW 0x0003AD0
#define ACP_P1_AUDIO2_TX_INTR_WATERMARK_SIZE 0x0003AD4
/* Registers from ACP_P1_SW_SWCLK block */
#define ACP_P1_SW_EN 0x0003C00
#define ACP_P1_SW_EN_STATUS 0x0003C04
#define ACP_P1_SW_FRAMESIZE 0x0003C08
#define ACP_P1_SW_SSP_COUNTER 0x0003C0C
#define ACP_P1_SW_BT_TX_EN 0x0003C50
#define ACP_P1_SW_BT_TX_EN_STATUS 0x0003C54
#define ACP_P1_SW_BT_TX_FRAME_FORMAT 0x0003C58
#define ACP_P1_SW_BT_TX_SAMPLEINTERVAL 0x0003C5C
#define ACP_P1_SW_BT_TX_HCTRL 0x0003C60
#define ACP_P1_SW_BT_TX_OFFSET 0x0003C64
#define ACP_P1_SW_BT_TX_CHANNEL_ENABLE_DP0 0x0003C68
#define ACP_P1_SW_BT_RX_EN 0x0003D28
#define ACP_P1_SW_BT_RX_EN_STATUS 0x0003D2C
#define ACP_P1_SW_BT_RX_FRAME_FORMAT 0x0003D30
#define ACP_P1_SW_BT_RX_SAMPLEINTERVAL 0x0003D34
#define ACP_P1_SW_BT_RX_HCTRL 0x0003D38
#define ACP_P1_SW_BT_RX_OFFSET 0x0003D3C
#define ACP_P1_SW_BT_RX_CHANNEL_ENABLE_DP0 0x0003D40
#define ACP_P1_SW_BPT_PORT_EN 0x0003D60
#define ACP_P1_SW_BPT_PORT_EN_STATUS 0x0003D64
#define ACP_P1_SW_BPT_PORT_FRAME_FORMAT 0x0003D68
#define ACP_P1_SW_BPT_PORT_SAMPLEINTERVAL 0x0003D6C
#define ACP_P1_SW_BPT_PORT_HCTRL 0x0003D70
#define ACP_P1_SW_BPT_PORT_OFFSET 0x0003D74
#define ACP_P1_SW_BPT_PORT_CHANNEL_ENABLE 0x0003D78
#define ACP_P1_SW_BPT_PORT_FIRST_BYTE_ADDR 0x0003D7C
#define ACP_P1_SW_CLK_RESUME_CTRL 0x0003D80
#define ACP_P1_SW_CLK_RESUME_DELAY_CNTR 0x0003D84
#define ACP_P1_SW_BUS_RESET_CTRL 0x0003D88
#define ACP_P1_SW_PRBS_ERR_STATUS 0x0003D8C
/* Registers from ACP_SW1_SWCLK block */
#define ACP_SW1_EN 0x0003C00
#define ACP_SW1_EN_STATUS 0x0003C04
#define ACP_SW1_FRAMESIZE 0x0003C08
#define ACP_SW1_SSP_COUNTER 0x0003C0C
#define ACP_SW1_AUDIO1_TX_EN 0x0003C50
#define ACP_SW1_AUDIO1_TX_EN_STATUS 0x0003C54
#define ACP_SW1_AUDIO1_TX_FRAME_FORMAT 0x0003C58
#define ACP_SW1_AUDIO1_TX_SAMPLEINTERVAL 0x0003C5C
#define ACP_SW1_AUDIO1_TX_HCTRL 0x0003C60
#define ACP_SW1_AUDIO1_TX_OFFSET 0x0003C64
#define ACP_SW1_AUDIO1_TX_CHANNEL_ENABLE_DP0 0x0003C68
#define ACP_SW1_AUDIO1_RX_EN 0x0003D28
#define ACP_SW1_AUDIO1_RX_EN_STATUS 0x0003D2C
#define ACP_SW1_AUDIO1_RX_FRAME_FORMAT 0x0003D30
#define ACP_SW1_AUDIO1_RX_SAMPLEINTERVAL 0x0003D34
#define ACP_SW1_AUDIO1_RX_HCTRL 0x0003D38
#define ACP_SW1_AUDIO1_RX_OFFSET 0x0003D3C
#define ACP_SW1_AUDIO1_RX_CHANNEL_ENABLE_DP0 0x0003D40
#define ACP_SW1_BPT_PORT_EN 0x0003D60
#define ACP_SW1_BPT_PORT_EN_STATUS 0x0003D64
#define ACP_SW1_BPT_PORT_FRAME_FORMAT 0x0003D68
#define ACP_SW1_BPT_PORT_SAMPLEINTERVAL 0x0003D6C
#define ACP_SW1_BPT_PORT_HCTRL 0x0003D70
#define ACP_SW1_BPT_PORT_OFFSET 0x0003D74
#define ACP_SW1_BPT_PORT_CHANNEL_ENABLE 0x0003D78
#define ACP_SW1_BPT_PORT_FIRST_BYTE_ADDR 0x0003D7C
#define ACP_SW1_CLK_RESUME_CTRL 0x0003D80
#define ACP_SW1_CLK_RESUME_DELAY_CNTR 0x0003D84
#define ACP_SW1_BUS_RESET_CTRL 0x0003D88
#define ACP_SW1_PRBS_ERR_STATUS 0x0003D8C
/* Registers from ACP_P1_SW_ACLK block */
#define P1_SW_CORB_BASE_ADDRESS 0x0003E00
#define P1_SW_CORB_WRITE_POINTER 0x0003E04
#define P1_SW_CORB_READ_POINTER 0x0003E08
#define P1_SW_CORB_CONTROL 0x0003E0C
#define P1_SW_CORB_SIZE 0x0003E14
#define P1_SW_RIRB_BASE_ADDRESS 0x0003E18
#define P1_SW_RIRB_WRITE_POINTER 0x0003E1C
#define P1_SW_RIRB_RESPONSE_INTERRUPT_COUNT 0x0003E20
#define P1_SW_RIRB_CONTROL 0x0003E24
#define P1_SW_RIRB_SIZE 0x0003E28
#define P1_SW_RIRB_FIFO_MIN_THDL 0x0003E2C
#define P1_SW_IMM_CMD_UPPER_WORD 0x0003E30
#define P1_SW_IMM_CMD_LOWER_QWORD 0x0003E34
#define P1_SW_IMM_RESP_UPPER_WORD 0x0003E38
#define P1_SW_IMM_RESP_LOWER_QWORD 0x0003E3C
#define P1_SW_IMM_CMD_STS 0x0003E40
#define P1_SW_BRA_BASE_ADDRESS 0x0003E44
#define P1_SW_BRA_TRANSFER_SIZE 0x0003E48
#define P1_SW_BRA_DMA_BUSY 0x0003E4C
#define P1_SW_BRA_RESP 0x0003E50
#define P1_SW_BRA_RESP_FRAME_ADDR 0x0003E54
#define P1_SW_BRA_CURRENT_TRANSFER_SIZE 0x0003E58
#define P1_SW_STATE_CHANGE_STATUS_0TO7 0x0003E5C
#define P1_SW_STATE_CHANGE_STATUS_8TO11 0x0003E60
#define P1_SW_STATE_CHANGE_STATUS_MASK_0TO7 0x0003E64
#define P1_SW_STATE_CHANGE_STATUS_MASK_8TO11 0x0003E68
#define P1_SW_CLK_FREQUENCY_CTRL 0x0003E6C
#define P1_SW_ERROR_INTR_MASK 0x0003E70
#define P1_SW_PHY_TEST_MODE_DATA_OFF 0x0003E74
/* Registers from ACP_SW1_ACLK block */
#define ACP_SW1_CORB_BASE_ADDRESS 0x0003E00
#define ACP_SW1_CORB_WRITE_POINTER 0x0003E04
#define ACP_SW1_CORB_READ_POINTER 0x0003E08
#define ACP_SW1_CORB_CONTROL 0x0003E0C
#define ACP_SW1_CORB_SIZE 0x0003E14
#define ACP_SW1_RIRB_BASE_ADDRESS 0x0003E18
#define ACP_SW1_RIRB_WRITE_POINTER 0x0003E1C
#define ACP_SW1_RIRB_RESPONSE_INTERRUPT_COUNT 0x0003E20
#define ACP_SW1_RIRB_CONTROL 0x0003E24
#define ACP_SW1_RIRB_SIZE 0x0003E28
#define ACP_SW1_RIRB_FIFO_MIN_THDL 0x0003E2C
#define ACP_SW1_IMM_CMD_UPPER_WORD 0x0003E30
#define ACP_SW1_IMM_CMD_LOWER_QWORD 0x0003E34
#define ACP_SW1_IMM_RESP_UPPER_WORD 0x0003E38
#define ACP_SW1_IMM_RESP_LOWER_QWORD 0x0003E3C
#define ACP_SW1_IMM_CMD_STS 0x0003E40
#define ACP_SW1_BRA_BASE_ADDRESS 0x0003E44
#define ACP_SW1_BRA_TRANSFER_SIZE 0x0003E48
#define ACP_SW1_BRA_DMA_BUSY 0x0003E4C
#define ACP_SW1_BRA_RESP 0x0003E50
#define ACP_SW1_BRA_RESP_FRAME_ADDR 0x0003E54
#define ACP_SW1_BRA_CURRENT_TRANSFER_SIZE 0x0003E58
#define ACP_SW1_STATECHANGE_STATUS_0TO7 0x0003E5C
#define ACP_SW1_STATECHANGE_STATUS_8TO11 0x0003E60
#define ACP_SW1_STATECHANGE_STATUS_MASK_0TO7 0x0003E64
#define ACP_SW1_STATECHANGE_STATUS_MASK_8TO11 0x0003E68
#define ACP_SW1_CLK_FREQUENCY_CTRL 0x0003E6C
#define ACP_SW1_ERROR_INTR_MASK 0x0003E70
#define ACP_SW1_PHY_TEST_MODE_DATA_OFF 0x0003E74
/* Registers from ACP_SCRATCH block */
#define ACP_SCRATCH_REG_0 0x0010000
#define ACP_SCRATCH_REG_1 0x0010004
#define ACP_SCRATCH_REG_2 0x0010008
#define ACP_SCRATCH_REG_3 0x001000C
#define ACP_SCRATCH_REG_4 0x0010010
#define ACP_SCRATCH_REG_5 0x0010014
#define ACP_SCRATCH_REG_6 0x0010018
#define ACP_SCRATCH_REG_7 0x001001C
#define ACP_SCRATCH_REG_8 0x0010020
#define ACP_SCRATCH_REG_9 0x0010024
#define ACP_SCRATCH_REG_10 0x0010028
#define ACP_SCRATCH_REG_11 0x001002C
#define ACP_SCRATCH_REG_12 0x0010030
#define ACP_SCRATCH_REG_13 0x0010034
#define ACP_SCRATCH_REG_14 0x0010038
#define ACP_SCRATCH_REG_15 0x001003C
#define ACP_SCRATCH_REG_16 0x0010040
#define ACP_SCRATCH_REG_17 0x0010044
#define ACP_SCRATCH_REG_18 0x0010048
#define ACP_SCRATCH_REG_19 0x001004C
#define ACP_SCRATCH_REG_20 0x0010050
#define ACP_SCRATCH_REG_21 0x0010054
#define ACP_SCRATCH_REG_22 0x0010058
#define ACP_SCRATCH_REG_23 0x001005C
#define ACP_SCRATCH_REG_24 0x0010060
#define ACP_SCRATCH_REG_25 0x0010064
#define ACP_SCRATCH_REG_26 0x0010068
#define ACP_SCRATCH_REG_27 0x001006C
#define ACP_SCRATCH_REG_28 0x0010070
#define ACP_SCRATCH_REG_29 0x0010074
#define ACP_SCRATCH_REG_30 0x0010078
#define ACP_SCRATCH_REG_31 0x001007C
#define ACP_SCRATCH_REG_32 0x0010080
#define ACP_SCRATCH_REG_33 0x0010084
#define ACP_SCRATCH_REG_34 0x0010088
#define ACP_SCRATCH_REG_35 0x001008C
#define ACP_SCRATCH_REG_36 0x0010090
#define ACP_SCRATCH_REG_37 0x0010094
#define ACP_SCRATCH_REG_38 0x0010098
#define ACP_SCRATCH_REG_39 0x001009C
#define ACP_SCRATCH_REG_40 0x00100A0
#define ACP_SCRATCH_REG_41 0x00100A4
#define ACP_SCRATCH_REG_42 0x00100A8
#define ACP_SCRATCH_REG_43 0x00100AC
#define ACP_SCRATCH_REG_44 0x00100B0
#define ACP_SCRATCH_REG_45 0x00100B4
#define ACP_SCRATCH_REG_46 0x00100B8
#define ACP_SCRATCH_REG_47 0x00100BC
#define ACP_SCRATCH_REG_48 0x00100C0
#define ACP_SCRATCH_REG_49 0x00100C4
#define ACP_SCRATCH_REG_50 0x00100C8
#define ACP_SCRATCH_REG_51 0x00100CC
#define ACP_SCRATCH_REG_52 0x00100D0
#define ACP_SCRATCH_REG_53 0x00100D4
#define ACP_SCRATCH_REG_54 0x00100D8
#define ACP_SCRATCH_REG_55 0x00100DC
#define ACP_SCRATCH_REG_56 0x00100E0
#define ACP_SCRATCH_REG_57 0x00100E4
#define ACP_SCRATCH_REG_58 0x00100E8
#define ACP_SCRATCH_REG_59 0x00100EC
#define ACP_SCRATCH_REG_60 0x00100F0
#define ACP_SCRATCH_REG_61 0x00100F4
#define ACP_SCRATCH_REG_62 0x00100F8
#define ACP_SCRATCH_REG_63 0x00100FC
#define ACP_SCRATCH_REG_64 0x0010100
#define ACP_SCRATCH_REG_65 0x0010104
#define ACP_SCRATCH_REG_66 0x0010108
#define ACP_SCRATCH_REG_67 0x001010C
#define ACP_SCRATCH_REG_68 0x0010110
#define ACP_SCRATCH_REG_69 0x0010114
#define ACP_SCRATCH_REG_70 0x0010118
#define ACP_SCRATCH_REG_71 0x001011C
#define ACP_SCRATCH_REG_72 0x0010120
#define ACP_SCRATCH_REG_73 0x0010124
#define ACP_SCRATCH_REG_74 0x0010128
#define ACP_SCRATCH_REG_75 0x001012C
#define ACP_SCRATCH_REG_76 0x0010130
#define ACP_SCRATCH_REG_77 0x0010134
#define ACP_SCRATCH_REG_78 0x0010138
#define ACP_SCRATCH_REG_79 0x001013C
#define ACP_SCRATCH_REG_80 0x0010140
#define ACP_SCRATCH_REG_81 0x0010144
#define ACP_SCRATCH_REG_82 0x0010148
#define ACP_SCRATCH_REG_83 0x001014C
#define ACP_SCRATCH_REG_84 0x0010150
#define ACP_SCRATCH_REG_85 0x0010154
#define ACP_SCRATCH_REG_86 0x0010158
#define ACP_SCRATCH_REG_87 0x001015C
#define ACP_SCRATCH_REG_88 0x0010160
#define ACP_SCRATCH_REG_89 0x0010164
#define ACP_SCRATCH_REG_90 0x0010168
#define ACP_SCRATCH_REG_91 0x001016C
#define ACP_SCRATCH_REG_92 0x0010170
#define ACP_SCRATCH_REG_93 0x0010174
#define ACP_SCRATCH_REG_94 0x0010178
#define ACP_SCRATCH_REG_95 0x001017C
#define ACP_SCRATCH_REG_96 0x0010180
#define ACP_SCRATCH_REG_97 0x0010184
#define ACP_SCRATCH_REG_98 0x0010188
#define ACP_SCRATCH_REG_99 0x001018C
#define ACP_SCRATCH_REG_100 0x0010190
#define ACP_SCRATCH_REG_101 0x0010194
#define ACP_SCRATCH_REG_102 0x0010198
#define ACP_SCRATCH_REG_103 0x001019C
#define ACP_SCRATCH_REG_104 0x00101A0
#define ACP_SCRATCH_REG_105 0x00101A4
#define ACP_SCRATCH_REG_106 0x00101A8
#define ACP_SCRATCH_REG_107 0x00101AC
#define ACP_SCRATCH_REG_108 0x00101B0
#define ACP_SCRATCH_REG_109 0x00101B4
#define ACP_SCRATCH_REG_110 0x00101B8
#define ACP_SCRATCH_REG_111 0x00101BC
#define ACP_SCRATCH_REG_112 0x00101C0
#define ACP_SCRATCH_REG_113 0x00101C4
#define ACP_SCRATCH_REG_114 0x00101C8
#define ACP_SCRATCH_REG_115 0x00101CC
#define ACP_SCRATCH_REG_116 0x00101D0
#define ACP_SCRATCH_REG_117 0x00101D4
#define ACP_SCRATCH_REG_118 0x00101D8
#define ACP_SCRATCH_REG_119 0x00101DC
#define ACP_SCRATCH_REG_120 0x00101E0
#define ACP_SCRATCH_REG_121 0x00101E4
#define ACP_SCRATCH_REG_122 0x00101E8
#define ACP_SCRATCH_REG_123 0x00101EC
#define ACP_SCRATCH_REG_124 0x00101F0
#define ACP_SCRATCH_REG_125 0x00101F4
#define ACP_SCRATCH_REG_126 0x00101F8
#define ACP_SCRATCH_REG_127 0x00101FC
#define ACP_SCRATCH_REG_128 0x0010200
#define ACP_SCRATCH_REG_0 0x0010000
#endif

View File

@ -34,6 +34,7 @@
#define CS42L42_PAGE_24 0x2400
#define CS42L42_PAGE_25 0x2500
#define CS42L42_PAGE_26 0x2600
#define CS42L42_PAGE_27 0x2700
#define CS42L42_PAGE_28 0x2800
#define CS42L42_PAGE_29 0x2900
#define CS42L42_PAGE_2A 0x2A00
@ -720,6 +721,10 @@
#define CS42L42_SRC_SDOUT_FS (CS42L42_PAGE_26 + 0x09)
/* Page 0x27 DMA */
#define CS42L42_SOFT_RESET_REBOOT (CS42L42_PAGE_27 + 0x01)
#define CS42L42_SFT_RST_REBOOT_MASK BIT(1)
/* Page 0x28 S/PDIF Registers */
#define CS42L42_SPDIF_CTL1 (CS42L42_PAGE_28 + 0x01)
#define CS42L42_SPDIF_CTL2 (CS42L42_PAGE_28 + 0x02)

View File

@ -69,6 +69,7 @@ struct asoc_simple_priv {
} *dai_props;
struct asoc_simple_jack hp_jack;
struct asoc_simple_jack mic_jack;
struct snd_soc_jack *aux_jacks;
struct snd_soc_dai_link *dai_link;
struct asoc_simple_dai *dais;
struct snd_soc_dai_link_component *dlcs;
@ -187,6 +188,8 @@ int asoc_simple_parse_pin_switches(struct snd_soc_card *card,
int asoc_simple_init_jack(struct snd_soc_card *card,
struct asoc_simple_jack *sjack,
int is_hp, char *prefix, char *pin);
int asoc_simple_init_aux_jacks(struct asoc_simple_priv *priv,
char *prefix);
int asoc_simple_init_priv(struct asoc_simple_priv *priv,
struct link_info *li);
int asoc_simple_remove(struct platform_device *pdev);

View File

@ -98,6 +98,7 @@ struct snd_soc_component_driver {
int source, unsigned int freq_in, unsigned int freq_out);
int (*set_jack)(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data);
int (*get_jack_type)(struct snd_soc_component *component);
/* DT */
int (*of_xlate_dai_name)(struct snd_soc_component *component,
@ -384,6 +385,7 @@ int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
unsigned int freq_out);
int snd_soc_component_set_jack(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data);
int snd_soc_component_get_jack_type(struct snd_soc_component *component);
void snd_soc_component_seq_notifier(struct snd_soc_component *component,
enum snd_soc_dapm_type type, int subseq);

View File

@ -423,6 +423,16 @@ struct snd_soc_dai_driver {
int remove_order;
};
/* for Playback/Capture */
struct snd_soc_dai_stream {
struct snd_soc_dapm_widget *widget;
unsigned int active; /* usage count */
unsigned int tdm_mask; /* CODEC TDM slot masks and params (for fixup) */
void *dma_data; /* DAI DMA data */
};
/*
* Digital Audio Interface runtime data.
*
@ -437,14 +447,7 @@ struct snd_soc_dai {
struct snd_soc_dai_driver *driver;
/* DAI runtime info */
unsigned int stream_active[SNDRV_PCM_STREAM_LAST + 1]; /* usage count */
struct snd_soc_dapm_widget *playback_widget;
struct snd_soc_dapm_widget *capture_widget;
/* DAI DMA data */
void *playback_dma_data;
void *capture_dma_data;
struct snd_soc_dai_stream stream[SNDRV_PCM_STREAM_LAST + 1];
/* Symmetry data - only valid if symmetry is being enforced */
unsigned int rate;
@ -454,10 +457,6 @@ struct snd_soc_dai {
/* parent platform/codec */
struct snd_soc_component *component;
/* CODEC TDM slot masks and params (for fixup) */
unsigned int tx_mask;
unsigned int rx_mask;
struct list_head list;
/* function mark */
@ -477,36 +476,59 @@ snd_soc_dai_get_pcm_stream(const struct snd_soc_dai *dai, int stream)
&dai->driver->playback : &dai->driver->capture;
}
#define snd_soc_dai_get_widget_playback(dai) snd_soc_dai_get_widget(dai, SNDRV_PCM_STREAM_PLAYBACK)
#define snd_soc_dai_get_widget_capture(dai) snd_soc_dai_get_widget(dai, SNDRV_PCM_STREAM_CAPTURE)
static inline
struct snd_soc_dapm_widget *snd_soc_dai_get_widget(
struct snd_soc_dai *dai, int stream)
struct snd_soc_dapm_widget *snd_soc_dai_get_widget(struct snd_soc_dai *dai, int stream)
{
return (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
dai->playback_widget : dai->capture_widget;
return dai->stream[stream].widget;
}
static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
const struct snd_pcm_substream *ss)
#define snd_soc_dai_set_widget_playback(dai, widget) snd_soc_dai_set_widget(dai, SNDRV_PCM_STREAM_PLAYBACK, widget)
#define snd_soc_dai_set_widget_capture(dai, widget) snd_soc_dai_set_widget(dai, SNDRV_PCM_STREAM_CAPTURE, widget)
static inline
void snd_soc_dai_set_widget(struct snd_soc_dai *dai, int stream, struct snd_soc_dapm_widget *widget)
{
return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
dai->playback_dma_data : dai->capture_dma_data;
dai->stream[stream].widget = widget;
}
static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai,
const struct snd_pcm_substream *ss,
void *data)
#define snd_soc_dai_dma_data_get_playback(dai) snd_soc_dai_dma_data_get(dai, SNDRV_PCM_STREAM_PLAYBACK)
#define snd_soc_dai_dma_data_get_capture(dai) snd_soc_dai_dma_data_get(dai, SNDRV_PCM_STREAM_CAPTURE)
#define snd_soc_dai_get_dma_data(dai, ss) snd_soc_dai_dma_data_get(dai, ss->stream)
static inline void *snd_soc_dai_dma_data_get(const struct snd_soc_dai *dai, int stream)
{
if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
dai->playback_dma_data = data;
else
dai->capture_dma_data = data;
return dai->stream[stream].dma_data;
}
static inline void snd_soc_dai_init_dma_data(struct snd_soc_dai *dai,
void *playback, void *capture)
#define snd_soc_dai_dma_data_set_playback(dai, data) snd_soc_dai_dma_data_set(dai, SNDRV_PCM_STREAM_PLAYBACK, data)
#define snd_soc_dai_dma_data_set_capture(dai, data) snd_soc_dai_dma_data_set(dai, SNDRV_PCM_STREAM_CAPTURE, data)
#define snd_soc_dai_set_dma_data(dai, ss, data) snd_soc_dai_dma_data_set(dai, ss->stream, data)
static inline void snd_soc_dai_dma_data_set(struct snd_soc_dai *dai, int stream, void *data)
{
dai->playback_dma_data = playback;
dai->capture_dma_data = capture;
dai->stream[stream].dma_data = data;
}
static inline void snd_soc_dai_init_dma_data(struct snd_soc_dai *dai, void *playback, void *capture)
{
snd_soc_dai_dma_data_set_playback(dai, playback);
snd_soc_dai_dma_data_set_capture(dai, capture);
}
static inline unsigned int snd_soc_dai_tdm_mask_get(struct snd_soc_dai *dai, int stream)
{
return dai->stream[stream].tdm_mask;
}
static inline void snd_soc_dai_tdm_mask_set(struct snd_soc_dai *dai, int stream,
unsigned int tdm_mask)
{
dai->stream[stream].tdm_mask = tdm_mask;
}
static inline unsigned int snd_soc_dai_stream_active(struct snd_soc_dai *dai, int stream)
{
/* see snd_soc_dai_action() for setup */
return dai->stream[stream].active;
}
static inline void snd_soc_dai_set_drvdata(struct snd_soc_dai *dai,
@ -561,10 +583,4 @@ static inline void *snd_soc_dai_get_stream(struct snd_soc_dai *dai,
return ERR_PTR(-ENOTSUPP);
}
static inline unsigned int
snd_soc_dai_stream_active(struct snd_soc_dai *dai, int stream)
{
return dai->stream_active[stream];
}
#endif

View File

@ -16,6 +16,7 @@
#include <sound/asoc.h>
struct device;
struct snd_pcm_substream;
struct snd_soc_pcm_runtime;
struct soc_enum;

View File

@ -162,6 +162,8 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream);
int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
int event);
bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, enum snd_soc_dapm_direction dir);
int widget_in_list(struct snd_soc_dapm_widget_list *list,
struct snd_soc_dapm_widget *widget);
#define dpcm_be_dai_startup_rollback(fe, stream, last) \
dpcm_be_dai_stop(fe, stream, 0, last)

View File

@ -62,7 +62,7 @@ struct snd_soc_dobj {
enum snd_soc_dobj_type type;
unsigned int index; /* objects can belong in different groups */
struct list_head list;
struct snd_soc_tplg_ops *ops;
int (*unload)(struct snd_soc_component *comp, struct snd_soc_dobj *dobj);
union {
struct snd_soc_dobj_control control;
struct snd_soc_dobj_widget widget;

View File

@ -1052,6 +1052,12 @@ struct snd_soc_card {
#define for_each_card_widgets_safe(card, w, _w) \
list_for_each_entry_safe(w, _w, &card->widgets, list)
static inline int snd_soc_card_is_instantiated(struct snd_soc_card *card)
{
return card && card->instantiated;
}
/* SoC machine DAI configuration, glues a codec and cpu DAI together */
struct snd_soc_pcm_runtime {
struct device *dev;

View File

@ -185,6 +185,9 @@ enum sof_ipc4_pipeline_state {
#define SOF_IPC4_GLB_PIPE_STATE_MASK GENMASK(15, 0)
#define SOF_IPC4_GLB_PIPE_STATE(x) ((x) << SOF_IPC4_GLB_PIPE_STATE_SHIFT)
/* pipeline set state IPC msg extension */
#define SOF_IPC4_GLB_PIPE_STATE_EXT_MULTI BIT(0)
/* load library ipc msg */
#define SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID_SHIFT 16
#define SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID(x) ((x) << SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID_SHIFT)

View File

@ -108,6 +108,7 @@ enum avs_tplg_token {
AVS_TKN_MOD_CORE_ID_U8 = 1704,
AVS_TKN_MOD_PROC_DOMAIN_U8 = 1705,
AVS_TKN_MOD_MODCFG_EXT_ID_U32 = 1706,
AVS_TKN_MOD_KCONTROL_ID_U32 = 1707,
/* struct avs_tplg_path_template */
AVS_TKN_PATH_TMPL_ID_U32 = 1801,
@ -121,6 +122,9 @@ enum avs_tplg_token {
AVS_TKN_PIN_FMT_INDEX_U32 = 2201,
AVS_TKN_PIN_FMT_IOBS_U32 = 2202,
AVS_TKN_PIN_FMT_AFMT_ID_U32 = 2203,
/* struct avs_tplg_kcontrol */
AVS_TKN_KCONTROL_ID_U32 = 2301,
};
#endif

View File

@ -16,6 +16,7 @@
#include <sound/pcm_params.h>
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <linux/dmi.h>
#include <linux/module.h>
#include "acp-mach.h"
@ -27,6 +28,7 @@ static struct acp_card_drvdata rt5682_rt1019_data = {
.hs_codec_id = RT5682,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.tdm_mode = false,
};
static struct acp_card_drvdata rt5682s_max_data = {
@ -36,6 +38,7 @@ static struct acp_card_drvdata rt5682s_max_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.tdm_mode = false,
};
static struct acp_card_drvdata rt5682s_rt1019_data = {
@ -45,6 +48,7 @@ static struct acp_card_drvdata rt5682s_rt1019_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.tdm_mode = false,
};
static struct acp_card_drvdata max_nau8825_data = {
@ -56,6 +60,7 @@ static struct acp_card_drvdata max_nau8825_data = {
.dmic_codec_id = DMIC,
.soc_mclk = true,
.platform = REMBRANDT,
.tdm_mode = false,
};
static struct acp_card_drvdata rt5682s_rt1019_rmb_data = {
@ -67,6 +72,7 @@ static struct acp_card_drvdata rt5682s_rt1019_rmb_data = {
.dmic_codec_id = DMIC,
.soc_mclk = true,
.platform = REMBRANDT,
.tdm_mode = false,
};
static const struct snd_kcontrol_new acp_controls[] = {
@ -90,6 +96,8 @@ static int acp_asoc_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = NULL;
struct device *dev = &pdev->dev;
const struct dmi_system_id *dmi_id;
struct acp_card_drvdata *acp_card_drvdata;
int ret;
if (!pdev->id_entry)
@ -108,6 +116,11 @@ static int acp_asoc_probe(struct platform_device *pdev)
card->num_controls = ARRAY_SIZE(acp_controls);
card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
acp_card_drvdata = card->drvdata;
dmi_id = dmi_first_match(acp_quirk_table);
if (dmi_id && dmi_id->driver_data)
acp_card_drvdata->tdm_mode = dmi_id->driver_data;
acp_legacy_dai_links_create(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);

View File

@ -32,6 +32,20 @@
#define DUAL_CHANNEL 2
#define FOUR_CHANNEL 4
#define TDM_MODE_ENABLE 1
const struct dmi_system_id acp_quirk_table[] = {
{
/* Google skyrim proto-0 */
.matches = {
DMI_EXACT_MATCH(DMI_PRODUCT_FAMILY, "Google_Skyrim"),
},
.driver_data = (void *)TDM_MODE_ENABLE,
},
{}
};
EXPORT_SYMBOL_GPL(acp_quirk_table);
static struct snd_soc_jack pco_jack;
static const unsigned int channels[] = {
@ -54,10 +68,11 @@ static const struct snd_pcm_hw_constraint_list constraints_channels = {
.mask = 0,
};
static int acp_clk_enable(struct acp_card_drvdata *drvdata)
static int acp_clk_enable(struct acp_card_drvdata *drvdata,
unsigned int srate, unsigned int bclk_ratio)
{
clk_set_rate(drvdata->wclk, 48000);
clk_set_rate(drvdata->bclk, 48000 * 64);
clk_set_rate(drvdata->wclk, srate);
clk_set_rate(drvdata->bclk, srate * bclk_ratio);
return clk_prepare_enable(drvdata->wclk);
}
@ -86,34 +101,6 @@ static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
if (drvdata->hs_codec_id != RT5682)
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 (ret < 0) {
dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
return ret;
}
ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK,
PCO_PLAT_CLK, RT5682_PLL_FREQ);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
return ret;
}
ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2,
RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
return ret;
}
/* Set tdm/i2s1 master bclk ratio */
ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
return ret;
}
drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
@ -151,10 +138,15 @@ static int acp_card_hs_startup(struct snd_pcm_substream *substream)
int ret;
unsigned int fmt;
if (drvdata->soc_mclk)
fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
if (drvdata->tdm_mode)
fmt = SND_SOC_DAIFMT_DSP_A;
else
fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
fmt = SND_SOC_DAIFMT_I2S;
if (drvdata->soc_mclk)
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
else
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
ret = snd_soc_dai_set_fmt(codec_dai, fmt);
if (ret < 0) {
@ -168,16 +160,6 @@ static int acp_card_hs_startup(struct snd_pcm_substream *substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (strcmp(codec_dai->name, "rt5682s-aif1") && strcmp(codec_dai->name, "rt5682s-aif2")) {
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;
}
@ -191,9 +173,96 @@ static void acp_card_shutdown(struct snd_pcm_substream *substream)
clk_disable_unprepare(drvdata->wclk);
}
static int acp_card_rt5682_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata;
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
int ret;
unsigned int fmt, srate, ch, format;
srate = params_rate(params);
ch = params_channels(params);
format = params_physical_width(params);
if (drvdata->tdm_mode)
fmt = SND_SOC_DAIFMT_DSP_A;
else
fmt = SND_SOC_DAIFMT_I2S;
if (drvdata->soc_mclk)
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
else
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
if (ret && ret != -ENOTSUPP) {
dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);
return ret;
}
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;
}
if (drvdata->tdm_mode) {
/**
* As codec supports slot 0 and slot 1 for playback and capture.
*/
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 8, 16);
if (ret && ret != -ENOTSUPP) {
dev_err(rtd->dev, "set TDM slot err: %d\n", ret);
return ret;
}
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 8, 16);
if (ret < 0) {
dev_warn(rtd->dev, "set TDM slot err:%d\n", ret);
return ret;
}
}
ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK,
PCO_PLAT_CLK, RT5682_PLL_FREQ);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
return ret;
}
ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2,
RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
return ret;
}
/* Set tdm/i2s1 master bclk ratio */
ret = snd_soc_dai_set_bclk_ratio(codec_dai, ch * format);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
return ret;
}
if (!drvdata->soc_mclk) {
ret = acp_clk_enable(drvdata, srate, ch * format);
if (ret < 0) {
dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);
return ret;
}
}
return 0;
}
static const struct snd_soc_ops acp_card_rt5682_ops = {
.startup = acp_card_hs_startup,
.shutdown = acp_card_shutdown,
.hw_params = acp_card_rt5682_hw_params,
};
/* Define RT5682S CODEC component*/
@ -212,7 +281,6 @@ 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);
@ -220,38 +288,6 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
if (drvdata->hs_codec_id != RT5682S)
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_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK,
PCO_PLAT_CLK, RT5682_PLL_FREQ);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
return ret;
}
ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2,
RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
return ret;
}
/* Set tdm/i2s1 master bclk ratio */
ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
return ret;
}
if (!drvdata->soc_mclk) {
drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
@ -281,8 +317,90 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682s_map, ARRAY_SIZE(rt5682s_map));
}
static int acp_card_rt5682s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata;
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
int ret;
unsigned int fmt, srate, ch, format;
srate = params_rate(params);
ch = params_channels(params);
format = params_physical_width(params);
if (drvdata->tdm_mode)
fmt = SND_SOC_DAIFMT_DSP_A;
else
fmt = SND_SOC_DAIFMT_I2S;
if (drvdata->soc_mclk)
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
else
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
if (ret && ret != -ENOTSUPP) {
dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);
return ret;
}
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;
}
if (drvdata->tdm_mode) {
/**
* As codec supports slot 0 and slot 1 for playback and capture.
*/
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 8, 16);
if (ret && ret != -ENOTSUPP) {
dev_err(rtd->dev, "set TDM slot err: %d\n", ret);
return ret;
}
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 8, 16);
if (ret < 0) {
dev_warn(rtd->dev, "set TDM slot err:%d\n", ret);
return ret;
}
}
ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK,
PCO_PLAT_CLK, RT5682_PLL_FREQ);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
return ret;
}
ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2,
RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
return ret;
}
/* Set tdm/i2s1 master bclk ratio */
ret = snd_soc_dai_set_bclk_ratio(codec_dai, ch * format);
if (ret < 0) {
dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
return ret;
}
clk_set_rate(drvdata->wclk, srate);
clk_set_rate(drvdata->bclk, srate * ch * format);
return 0;
}
static const struct snd_soc_ops acp_card_rt5682s_ops = {
.startup = acp_card_hs_startup,
.hw_params = acp_card_rt5682s_hw_params,
};
static const unsigned int dmic_channels[] = {
@ -351,19 +469,55 @@ static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata;
struct snd_soc_dai *codec_dai;
int srate, i, ret = 0;
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
int i, ret = 0;
unsigned int fmt, srate, ch, format;
srate = params_rate(params);
ch = params_channels(params);
format = params_physical_width(params);
if (drvdata->amp_codec_id != RT1019)
return -EINVAL;
if (drvdata->tdm_mode)
fmt = SND_SOC_DAIFMT_DSP_A;
else
fmt = SND_SOC_DAIFMT_I2S;
if (drvdata->soc_mclk)
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
else
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
if (ret && ret != -ENOTSUPP) {
dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);
return ret;
}
if (drvdata->tdm_mode) {
/**
* As codec supports slot 2 and slot 3 for playback.
*/
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xC, 0, 8, 16);
if (ret && ret != -ENOTSUPP) {
dev_err(rtd->dev, "set TDM slot err: %d\n", ret);
return ret;
}
}
for_each_rtd_codec_dais(rtd, i, codec_dai) {
if (strcmp(codec_dai->name, "rt1019-aif"))
continue;
ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
64 * srate, 256 * srate);
if (drvdata->tdm_mode)
ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
TDM_CHANNELS * format * srate, 256 * srate);
else
ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
ch * format * srate, 256 * srate);
if (ret < 0)
return ret;
@ -371,6 +525,41 @@ static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
256 * srate, SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
if (drvdata->tdm_mode) {
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A
| SND_SOC_DAIFMT_NB_NF);
if (ret < 0) {
dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
return ret;
}
/**
* As codec supports slot 2 for left channel playback.
*/
if (!strcmp(codec_dai->component->name, "i2c-10EC1019:00")) {
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x4, 0x4, 8, 16);
if (ret < 0)
break;
}
/**
* As codec supports slot 3 for right channel playback.
*/
if (!strcmp(codec_dai->component->name, "i2c-10EC1019:01")) {
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x8, 0x8, 8, 16);
if (ret < 0)
break;
}
}
}
if (!drvdata->soc_mclk) {
ret = acp_clk_enable(drvdata, srate, ch * format);
if (ret < 0) {
dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
return ret;
}
}
return 0;
@ -379,10 +568,6 @@ static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
static int acp_card_amp_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
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 = 0;
runtime->hw.channels_max = DUAL_CHANNEL;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
@ -390,14 +575,7 @@ 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);
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;
return 0;
}
static const struct snd_soc_ops acp_card_rt1019_ops = {
@ -426,9 +604,61 @@ static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd)
ARRAY_SIZE(max98360a_map));
}
static int acp_card_maxim_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_card_drvdata *drvdata = card->drvdata;
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
unsigned int fmt, srate, ch, format;
int ret;
srate = params_rate(params);
ch = params_channels(params);
format = params_physical_width(params);
if (drvdata->tdm_mode)
fmt = SND_SOC_DAIFMT_DSP_A;
else
fmt = SND_SOC_DAIFMT_I2S;
if (drvdata->soc_mclk)
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
else
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
if (ret && ret != -ENOTSUPP) {
dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);
return ret;
}
if (drvdata->tdm_mode) {
/**
* As codec supports slot 2 and slot 3 for playback.
*/
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xC, 0, 8, 16);
if (ret && ret != -ENOTSUPP) {
dev_err(rtd->dev, "set TDM slot err: %d\n", ret);
return ret;
}
}
if (!drvdata->soc_mclk) {
ret = acp_clk_enable(drvdata, srate, ch * format);
if (ret < 0) {
dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
return ret;
}
}
return 0;
}
static const struct snd_soc_ops acp_card_maxim_ops = {
.startup = acp_card_amp_startup,
.shutdown = acp_card_shutdown,
.hw_params = acp_card_maxim_hw_params,
};
/* Declare nau8825 codec components */
@ -446,7 +676,6 @@ static int acp_card_nau8825_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);
@ -454,16 +683,6 @@ static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)
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 |
@ -492,8 +711,12 @@ 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_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_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
int ret;
unsigned int fmt;
ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_FS,
(48000 * 256), SND_SOC_CLOCK_IN);
@ -507,6 +730,44 @@ static int acp_nau8825_hw_params(struct snd_pcm_substream *substream,
return ret;
}
if (drvdata->tdm_mode)
fmt = SND_SOC_DAIFMT_DSP_A;
else
fmt = SND_SOC_DAIFMT_I2S;
if (drvdata->soc_mclk)
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
else
fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
if (ret && ret != -ENOTSUPP) {
dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);
return ret;
}
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;
}
if (drvdata->tdm_mode) {
/**
* As codec supports slot 4 and slot 5 for playback and slot 6 for capture.
*/
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x30, 0xC0, 8, 16);
if (ret && ret != -ENOTSUPP) {
dev_err(rtd->dev, "set TDM slot err: %d\n", ret);
return ret;
}
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x40, 0x30, 8, 16);
if (ret < 0) {
dev_warn(rtd->dev, "set TDM slot err:%d\n", ret);
return ret;
}
}
return ret;
}
@ -565,8 +826,12 @@ 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_sp_virtual,
DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp-virtual")));
SND_SOC_DAILINK_DEF(sof_hs,
DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs")));
SND_SOC_DAILINK_DEF(sof_hs_virtual,
DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs-virtual")));
SND_SOC_DAILINK_DEF(sof_dmic,
DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
SND_SOC_DAILINK_DEF(pdm_dmic,
@ -596,8 +861,6 @@ static int acp_rtk_set_bias_level(struct snd_soc_card *card,
switch (level) {
case SND_SOC_BIAS_STANDBY:
if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) {
clk_set_rate(drvdata->wclk, 48000);
clk_set_rate(drvdata->bclk, 48000 * 64);
/* Increase bclk's enable_count */
ret = clk_prepare_enable(drvdata->bclk);
@ -701,8 +964,8 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
if (drv_data->amp_cpu_id == I2S_SP) {
links[i].name = "acp-amp-codec";
links[i].id = AMP_BE_ID;
links[i].cpus = sof_sp;
links[i].num_cpus = ARRAY_SIZE(sof_sp);
links[i].cpus = sof_sp_virtual;
links[i].num_cpus = ARRAY_SIZE(sof_sp_virtual);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
links[i].dpcm_playback = 1;
@ -733,8 +996,8 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
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].cpus = sof_hs_virtual;
links[i].num_cpus = ARRAY_SIZE(sof_hs_virtual);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
links[i].dpcm_playback = 1;

View File

@ -18,6 +18,8 @@
#include <linux/module.h>
#include <sound/soc.h>
#define TDM_CHANNELS 8
enum be_id {
HEADSET_BE_ID = 0,
AMP_BE_ID,
@ -58,9 +60,11 @@ struct acp_card_drvdata {
struct clk *wclk;
struct clk *bclk;
bool soc_mclk;
bool tdm_mode;
};
int acp_sofdsp_dai_links_create(struct snd_soc_card *card);
int acp_legacy_dai_links_create(struct snd_soc_card *card);
extern const struct dmi_system_id acp_quirk_table[];
#endif

View File

@ -16,6 +16,7 @@
#include <sound/pcm_params.h>
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <linux/dmi.h>
#include <linux/module.h>
#include "acp-mach.h"
@ -27,6 +28,7 @@ static struct acp_card_drvdata sof_rt5682_rt1019_data = {
.hs_codec_id = RT5682,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.tdm_mode = false,
};
static struct acp_card_drvdata sof_rt5682_max_data = {
@ -36,6 +38,7 @@ static struct acp_card_drvdata sof_rt5682_max_data = {
.hs_codec_id = RT5682,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.tdm_mode = false,
};
static struct acp_card_drvdata sof_rt5682s_rt1019_data = {
@ -45,6 +48,7 @@ static struct acp_card_drvdata sof_rt5682s_rt1019_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.tdm_mode = false,
};
static struct acp_card_drvdata sof_rt5682s_max_data = {
@ -54,6 +58,7 @@ static struct acp_card_drvdata sof_rt5682s_max_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.tdm_mode = false,
};
static struct acp_card_drvdata sof_nau8825_data = {
@ -64,6 +69,7 @@ static struct acp_card_drvdata sof_nau8825_data = {
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.soc_mclk = true,
.tdm_mode = false,
};
static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = {
@ -74,6 +80,7 @@ static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = {
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.soc_mclk = true,
.tdm_mode = false,
};
static const struct snd_kcontrol_new acp_controls[] = {
@ -96,6 +103,8 @@ static int acp_sof_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = NULL;
struct device *dev = &pdev->dev;
const struct dmi_system_id *dmi_id;
struct acp_card_drvdata *acp_card_drvdata;
int ret;
if (!pdev->id_entry)
@ -114,6 +123,11 @@ static int acp_sof_probe(struct platform_device *pdev)
card->num_controls = ARRAY_SIZE(acp_controls);
card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
acp_card_drvdata = card->drvdata;
dmi_id = dmi_first_match(acp_quirk_table);
if (dmi_id && dmi_id->driver_data)
acp_card_drvdata->tdm_mode = dmi_id->driver_data;
acp_sofdsp_dai_links_create(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);

View File

@ -11,7 +11,6 @@
#define ACP63_REG_START 0x1240000
#define ACP63_REG_END 0x1250200
#define ACP63_DEVS 3
#define ACP63_PDM_MODE 1
#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001
#define ACP_PGFSM_CNTL_POWER_ON_MASK 1
@ -30,7 +29,7 @@
#define ACP_ERROR_STAT 29
#define PDM_DECIMATION_FACTOR 2
#define ACP_PDM_CLK_FREQ_MASK 7
#define ACP_WOV_MISC_CTRL_MASK 0x10
#define ACP_WOV_GAIN_CONTROL GENMASK(4, 3)
#define ACP_PDM_ENABLE 1
#define ACP_PDM_DISABLE 0
#define ACP_PDM_DMA_EN_STATUS 2
@ -54,6 +53,11 @@
/* time in ms for runtime suspend delay */
#define ACP_SUSPEND_DELAY_MS 2000
#define ACP63_DMIC_ADDR 2
#define ACP63_PDM_MODE_DEVS 3
#define ACP63_PDM_DEV_MASK 1
#define ACP_DMIC_DEV 2
enum acp_config {
ACP_CONFIG_0 = 0,
ACP_CONFIG_1,
@ -84,6 +88,7 @@ struct pdm_stream_instance {
struct pdm_dev_data {
u32 pdm_irq;
void __iomem *acp63_base;
struct mutex *acp_lock;
struct snd_pcm_substream *capture_stream;
};
@ -100,6 +105,9 @@ static inline void acp63_writel(u32 val, void __iomem *base_addr)
struct acp63_dev_data {
void __iomem *acp63_base;
struct resource *res;
bool acp63_audio_mode;
struct platform_device *pdev[ACP63_DEVS];
struct mutex acp_lock; /* protect shared registers */
u16 pdev_mask;
u16 pdev_count;
u16 pdm_dev_index;
};

View File

@ -116,6 +116,7 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
struct acp63_dev_data *adata;
struct pdm_dev_data *ps_pdm_data;
u32 val;
u16 pdev_index;
adata = dev_id;
if (!adata)
@ -123,7 +124,8 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
val = acp63_readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
if (val & BIT(PDM_DMA_STAT)) {
ps_pdm_data = dev_get_drvdata(&adata->pdev[0]->dev);
pdev_index = adata->pdm_dev_index;
ps_pdm_data = dev_get_drvdata(&adata->pdev[pdev_index]->dev);
acp63_writel(BIT(PDM_DMA_STAT), adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
if (ps_pdm_data->capture_stream)
snd_pcm_period_elapsed(ps_pdm_data->capture_stream);
@ -132,17 +134,124 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
return IRQ_NONE;
}
static void get_acp63_device_config(u32 config, struct pci_dev *pci,
struct acp63_dev_data *acp_data)
{
struct acpi_device *dmic_dev;
const union acpi_object *obj;
bool is_dmic_dev = false;
dmic_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_DMIC_ADDR, 0);
if (dmic_dev) {
if (!acpi_dev_get_property(dmic_dev, "acp-audio-device-type",
ACPI_TYPE_INTEGER, &obj) &&
obj->integer.value == ACP_DMIC_DEV)
is_dmic_dev = true;
}
switch (config) {
case ACP_CONFIG_0:
case ACP_CONFIG_1:
case ACP_CONFIG_2:
case ACP_CONFIG_3:
case ACP_CONFIG_9:
case ACP_CONFIG_15:
dev_dbg(&pci->dev, "Audio Mode %d\n", config);
break;
default:
if (is_dmic_dev) {
acp_data->pdev_mask = ACP63_PDM_DEV_MASK;
acp_data->pdev_count = ACP63_PDM_MODE_DEVS;
}
break;
}
}
static void acp63_fill_platform_dev_info(struct platform_device_info *pdevinfo,
struct device *parent,
struct fwnode_handle *fw_node,
char *name, unsigned int id,
const struct resource *res,
unsigned int num_res,
const void *data,
size_t size_data)
{
pdevinfo->name = name;
pdevinfo->id = id;
pdevinfo->parent = parent;
pdevinfo->num_res = num_res;
pdevinfo->res = res;
pdevinfo->data = data;
pdevinfo->size_data = size_data;
pdevinfo->fwnode = fw_node;
}
static int create_acp63_platform_devs(struct pci_dev *pci, struct acp63_dev_data *adata, u32 addr)
{
struct platform_device_info pdevinfo[ACP63_DEVS];
struct device *parent;
int index;
int ret;
parent = &pci->dev;
dev_dbg(&pci->dev,
"%s pdev_mask:0x%x pdev_count:0x%x\n", __func__, adata->pdev_mask,
adata->pdev_count);
if (adata->pdev_mask) {
adata->res = devm_kzalloc(&pci->dev, sizeof(struct resource), GFP_KERNEL);
if (!adata->res) {
ret = -ENOMEM;
goto de_init;
}
adata->res->flags = IORESOURCE_MEM;
adata->res->start = addr;
adata->res->end = addr + (ACP63_REG_END - ACP63_REG_START);
memset(&pdevinfo, 0, sizeof(pdevinfo));
}
switch (adata->pdev_mask) {
case ACP63_PDM_DEV_MASK:
adata->pdm_dev_index = 0;
acp63_fill_platform_dev_info(&pdevinfo[0], parent, NULL, "acp_ps_pdm_dma",
0, adata->res, 1, &adata->acp_lock,
sizeof(adata->acp_lock));
acp63_fill_platform_dev_info(&pdevinfo[1], parent, NULL, "dmic-codec",
0, NULL, 0, NULL, 0);
acp63_fill_platform_dev_info(&pdevinfo[2], parent, NULL, "acp_ps_mach",
0, NULL, 0, NULL, 0);
break;
default:
dev_dbg(&pci->dev, "No PDM devices found\n");
return 0;
}
for (index = 0; index < adata->pdev_count; index++) {
adata->pdev[index] = platform_device_register_full(&pdevinfo[index]);
if (IS_ERR(adata->pdev[index])) {
dev_err(&pci->dev,
"cannot register %s device\n", pdevinfo[index].name);
ret = PTR_ERR(adata->pdev[index]);
goto unregister_devs;
}
}
return 0;
unregister_devs:
for (--index; index >= 0; index--)
platform_device_unregister(adata->pdev[index]);
de_init:
if (acp63_deinit(adata->acp63_base, &pci->dev))
dev_err(&pci->dev, "ACP de-init failed\n");
return ret;
}
static int snd_acp63_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
struct acp63_dev_data *adata;
struct platform_device_info pdevinfo[ACP63_DEVS];
int index, ret;
int val = 0x00;
struct acpi_device *adev;
const union acpi_object *obj;
u32 addr;
unsigned int irqflags;
u32 irqflags;
int val;
int ret;
irqflags = IRQF_SHARED;
/* Pink Sardine device check */
@ -179,86 +288,28 @@ static int snd_acp63_probe(struct pci_dev *pci,
}
pci_set_master(pci);
pci_set_drvdata(pci, adata);
mutex_init(&adata->acp_lock);
ret = acp63_init(adata->acp63_base, &pci->dev);
if (ret)
goto release_regions;
ret = devm_request_irq(&pci->dev, pci->irq, acp63_irq_handler,
irqflags, "ACP_PCI_IRQ", adata);
if (ret) {
dev_err(&pci->dev, "ACP PCI IRQ request failed\n");
goto de_init;
}
val = acp63_readl(adata->acp63_base + ACP_PIN_CONFIG);
switch (val) {
case ACP_CONFIG_0:
case ACP_CONFIG_1:
case ACP_CONFIG_2:
case ACP_CONFIG_3:
case ACP_CONFIG_9:
case ACP_CONFIG_15:
dev_info(&pci->dev, "Audio Mode %d\n", val);
break;
default:
/* Checking DMIC hardware*/
adev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), 0x02, 0);
if (!adev)
break;
if (!acpi_dev_get_property(adev, "acp-audio-device-type",
ACPI_TYPE_INTEGER, &obj) &&
obj->integer.value == 2) {
adata->res = devm_kzalloc(&pci->dev, sizeof(struct resource), GFP_KERNEL);
if (!adata->res) {
ret = -ENOMEM;
goto de_init;
}
adata->res->name = "acp_iomem";
adata->res->flags = IORESOURCE_MEM;
adata->res->start = addr;
adata->res->end = addr + (ACP63_REG_END - ACP63_REG_START);
adata->acp63_audio_mode = ACP63_PDM_MODE;
memset(&pdevinfo, 0, sizeof(pdevinfo));
pdevinfo[0].name = "acp_ps_pdm_dma";
pdevinfo[0].id = 0;
pdevinfo[0].parent = &pci->dev;
pdevinfo[0].num_res = 1;
pdevinfo[0].res = adata->res;
pdevinfo[1].name = "dmic-codec";
pdevinfo[1].id = 0;
pdevinfo[1].parent = &pci->dev;
pdevinfo[2].name = "acp_ps_mach";
pdevinfo[2].id = 0;
pdevinfo[2].parent = &pci->dev;
for (index = 0; index < ACP63_DEVS; index++) {
adata->pdev[index] =
platform_device_register_full(&pdevinfo[index]);
if (IS_ERR(adata->pdev[index])) {
dev_err(&pci->dev,
"cannot register %s device\n",
pdevinfo[index].name);
ret = PTR_ERR(adata->pdev[index]);
goto unregister_devs;
}
ret = devm_request_irq(&pci->dev, pci->irq, acp63_irq_handler,
irqflags, "ACP_PCI_IRQ", adata);
if (ret) {
dev_err(&pci->dev, "ACP PCI IRQ request failed\n");
goto unregister_devs;
}
}
}
break;
get_acp63_device_config(val, pci, adata);
ret = create_acp63_platform_devs(pci, adata, addr);
if (ret < 0) {
dev_err(&pci->dev, "ACP platform devices creation failed\n");
goto de_init;
}
pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&pci->dev);
pm_runtime_put_noidle(&pci->dev);
pm_runtime_allow(&pci->dev);
return 0;
unregister_devs:
for (--index; index >= 0; index--)
platform_device_unregister(adata->pdev[index]);
de_init:
if (acp63_deinit(adata->acp63_base, &pci->dev))
dev_err(&pci->dev, "ACP de-init failed\n");
@ -305,10 +356,8 @@ static void snd_acp63_remove(struct pci_dev *pci)
int ret, index;
adata = pci_get_drvdata(pci);
if (adata->acp63_audio_mode == ACP63_PDM_MODE) {
for (index = 0; index < ACP63_DEVS; index++)
platform_device_unregister(adata->pdev[index]);
}
for (index = 0; index < adata->pdev_count; index++)
platform_device_unregister(adata->pdev[index]);
ret = acp63_deinit(adata->acp63_base, &pci->dev);
if (ret)
dev_err(&pci->dev, "ACP de-init failed\n");

View File

@ -7,6 +7,7 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/bitfield.h>
#include <linux/err.h>
#include <linux/io.h>
#include <sound/pcm_params.h>
@ -18,6 +19,10 @@
#define DRV_NAME "acp_ps_pdm_dma"
static int pdm_gain = 3;
module_param(pdm_gain, int, 0644);
MODULE_PARM_DESC(pdm_gain, "Gain control (0-3)");
static const struct snd_pcm_hardware acp63_pdm_hardware_capture = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@ -55,26 +60,31 @@ static void acp63_enable_pdm_clock(void __iomem *acp_base)
acp63_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL);
pdm_ctrl = acp63_readl(acp_base + ACP_WOV_MISC_CTRL);
pdm_ctrl |= ACP_WOV_MISC_CTRL_MASK;
pdm_ctrl &= ~ACP_WOV_GAIN_CONTROL;
pdm_ctrl |= FIELD_PREP(ACP_WOV_GAIN_CONTROL, clamp(pdm_gain, 0, 3));
acp63_writel(pdm_ctrl, acp_base + ACP_WOV_MISC_CTRL);
}
static void acp63_enable_pdm_interrupts(void __iomem *acp_base)
static void acp63_enable_pdm_interrupts(struct pdm_dev_data *adata)
{
u32 ext_int_ctrl;
ext_int_ctrl = acp63_readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
mutex_lock(adata->acp_lock);
ext_int_ctrl = acp63_readl(adata->acp63_base + ACP_EXTERNAL_INTR_CNTL);
ext_int_ctrl |= PDM_DMA_INTR_MASK;
acp63_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL);
acp63_writel(ext_int_ctrl, adata->acp63_base + ACP_EXTERNAL_INTR_CNTL);
mutex_unlock(adata->acp_lock);
}
static void acp63_disable_pdm_interrupts(void __iomem *acp_base)
static void acp63_disable_pdm_interrupts(struct pdm_dev_data *adata)
{
u32 ext_int_ctrl;
ext_int_ctrl = acp63_readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
mutex_lock(adata->acp_lock);
ext_int_ctrl = acp63_readl(adata->acp63_base + ACP_EXTERNAL_INTR_CNTL);
ext_int_ctrl &= ~PDM_DMA_INTR_MASK;
acp63_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL);
acp63_writel(ext_int_ctrl, adata->acp63_base + ACP_EXTERNAL_INTR_CNTL);
mutex_unlock(adata->acp_lock);
}
static bool acp63_check_pdm_dma_status(void __iomem *acp_base)
@ -196,7 +206,7 @@ static int acp63_pdm_dma_open(struct snd_soc_component *component,
return ret;
}
acp63_enable_pdm_interrupts(adata->acp63_base);
acp63_enable_pdm_interrupts(adata);
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
adata->capture_stream = substream;
@ -272,7 +282,7 @@ static int acp63_pdm_dma_close(struct snd_soc_component *component,
struct pdm_dev_data *adata = dev_get_drvdata(component->dev);
struct snd_pcm_runtime *runtime = substream->runtime;
acp63_disable_pdm_interrupts(adata->acp63_base);
acp63_disable_pdm_interrupts(adata);
adata->capture_stream = NULL;
kfree(runtime->private_data);
return 0;
@ -353,6 +363,10 @@ static int acp63_pdm_audio_probe(struct platform_device *pdev)
struct pdm_dev_data *adata;
int status;
if (!pdev->dev.platform_data) {
dev_err(&pdev->dev, "platform_data not retrieved\n");
return -ENODEV;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
@ -368,7 +382,7 @@ static int acp63_pdm_audio_probe(struct platform_device *pdev)
return -ENOMEM;
adata->capture_stream = NULL;
adata->acp_lock = pdev->dev.platform_data;
dev_set_drvdata(&pdev->dev, adata);
status = devm_snd_soc_register_component(&pdev->dev,
&acp63_pdm_component,
@ -408,7 +422,7 @@ static int __maybe_unused acp63_pdm_resume(struct device *dev)
acp63_init_pdm_ring_buffer(PDM_MEM_WINDOW_START, buffer_len,
period_bytes, adata->acp63_base);
}
acp63_enable_pdm_interrupts(adata->acp63_base);
acp63_enable_pdm_interrupts(adata);
return 0;
}
@ -417,7 +431,7 @@ static int __maybe_unused acp63_pdm_suspend(struct device *dev)
struct pdm_dev_data *adata;
adata = dev_get_drvdata(dev);
acp63_disable_pdm_interrupts(adata->acp63_base);
acp63_disable_pdm_interrupts(adata);
return 0;
}
@ -426,7 +440,7 @@ static int __maybe_unused acp63_pdm_runtime_resume(struct device *dev)
struct pdm_dev_data *adata;
adata = dev_get_drvdata(dev);
acp63_enable_pdm_interrupts(adata->acp63_base);
acp63_enable_pdm_interrupts(adata);
return 0;
}

View File

@ -315,16 +315,8 @@ static int acp3x_dai_probe(struct platform_device *pdev)
return 0;
}
static int acp3x_dai_remove(struct platform_device *pdev)
{
/* As we use devm_ memory alloc there is nothing TBD here */
return 0;
}
static struct platform_driver acp3x_dai_driver = {
.probe = acp3x_dai_probe,
.remove = acp3x_dai_remove,
.driver = {
.name = "acp3x_i2s_playcap",
},

View File

@ -6,6 +6,7 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/bitfield.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
@ -17,6 +18,10 @@
#define DRV_NAME "acp_rn_pdm_dma"
static int pdm_gain = 3;
module_param(pdm_gain, int, 0644);
MODULE_PARM_DESC(pdm_gain, "Gain control (0-3)");
static const struct snd_pcm_hardware acp_pdm_hardware_capture = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@ -80,7 +85,8 @@ static void enable_pdm_clock(void __iomem *acp_base)
rn_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL);
pdm_ctrl = rn_readl(acp_base + ACP_WOV_MISC_CTRL);
pdm_ctrl |= ACP_WOV_MISC_CTRL_MASK;
pdm_ctrl &= ~ACP_WOV_GAIN_CONTROL;
pdm_ctrl |= FIELD_PREP(ACP_WOV_GAIN_CONTROL, clamp(pdm_gain, 0, 3));
rn_writel(pdm_ctrl, acp_base + ACP_WOV_MISC_CTRL);
}

View File

@ -34,7 +34,7 @@
#define ACP_ERROR_STAT 29
#define PDM_DECIMATION_FACTOR 0x2
#define ACP_PDM_CLK_FREQ_MASK 0x07
#define ACP_WOV_MISC_CTRL_MASK 0x10
#define ACP_WOV_GAIN_CONTROL GENMASK(4, 3)
#define ACP_PDM_ENABLE 0x01
#define ACP_PDM_DISABLE 0x00
#define ACP_PDM_DMA_EN_STATUS 0x02

View File

@ -7,6 +7,7 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/bitfield.h>
#include <linux/err.h>
#include <linux/io.h>
#include <sound/pcm_params.h>
@ -18,6 +19,10 @@
#define DRV_NAME "acp_yc_pdm_dma"
static int pdm_gain = 3;
module_param(pdm_gain, int, 0644);
MODULE_PARM_DESC(pdm_gain, "Gain control (0-3)");
static const struct snd_pcm_hardware acp6x_pdm_hardware_capture = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@ -55,7 +60,8 @@ static void acp6x_enable_pdm_clock(void __iomem *acp_base)
acp6x_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL);
pdm_ctrl = acp6x_readl(acp_base + ACP_WOV_MISC_CTRL);
pdm_ctrl |= ACP_WOV_MISC_CTRL_MASK;
pdm_ctrl &= ~ACP_WOV_GAIN_CONTROL;
pdm_ctrl |= FIELD_PREP(ACP_WOV_GAIN_CONTROL, clamp(pdm_gain, 0, 3));
acp6x_writel(pdm_ctrl, acp_base + ACP_WOV_MISC_CTRL);
}

View File

@ -31,7 +31,7 @@
#define ACP_ERROR_STAT 29
#define PDM_DECIMATION_FACTOR 2
#define ACP_PDM_CLK_FREQ_MASK 7
#define ACP_WOV_MISC_CTRL_MASK 0x10
#define ACP_WOV_GAIN_CONTROL GENMASK(4, 3)
#define ACP_PDM_ENABLE 1
#define ACP_PDM_DISABLE 0
#define ACP_PDM_DMA_EN_STATUS 2

View File

@ -616,11 +616,6 @@ unregister_codec:
return ret;
}
static int atmel_classd_remove(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver atmel_classd_driver = {
.driver = {
.name = "atmel-classd",
@ -628,7 +623,6 @@ static struct platform_driver atmel_classd_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = atmel_classd_probe,
.remove = atmel_classd_remove,
};
module_platform_driver(atmel_classd_driver);

View File

@ -692,11 +692,6 @@ unregister_codec:
return ret;
}
static int atmel_pdmic_remove(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver atmel_pdmic_driver = {
.driver = {
.name = "atmel-pdmic",
@ -704,7 +699,6 @@ static struct platform_driver atmel_pdmic_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = atmel_pdmic_probe,
.remove = atmel_pdmic_remove,
};
module_platform_driver(atmel_pdmic_driver);

View File

@ -11,6 +11,7 @@
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <sound/core.h>
@ -112,10 +113,10 @@ struct mchp_pdmc {
struct clk *pclk;
struct clk *gclk;
u32 pdmcen;
u32 suspend_irq;
int mic_no;
int sinc_order;
bool audio_filter_en;
u8 gclk_enabled:1;
};
static const char *const mchp_pdmc_sinc_filter_order_text[] = {
@ -454,13 +455,6 @@ static int mchp_pdmc_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mchp_pdmc *dd = snd_soc_dai_get_drvdata(dai);
int ret;
ret = clk_prepare_enable(dd->pclk);
if (ret) {
dev_err(dd->dev, "failed to enable the peripheral clock: %d\n", ret);
return ret;
}
regmap_write(dd->regmap, MCHP_PDMC_CR, MCHP_PDMC_CR_SWRST);
@ -470,14 +464,6 @@ static int mchp_pdmc_startup(struct snd_pcm_substream *substream,
return 0;
}
static void mchp_pdmc_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mchp_pdmc *dd = snd_soc_dai_get_drvdata(dai);
clk_disable_unprepare(dd->pclk);
}
static int mchp_pdmc_dai_probe(struct snd_soc_dai *dai)
{
struct mchp_pdmc *dd = snd_soc_dai_get_drvdata(dai);
@ -594,11 +580,6 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream,
cfgr_val |= MCHP_PDMC_CFGR_BSSEL(i);
}
if (dd->gclk_enabled) {
clk_disable_unprepare(dd->gclk);
dd->gclk_enabled = 0;
}
for (osr_start = dd->audio_filter_en ? 64 : 8;
osr_start <= 256 && best_diff_rate; osr_start *= 2) {
long round_rate;
@ -620,8 +601,12 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
/* CLK is enabled by runtime PM. */
clk_disable_unprepare(dd->gclk);
/* set the rate */
ret = clk_set_rate(dd->gclk, gclk_rate);
clk_prepare_enable(dd->gclk);
if (ret) {
dev_err(comp->dev, "unable to set rate %lu to GCLK: %d\n",
gclk_rate, ret);
@ -636,9 +621,6 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream,
mr_val |= MCHP_PDMC_MR_CHUNK(dd->addr.maxburst);
dev_dbg(comp->dev, "maxburst set to %d\n", dd->addr.maxburst);
clk_prepare_enable(dd->gclk);
dd->gclk_enabled = 1;
snd_soc_component_update_bits(comp, MCHP_PDMC_MR,
MCHP_PDMC_MR_OSR_MASK |
MCHP_PDMC_MR_SINCORDER_MASK |
@ -650,19 +632,6 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int mchp_pdmc_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mchp_pdmc *dd = snd_soc_dai_get_drvdata(dai);
if (dd->gclk_enabled) {
clk_disable_unprepare(dd->gclk);
dd->gclk_enabled = 0;
}
return 0;
}
static int mchp_pdmc_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
@ -673,22 +642,27 @@ static int mchp_pdmc_trigger(struct snd_pcm_substream *substream,
#endif
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_START:
/* Enable overrun and underrun error interrupts */
regmap_write(dd->regmap, MCHP_PDMC_IER,
regmap_write(dd->regmap, MCHP_PDMC_IER, dd->suspend_irq |
MCHP_PDMC_IR_RXOVR | MCHP_PDMC_IR_RXUDR);
dd->suspend_irq = 0;
fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
snd_soc_component_update_bits(cpu, MCHP_PDMC_MR,
MCHP_PDMC_MR_PDMCEN_MASK,
dd->pdmcen);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
regmap_read(dd->regmap, MCHP_PDMC_IMR, &dd->suspend_irq);
fallthrough;
case SNDRV_PCM_TRIGGER_STOP:
/* Disable overrun and underrun error interrupts */
regmap_write(dd->regmap, MCHP_PDMC_IDR,
regmap_write(dd->regmap, MCHP_PDMC_IDR, dd->suspend_irq |
MCHP_PDMC_IR_RXOVR | MCHP_PDMC_IR_RXUDR);
fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
snd_soc_component_update_bits(cpu, MCHP_PDMC_MR,
MCHP_PDMC_MR_PDMCEN_MASK, 0);
break;
@ -711,9 +685,7 @@ static int mchp_pdmc_trigger(struct snd_pcm_substream *substream,
static const struct snd_soc_dai_ops mchp_pdmc_dai_ops = {
.set_fmt = mchp_pdmc_set_fmt,
.startup = mchp_pdmc_startup,
.shutdown = mchp_pdmc_shutdown,
.hw_params = mchp_pdmc_hw_params,
.hw_free = mchp_pdmc_hw_free,
.trigger = mchp_pdmc_trigger,
};
@ -864,6 +836,7 @@ static const struct regmap_config mchp_pdmc_regmap_config = {
.readable_reg = mchp_pdmc_readable_reg,
.writeable_reg = mchp_pdmc_writeable_reg,
.precious_reg = mchp_pdmc_precious_reg,
.cache_type = REGCACHE_FLAT,
};
static int mchp_pdmc_dt_init(struct mchp_pdmc *dd)
@ -970,6 +943,49 @@ static struct snd_dmaengine_pcm_config mchp_pdmc_config = {
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
};
static int mchp_pdmc_runtime_suspend(struct device *dev)
{
struct mchp_pdmc *dd = dev_get_drvdata(dev);
regcache_cache_only(dd->regmap, true);
clk_disable_unprepare(dd->gclk);
clk_disable_unprepare(dd->pclk);
return 0;
}
static int mchp_pdmc_runtime_resume(struct device *dev)
{
struct mchp_pdmc *dd = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(dd->pclk);
if (ret) {
dev_err(dd->dev,
"failed to enable the peripheral clock: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(dd->gclk);
if (ret) {
dev_err(dd->dev,
"failed to enable generic clock: %d\n", ret);
goto disable_pclk;
}
regcache_cache_only(dd->regmap, false);
regcache_mark_dirty(dd->regmap);
ret = regcache_sync(dd->regmap);
if (ret) {
regcache_cache_only(dd->regmap, true);
clk_disable_unprepare(dd->gclk);
disable_pclk:
clk_disable_unprepare(dd->pclk);
}
return ret;
}
static int mchp_pdmc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -1039,18 +1055,25 @@ static int mchp_pdmc_probe(struct platform_device *pdev)
dd->addr.addr = (dma_addr_t)res->start + MCHP_PDMC_RHR;
platform_set_drvdata(pdev, dd);
pm_runtime_enable(dd->dev);
if (!pm_runtime_enabled(dd->dev)) {
ret = mchp_pdmc_runtime_resume(dd->dev);
if (ret)
return ret;
}
/* register platform */
ret = devm_snd_dmaengine_pcm_register(dev, &mchp_pdmc_config, 0);
if (ret) {
dev_err(dev, "could not register platform: %d\n", ret);
return ret;
goto pm_runtime_suspend;
}
ret = devm_snd_soc_register_component(dev, &mchp_pdmc_dai_component,
&mchp_pdmc_dai, 1);
if (ret) {
dev_err(dev, "could not register CPU DAI: %d\n", ret);
return ret;
goto pm_runtime_suspend;
}
/* print IP version */
@ -1059,6 +1082,25 @@ static int mchp_pdmc_probe(struct platform_device *pdev)
version & MCHP_PDMC_VER_VERSION);
return 0;
pm_runtime_suspend:
if (!pm_runtime_status_suspended(dd->dev))
mchp_pdmc_runtime_suspend(dd->dev);
pm_runtime_disable(dd->dev);
return ret;
}
static int mchp_pdmc_remove(struct platform_device *pdev)
{
struct mchp_pdmc *dd = platform_get_drvdata(pdev);
if (!pm_runtime_status_suspended(dd->dev))
mchp_pdmc_runtime_suspend(dd->dev);
pm_runtime_disable(dd->dev);
return 0;
}
static const struct of_device_id mchp_pdmc_of_match[] = {
@ -1070,13 +1112,20 @@ static const struct of_device_id mchp_pdmc_of_match[] = {
};
MODULE_DEVICE_TABLE(of, mchp_pdmc_of_match);
static const struct dev_pm_ops mchp_pdmc_pm_ops = {
SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
RUNTIME_PM_OPS(mchp_pdmc_runtime_suspend, mchp_pdmc_runtime_resume,
NULL)
};
static struct platform_driver mchp_pdmc_driver = {
.driver = {
.name = "mchp-pdmc",
.of_match_table = of_match_ptr(mchp_pdmc_of_match),
.pm = &snd_soc_pm_ops,
.pm = pm_ptr(&mchp_pdmc_pm_ops),
},
.probe = mchp_pdmc_probe,
.remove = mchp_pdmc_remove,
};
module_platform_driver(mchp_pdmc_driver);

View File

@ -9,6 +9,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/spinlock.h>
@ -192,6 +193,43 @@ static bool mchp_spdifrx_precious_reg(struct device *dev, unsigned int reg)
}
}
static bool mchp_spdifrx_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case SPDIFRX_IMR:
case SPDIFRX_ISR:
case SPDIFRX_RSR:
case SPDIFRX_CHSR(0, 0):
case SPDIFRX_CHSR(0, 1):
case SPDIFRX_CHSR(0, 2):
case SPDIFRX_CHSR(0, 3):
case SPDIFRX_CHSR(0, 4):
case SPDIFRX_CHSR(0, 5):
case SPDIFRX_CHUD(0, 0):
case SPDIFRX_CHUD(0, 1):
case SPDIFRX_CHUD(0, 2):
case SPDIFRX_CHUD(0, 3):
case SPDIFRX_CHUD(0, 4):
case SPDIFRX_CHUD(0, 5):
case SPDIFRX_CHSR(1, 0):
case SPDIFRX_CHSR(1, 1):
case SPDIFRX_CHSR(1, 2):
case SPDIFRX_CHSR(1, 3):
case SPDIFRX_CHSR(1, 4):
case SPDIFRX_CHSR(1, 5):
case SPDIFRX_CHUD(1, 0):
case SPDIFRX_CHUD(1, 1):
case SPDIFRX_CHUD(1, 2):
case SPDIFRX_CHUD(1, 3):
case SPDIFRX_CHUD(1, 4):
case SPDIFRX_CHUD(1, 5):
case SPDIFRX_VERSION:
return true;
default:
return false;
}
}
static const struct regmap_config mchp_spdifrx_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@ -200,6 +238,8 @@ static const struct regmap_config mchp_spdifrx_regmap_config = {
.readable_reg = mchp_spdifrx_readable_reg,
.writeable_reg = mchp_spdifrx_writeable_reg,
.precious_reg = mchp_spdifrx_precious_reg,
.volatile_reg = mchp_spdifrx_volatile_reg,
.cache_type = REGCACHE_FLAT,
};
#define SPDIFRX_GCLK_RATIO_MIN (12 * 64)
@ -209,17 +249,34 @@ static const struct regmap_config mchp_spdifrx_regmap_config = {
#define SPDIFRX_CHANNELS 2
/**
* struct mchp_spdifrx_ch_stat: MCHP SPDIFRX channel status
* @data: channel status bits
* @done: completion to signal channel status bits acquisition done
*/
struct mchp_spdifrx_ch_stat {
unsigned char data[SPDIFRX_CS_BITS / 8];
struct completion done;
};
/**
* struct mchp_spdifrx_user_data: MCHP SPDIFRX user data
* @data: user data bits
* @done: completion to signal user data bits acquisition done
*/
struct mchp_spdifrx_user_data {
unsigned char data[SPDIFRX_UD_BITS / 8];
struct completion done;
spinlock_t lock; /* protect access to user data */
};
/**
* struct mchp_spdifrx_mixer_control: MCHP SPDIFRX mixer control data structure
* @ch_stat: array of channel statuses
* @user_data: array of user data
* @ulock: ulock bit status
* @badf: badf bit status
* @signal: signal bit status
*/
struct mchp_spdifrx_mixer_control {
struct mchp_spdifrx_ch_stat ch_stat[SPDIFRX_CHANNELS];
struct mchp_spdifrx_user_data user_data[SPDIFRX_CHANNELS];
@ -228,17 +285,26 @@ struct mchp_spdifrx_mixer_control {
bool signal;
};
/**
* struct mchp_spdifrx_dev: MCHP SPDIFRX device data structure
* @capture: DAI DMA configuration data
* @control: mixer controls
* @mlock: mutex to protect concurency b/w configuration and control APIs
* @dev: struct device
* @regmap: regmap for this device
* @pclk: peripheral clock
* @gclk: generic clock
* @trigger_enabled: true if enabled though trigger() ops
*/
struct mchp_spdifrx_dev {
struct snd_dmaengine_dai_dma_data capture;
struct mchp_spdifrx_mixer_control control;
spinlock_t blockend_lock; /* protect access to blockend_refcount */
int blockend_refcount;
struct mutex mlock;
struct device *dev;
struct regmap *regmap;
struct clk *pclk;
struct clk *gclk;
unsigned int fmt;
unsigned int gclk_enabled:1;
unsigned int trigger_enabled;
};
static void mchp_spdifrx_channel_status_read(struct mchp_spdifrx_dev *dev,
@ -275,37 +341,11 @@ static void mchp_spdifrx_channel_user_data_read(struct mchp_spdifrx_dev *dev,
}
}
/* called from non-atomic context only */
static void mchp_spdifrx_isr_blockend_en(struct mchp_spdifrx_dev *dev)
{
unsigned long flags;
spin_lock_irqsave(&dev->blockend_lock, flags);
dev->blockend_refcount++;
/* don't enable BLOCKEND interrupt if it's already enabled */
if (dev->blockend_refcount == 1)
regmap_write(dev->regmap, SPDIFRX_IER, SPDIFRX_IR_BLOCKEND);
spin_unlock_irqrestore(&dev->blockend_lock, flags);
}
/* called from atomic/non-atomic context */
static void mchp_spdifrx_isr_blockend_dis(struct mchp_spdifrx_dev *dev)
{
unsigned long flags;
spin_lock_irqsave(&dev->blockend_lock, flags);
dev->blockend_refcount--;
/* don't enable BLOCKEND interrupt if it's already enabled */
if (dev->blockend_refcount == 0)
regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_BLOCKEND);
spin_unlock_irqrestore(&dev->blockend_lock, flags);
}
static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id)
{
struct mchp_spdifrx_dev *dev = dev_id;
struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
u32 sr, imr, pending, idr = 0;
u32 sr, imr, pending;
irqreturn_t ret = IRQ_NONE;
int ch;
@ -320,13 +360,10 @@ static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id)
if (pending & SPDIFRX_IR_BLOCKEND) {
for (ch = 0; ch < SPDIFRX_CHANNELS; ch++) {
spin_lock(&ctrl->user_data[ch].lock);
mchp_spdifrx_channel_user_data_read(dev, ch);
spin_unlock(&ctrl->user_data[ch].lock);
complete(&ctrl->user_data[ch].done);
}
mchp_spdifrx_isr_blockend_dis(dev);
regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_BLOCKEND);
ret = IRQ_HANDLED;
}
@ -334,7 +371,7 @@ static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id)
if (pending & SPDIFRX_IR_CSC(ch)) {
mchp_spdifrx_channel_status_read(dev, ch);
complete(&ctrl->ch_stat[ch].done);
idr |= SPDIFRX_IR_CSC(ch);
regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_CSC(ch));
ret = IRQ_HANDLED;
}
}
@ -344,8 +381,6 @@ static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id)
ret = IRQ_HANDLED;
}
regmap_write(dev->regmap, SPDIFRX_IDR, idr);
return ret;
}
@ -353,47 +388,40 @@ static int mchp_spdifrx_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
u32 mr;
int running;
int ret;
regmap_read(dev->regmap, SPDIFRX_MR, &mr);
running = !!(mr & SPDIFRX_MR_RXEN_ENABLE);
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (!running) {
mr &= ~SPDIFRX_MR_RXEN_MASK;
mr |= SPDIFRX_MR_RXEN_ENABLE;
/* enable overrun interrupts */
regmap_write(dev->regmap, SPDIFRX_IER,
SPDIFRX_IR_OVERRUN);
}
mutex_lock(&dev->mlock);
/* Enable overrun interrupts */
regmap_write(dev->regmap, SPDIFRX_IER, SPDIFRX_IR_OVERRUN);
/* Enable receiver. */
regmap_update_bits(dev->regmap, SPDIFRX_MR, SPDIFRX_MR_RXEN_MASK,
SPDIFRX_MR_RXEN_ENABLE);
dev->trigger_enabled = true;
mutex_unlock(&dev->mlock);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (running) {
mr &= ~SPDIFRX_MR_RXEN_MASK;
mr |= SPDIFRX_MR_RXEN_DISABLE;
/* disable overrun interrupts */
regmap_write(dev->regmap, SPDIFRX_IDR,
SPDIFRX_IR_OVERRUN);
}
mutex_lock(&dev->mlock);
/* Disable overrun interrupts */
regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_OVERRUN);
/* Disable receiver. */
regmap_update_bits(dev->regmap, SPDIFRX_MR, SPDIFRX_MR_RXEN_MASK,
SPDIFRX_MR_RXEN_DISABLE);
dev->trigger_enabled = false;
mutex_unlock(&dev->mlock);
break;
default:
return -EINVAL;
ret = -EINVAL;
}
ret = regmap_write(dev->regmap, SPDIFRX_MR, mr);
if (ret) {
dev_err(dev->dev, "unable to enable/disable RX: %d\n", ret);
return ret;
}
return 0;
return ret;
}
static int mchp_spdifrx_hw_params(struct snd_pcm_substream *substream,
@ -401,7 +429,7 @@ static int mchp_spdifrx_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
u32 mr;
u32 mr = 0;
int ret;
dev_dbg(dev->dev, "%s() rate=%u format=%#x width=%u channels=%u\n",
@ -413,13 +441,6 @@ static int mchp_spdifrx_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
regmap_read(dev->regmap, SPDIFRX_MR, &mr);
if (mr & SPDIFRX_MR_RXEN_ENABLE) {
dev_err(dev->dev, "PCM already running\n");
return -EBUSY;
}
if (params_channels(params) != SPDIFRX_CHANNELS) {
dev_err(dev->dev, "unsupported number of channels: %d\n",
params_channels(params));
@ -445,47 +466,46 @@ static int mchp_spdifrx_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
if (dev->gclk_enabled) {
clk_disable_unprepare(dev->gclk);
dev->gclk_enabled = 0;
mutex_lock(&dev->mlock);
if (dev->trigger_enabled) {
dev_err(dev->dev, "PCM already running\n");
ret = -EBUSY;
goto unlock;
}
/* GCLK is enabled by runtime PM. */
clk_disable_unprepare(dev->gclk);
ret = clk_set_min_rate(dev->gclk, params_rate(params) *
SPDIFRX_GCLK_RATIO_MIN + 1);
if (ret) {
dev_err(dev->dev,
"unable to set gclk min rate: rate %u * ratio %u + 1\n",
params_rate(params), SPDIFRX_GCLK_RATIO_MIN);
return ret;
/* Restore runtime PM state. */
clk_prepare_enable(dev->gclk);
goto unlock;
}
ret = clk_prepare_enable(dev->gclk);
if (ret) {
dev_err(dev->dev, "unable to enable gclk: %d\n", ret);
return ret;
goto unlock;
}
dev->gclk_enabled = 1;
dev_dbg(dev->dev, "GCLK range min set to %d\n",
params_rate(params) * SPDIFRX_GCLK_RATIO_MIN + 1);
return regmap_write(dev->regmap, SPDIFRX_MR, mr);
}
ret = regmap_write(dev->regmap, SPDIFRX_MR, mr);
static int mchp_spdifrx_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
unlock:
mutex_unlock(&dev->mlock);
if (dev->gclk_enabled) {
clk_disable_unprepare(dev->gclk);
dev->gclk_enabled = 0;
}
return 0;
return ret;
}
static const struct snd_soc_dai_ops mchp_spdifrx_dai_ops = {
.trigger = mchp_spdifrx_trigger,
.hw_params = mchp_spdifrx_hw_params,
.hw_free = mchp_spdifrx_hw_free,
};
#define MCHP_SPDIF_RATES SNDRV_PCM_RATE_8000_192000
@ -515,22 +535,58 @@ static int mchp_spdifrx_cs_get(struct mchp_spdifrx_dev *dev,
{
struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
struct mchp_spdifrx_ch_stat *ch_stat = &ctrl->ch_stat[channel];
int ret;
int ret = 0;
regmap_write(dev->regmap, SPDIFRX_IER, SPDIFRX_IR_CSC(channel));
/* check for new data available */
ret = wait_for_completion_interruptible_timeout(&ch_stat->done,
msecs_to_jiffies(100));
/* IP might not be started or valid stream might not be present */
if (ret < 0) {
dev_dbg(dev->dev, "channel status for channel %d timeout\n",
channel);
mutex_lock(&dev->mlock);
ret = pm_runtime_resume_and_get(dev->dev);
if (ret < 0)
goto unlock;
/*
* We may reach this point with both clocks enabled but the receiver
* still disabled. To void waiting for completion and return with
* timeout check the dev->trigger_enabled.
*
* To retrieve data:
* - if the receiver is enabled CSC IRQ will update the data in software
* caches (ch_stat->data)
* - otherwise we just update it here the software caches with latest
* available information and return it; in this case we don't need
* spin locking as the IRQ is disabled and will not be raised from
* anywhere else.
*/
if (dev->trigger_enabled) {
reinit_completion(&ch_stat->done);
regmap_write(dev->regmap, SPDIFRX_IER, SPDIFRX_IR_CSC(channel));
/* Check for new data available */
ret = wait_for_completion_interruptible_timeout(&ch_stat->done,
msecs_to_jiffies(100));
/* Valid stream might not be present */
if (ret <= 0) {
dev_dbg(dev->dev, "channel status for channel %d timeout\n",
channel);
regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_CSC(channel));
ret = ret ? : -ETIMEDOUT;
goto pm_runtime_put;
} else {
ret = 0;
}
} else {
/* Update software cache with latest channel status. */
mchp_spdifrx_channel_status_read(dev, channel);
}
memcpy(uvalue->value.iec958.status, ch_stat->data,
sizeof(ch_stat->data));
return 0;
pm_runtime_put:
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
unlock:
mutex_unlock(&dev->mlock);
return ret;
}
static int mchp_spdifrx_cs1_get(struct snd_kcontrol *kcontrol,
@ -564,29 +620,56 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,
int channel,
struct snd_ctl_elem_value *uvalue)
{
unsigned long flags;
struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
struct mchp_spdifrx_user_data *user_data = &ctrl->user_data[channel];
int ret;
int ret = 0;
reinit_completion(&user_data->done);
mchp_spdifrx_isr_blockend_en(dev);
ret = wait_for_completion_interruptible_timeout(&user_data->done,
msecs_to_jiffies(100));
/* IP might not be started or valid stream might not be present */
if (ret <= 0) {
dev_dbg(dev->dev, "user data for channel %d timeout\n",
channel);
mchp_spdifrx_isr_blockend_dis(dev);
return ret;
mutex_lock(&dev->mlock);
ret = pm_runtime_resume_and_get(dev->dev);
if (ret < 0)
goto unlock;
/*
* We may reach this point with both clocks enabled but the receiver
* still disabled. To void waiting for completion to just timeout we
* check here the dev->trigger_enabled flag.
*
* To retrieve data:
* - if the receiver is enabled we need to wait for blockend IRQ to read
* data to and update it for us in software caches
* - otherwise reading the SPDIFRX_CHUD() registers is enough.
*/
if (dev->trigger_enabled) {
reinit_completion(&user_data->done);
regmap_write(dev->regmap, SPDIFRX_IER, SPDIFRX_IR_BLOCKEND);
ret = wait_for_completion_interruptible_timeout(&user_data->done,
msecs_to_jiffies(100));
/* Valid stream might not be present. */
if (ret <= 0) {
dev_dbg(dev->dev, "user data for channel %d timeout\n",
channel);
regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_BLOCKEND);
ret = ret ? : -ETIMEDOUT;
goto pm_runtime_put;
} else {
ret = 0;
}
} else {
/* Update software cache with last available data. */
mchp_spdifrx_channel_user_data_read(dev, channel);
}
spin_lock_irqsave(&user_data->lock, flags);
memcpy(uvalue->value.iec958.subcode, user_data->data,
sizeof(user_data->data));
spin_unlock_irqrestore(&user_data->lock, flags);
return 0;
pm_runtime_put:
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
unlock:
mutex_unlock(&dev->mlock);
return ret;
}
static int mchp_spdifrx_subcode_ch1_get(struct snd_kcontrol *kcontrol,
@ -625,12 +708,34 @@ static int mchp_spdifrx_ulock_get(struct snd_kcontrol *kcontrol,
struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
u32 val;
int ret;
bool ulock_old = ctrl->ulock;
regmap_read(dev->regmap, SPDIFRX_RSR, &val);
ctrl->ulock = !(val & SPDIFRX_RSR_ULOCK);
mutex_lock(&dev->mlock);
ret = pm_runtime_resume_and_get(dev->dev);
if (ret < 0)
goto unlock;
/*
* The RSR.ULOCK has wrong value if both pclk and gclk are enabled
* and the receiver is disabled. Thus we take into account the
* dev->trigger_enabled here to return a real status.
*/
if (dev->trigger_enabled) {
regmap_read(dev->regmap, SPDIFRX_RSR, &val);
ctrl->ulock = !(val & SPDIFRX_RSR_ULOCK);
} else {
ctrl->ulock = 0;
}
uvalue->value.integer.value[0] = ctrl->ulock;
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
unlock:
mutex_unlock(&dev->mlock);
return ulock_old != ctrl->ulock;
}
@ -641,10 +746,32 @@ static int mchp_spdifrx_badf_get(struct snd_kcontrol *kcontrol,
struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
u32 val;
int ret;
bool badf_old = ctrl->badf;
regmap_read(dev->regmap, SPDIFRX_RSR, &val);
ctrl->badf = !!(val & SPDIFRX_RSR_BADF);
mutex_lock(&dev->mlock);
ret = pm_runtime_resume_and_get(dev->dev);
if (ret < 0)
goto unlock;
/*
* The RSR.ULOCK has wrong value if both pclk and gclk are enabled
* and the receiver is disabled. Thus we take into account the
* dev->trigger_enabled here to return a real status.
*/
if (dev->trigger_enabled) {
regmap_read(dev->regmap, SPDIFRX_RSR, &val);
ctrl->badf = !!(val & SPDIFRX_RSR_BADF);
} else {
ctrl->badf = 0;
}
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
unlock:
mutex_unlock(&dev->mlock);
uvalue->value.integer.value[0] = ctrl->badf;
return badf_old != ctrl->badf;
@ -656,11 +783,49 @@ static int mchp_spdifrx_signal_get(struct snd_kcontrol *kcontrol,
struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
u32 val;
u32 val = ~0U, loops = 10;
int ret;
bool signal_old = ctrl->signal;
regmap_read(dev->regmap, SPDIFRX_RSR, &val);
ctrl->signal = !(val & SPDIFRX_RSR_NOSIGNAL);
mutex_lock(&dev->mlock);
ret = pm_runtime_resume_and_get(dev->dev);
if (ret < 0)
goto unlock;
/*
* To get the signal we need to have receiver enabled. This
* could be enabled also from trigger() function thus we need to
* take care of not disabling the receiver when it runs.
*/
if (!dev->trigger_enabled) {
regmap_update_bits(dev->regmap, SPDIFRX_MR, SPDIFRX_MR_RXEN_MASK,
SPDIFRX_MR_RXEN_ENABLE);
/* Wait for RSR.ULOCK bit. */
while (--loops) {
regmap_read(dev->regmap, SPDIFRX_RSR, &val);
if (!(val & SPDIFRX_RSR_ULOCK))
break;
usleep_range(100, 150);
}
regmap_update_bits(dev->regmap, SPDIFRX_MR, SPDIFRX_MR_RXEN_MASK,
SPDIFRX_MR_RXEN_DISABLE);
} else {
regmap_read(dev->regmap, SPDIFRX_RSR, &val);
}
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
unlock:
mutex_unlock(&dev->mlock);
if (!(val & SPDIFRX_RSR_ULOCK))
ctrl->signal = !(val & SPDIFRX_RSR_NOSIGNAL);
else
ctrl->signal = 0;
uvalue->value.integer.value[0] = ctrl->signal;
return signal_old != ctrl->signal;
@ -682,22 +847,44 @@ static int mchp_spdifrx_rate_get(struct snd_kcontrol *kcontrol,
{
struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
unsigned long rate;
u32 val;
int rate;
int ret;
regmap_read(dev->regmap, SPDIFRX_RSR, &val);
mutex_lock(&dev->mlock);
/* if the receiver is not locked, ISF data is invalid */
if (val & SPDIFRX_RSR_ULOCK || !(val & SPDIFRX_RSR_IFS_MASK)) {
ret = pm_runtime_resume_and_get(dev->dev);
if (ret < 0)
goto unlock;
/*
* The RSR.ULOCK has wrong value if both pclk and gclk are enabled
* and the receiver is disabled. Thus we take into account the
* dev->trigger_enabled here to return a real status.
*/
if (dev->trigger_enabled) {
regmap_read(dev->regmap, SPDIFRX_RSR, &val);
/* If the receiver is not locked, ISF data is invalid. */
if (val & SPDIFRX_RSR_ULOCK || !(val & SPDIFRX_RSR_IFS_MASK)) {
ucontrol->value.integer.value[0] = 0;
goto pm_runtime_put;
}
} else {
/* Reveicer is not locked, IFS data is invalid. */
ucontrol->value.integer.value[0] = 0;
return 0;
goto pm_runtime_put;
}
rate = clk_get_rate(dev->gclk);
ucontrol->value.integer.value[0] = rate / (32 * SPDIFRX_RSR_IFS(val));
return 0;
pm_runtime_put:
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
unlock:
mutex_unlock(&dev->mlock);
return ret;
}
static struct snd_kcontrol_new mchp_spdifrx_ctrls[] = {
@ -787,14 +974,6 @@ static int mchp_spdifrx_dai_probe(struct snd_soc_dai *dai)
struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
int ch;
int err;
err = clk_prepare_enable(dev->pclk);
if (err) {
dev_err(dev->dev,
"failed to enable the peripheral clock: %d\n", err);
return err;
}
snd_soc_dai_init_dma_data(dai, NULL, &dev->capture);
@ -808,11 +987,9 @@ static int mchp_spdifrx_dai_probe(struct snd_soc_dai *dai)
SPDIFRX_MR_AUTORST_NOACTION |
SPDIFRX_MR_PACK_DISABLED);
dev->blockend_refcount = 0;
for (ch = 0; ch < SPDIFRX_CHANNELS; ch++) {
init_completion(&ctrl->ch_stat[ch].done);
init_completion(&ctrl->user_data[ch].done);
spin_lock_init(&ctrl->user_data[ch].lock);
}
/* Add controls */
@ -827,9 +1004,7 @@ static int mchp_spdifrx_dai_remove(struct snd_soc_dai *dai)
struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
/* Disable interrupts */
regmap_write(dev->regmap, SPDIFRX_IDR, 0xFF);
clk_disable_unprepare(dev->pclk);
regmap_write(dev->regmap, SPDIFRX_IDR, GENMASK(14, 0));
return 0;
}
@ -861,6 +1036,48 @@ static const struct of_device_id mchp_spdifrx_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, mchp_spdifrx_dt_ids);
static int mchp_spdifrx_runtime_suspend(struct device *dev)
{
struct mchp_spdifrx_dev *spdifrx = dev_get_drvdata(dev);
regcache_cache_only(spdifrx->regmap, true);
clk_disable_unprepare(spdifrx->gclk);
clk_disable_unprepare(spdifrx->pclk);
return 0;
}
static int mchp_spdifrx_runtime_resume(struct device *dev)
{
struct mchp_spdifrx_dev *spdifrx = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(spdifrx->pclk);
if (ret)
return ret;
ret = clk_prepare_enable(spdifrx->gclk);
if (ret)
goto disable_pclk;
regcache_cache_only(spdifrx->regmap, false);
regcache_mark_dirty(spdifrx->regmap);
ret = regcache_sync(spdifrx->regmap);
if (ret) {
regcache_cache_only(spdifrx->regmap, true);
clk_disable_unprepare(spdifrx->gclk);
disable_pclk:
clk_disable_unprepare(spdifrx->pclk);
}
return ret;
}
static const struct dev_pm_ops mchp_spdifrx_pm_ops = {
RUNTIME_PM_OPS(mchp_spdifrx_runtime_suspend, mchp_spdifrx_runtime_resume,
NULL)
};
static int mchp_spdifrx_probe(struct platform_device *pdev)
{
struct mchp_spdifrx_dev *dev;
@ -913,19 +1130,36 @@ static int mchp_spdifrx_probe(struct platform_device *pdev)
"failed to get the PMC generated clock: %d\n", err);
return err;
}
spin_lock_init(&dev->blockend_lock);
/*
* Signal control need a valid rate on gclk. hw_params() configures
* it propertly but requesting signal before any hw_params() has been
* called lead to invalid value returned for signal. Thus, configure
* gclk at a valid rate, here, in initialization, to simplify the
* control path.
*/
clk_set_min_rate(dev->gclk, 48000 * SPDIFRX_GCLK_RATIO_MIN + 1);
mutex_init(&dev->mlock);
dev->dev = &pdev->dev;
dev->regmap = regmap;
platform_set_drvdata(pdev, dev);
pm_runtime_enable(dev->dev);
if (!pm_runtime_enabled(dev->dev)) {
err = mchp_spdifrx_runtime_resume(dev->dev);
if (err)
goto pm_runtime_disable;
}
dev->capture.addr = (dma_addr_t)mem->start + SPDIFRX_RHR;
dev->capture.maxburst = 1;
err = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
if (err) {
dev_err(&pdev->dev, "failed to register PCM: %d\n", err);
return err;
goto pm_runtime_suspend;
}
err = devm_snd_soc_register_component(&pdev->dev,
@ -933,20 +1167,40 @@ static int mchp_spdifrx_probe(struct platform_device *pdev)
&mchp_spdifrx_dai, 1);
if (err) {
dev_err(&pdev->dev, "fail to register dai\n");
return err;
goto pm_runtime_suspend;
}
regmap_read(regmap, SPDIFRX_VERSION, &vers);
dev_info(&pdev->dev, "hw version: %#lx\n", vers & SPDIFRX_VERSION_MASK);
return 0;
pm_runtime_suspend:
if (!pm_runtime_status_suspended(dev->dev))
mchp_spdifrx_runtime_suspend(dev->dev);
pm_runtime_disable:
pm_runtime_disable(dev->dev);
return err;
}
static int mchp_spdifrx_remove(struct platform_device *pdev)
{
struct mchp_spdifrx_dev *dev = platform_get_drvdata(pdev);
pm_runtime_disable(dev->dev);
if (!pm_runtime_status_suspended(dev->dev))
mchp_spdifrx_runtime_suspend(dev->dev);
return 0;
}
static struct platform_driver mchp_spdifrx_driver = {
.probe = mchp_spdifrx_probe,
.remove = mchp_spdifrx_remove,
.driver = {
.name = "mchp_spdifrx",
.of_match_table = of_match_ptr(mchp_spdifrx_dt_ids),
.pm = pm_ptr(&mchp_spdifrx_pm_ops),
},
};

View File

@ -6,6 +6,7 @@
//
// Author: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
@ -71,11 +72,11 @@
/* Valid Bits per Sample */
#define SPDIFTX_MR_VBPS_MASK GENMASK(13, 8)
#define SPDIFTX_MR_VBPS(bps) (((bps) << 8) & SPDIFTX_MR_VBPS_MASK)
#define SPDIFTX_MR_VBPS(bps) FIELD_PREP(SPDIFTX_MR_VBPS_MASK, bps)
/* Chunk Size */
#define SPDIFTX_MR_CHUNK_MASK GENMASK(19, 16)
#define SPDIFTX_MR_CHUNK(size) (((size) << 16) & SPDIFTX_MR_CHUNK_MASK)
#define SPDIFTX_MR_CHUNK(size) FIELD_PREP(SPDIFTX_MR_CHUNK_MASK, size)
/* Validity Bits for Channels 1 and 2 */
#define SPDIFTX_MR_VALID1 BIT(24)
@ -88,8 +89,7 @@
/* Bytes per Sample */
#define SPDIFTX_MR_BPS_MASK GENMASK(29, 28)
#define SPDIFTX_MR_BPS(bytes) \
((((bytes) - 1) << 28) & SPDIFTX_MR_BPS_MASK)
#define SPDIFTX_MR_BPS(bytes) FIELD_PREP(SPDIFTX_MR_BPS_MASK, (bytes - 1))
/*
* ---- Interrupt Enable/Disable/Mask/Status Register (Write/Read-only) ----

View File

@ -323,8 +323,8 @@ static int ep93xx_ac97_dai_probe(struct snd_soc_dai *dai)
info->dma_params_tx.filter_data = &ep93xx_ac97_pcm_out;
info->dma_params_rx.filter_data = &ep93xx_ac97_pcm_in;
dai->playback_dma_data = &info->dma_params_tx;
dai->capture_dma_data = &info->dma_params_rx;
snd_soc_dai_init_dma_data(dai, &info->dma_params_tx,
&info->dma_params_rx);
return 0;
}

View File

@ -202,8 +202,8 @@ static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai)
info->dma_params_rx.filter_data =
&ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_CAPTURE];
dai->playback_dma_data = &info->dma_params_tx;
dai->capture_dma_data = &info->dma_params_rx;
snd_soc_dai_init_dma_data(dai, &info->dma_params_tx,
&info->dma_params_rx);
return 0;
}
@ -359,6 +359,8 @@ static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
return -EINVAL;
if (!freq)
return 0;
return clk_set_rate(info->mclk, freq);
}

View File

@ -1386,17 +1386,11 @@ static int pm860x_codec_probe(struct platform_device *pdev)
return ret;
}
static int pm860x_codec_remove(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver pm860x_codec_driver = {
.driver = {
.name = "88pm860x-codec",
},
.probe = pm860x_codec_probe,
.remove = pm860x_codec_remove,
};
module_platform_driver(pm860x_codec_driver);

View File

@ -54,6 +54,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_ALC5623
imply SND_SOC_ALC5632
imply SND_SOC_AW8738
imply SND_SOC_AW88395
imply SND_SOC_BT_SCO
imply SND_SOC_BD28623
imply SND_SOC_CQ0093VC
@ -68,6 +69,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_CS35L45_I2C
imply SND_SOC_CS35L45_SPI
imply SND_SOC_CS42L42
imply SND_SOC_CS42L42_SDW
imply SND_SOC_CS42L51_I2C
imply SND_SOC_CS42L52
imply SND_SOC_CS42L56
@ -107,6 +109,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_HDAC_HDMI
imply SND_SOC_HDAC_HDA
imply SND_SOC_ICS43432
imply SND_SOC_IDT821034
imply SND_SOC_INNO_RK3036
imply SND_SOC_ISABELLE
imply SND_SOC_JZ4740_CODEC
@ -164,6 +167,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_PCM5102A
imply SND_SOC_PCM512x_I2C
imply SND_SOC_PCM512x_SPI
imply SND_SOC_PEB2466
imply SND_SOC_RK3328
imply SND_SOC_RK817
imply SND_SOC_RT274
@ -195,6 +199,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_RT700_SDW
imply SND_SOC_RT711_SDW
imply SND_SOC_RT711_SDCA_SDW
imply SND_SOC_RT712_SDCA_SDW
imply SND_SOC_RT715_SDW
imply SND_SOC_RT715_SDCA_SDW
imply SND_SOC_RT1308_SDW
@ -206,6 +211,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_SI476X
imply SND_SOC_SIMPLE_AMPLIFIER
imply SND_SOC_SIMPLE_MUX
imply SND_SOC_SMA1303
imply SND_SOC_SPDIF
imply SND_SOC_SRC4XXX_I2C
imply SND_SOC_SSM2305
@ -599,6 +605,23 @@ config SND_SOC_AW8738
SND_SOC_SIMPLE_AMPLIFIER, but additionally allows setting the
operation mode using the Awinic-specific one-wire pulse control.
config SND_SOC_AW88395_LIB
tristate
config SND_SOC_AW88395
tristate "Soc Audio for awinic aw88395"
depends on I2C
select CRC8
select CRC32
select REGMAP_I2C
select GPIOLIB
select SND_SOC_AW88395_LIB
help
this option enables support for aw88395 Smart PA.
The Awinic AW88395 is an I2S/TDM input, high efficiency
digital Smart K audio amplifier with an integrated 10V
smart boost convert.
config SND_SOC_BD28623
tristate "ROHM BD28623 CODEC"
help
@ -665,9 +688,6 @@ config SND_SOC_CS35L41_I2C
select SND_SOC_CS35L41
select REGMAP_I2C
config SND_SOC_CS35L45_TABLES
tristate
config SND_SOC_CS35L45
tristate
@ -676,7 +696,6 @@ config SND_SOC_CS35L45_SPI
depends on SPI_MASTER
select REGMAP
select REGMAP_SPI
select SND_SOC_CS35L45_TABLES
select SND_SOC_CS35L45
help
Enable support for Cirrus Logic CS35L45 smart speaker amplifier
@ -687,7 +706,6 @@ config SND_SOC_CS35L45_I2C
depends on I2C
select REGMAP
select REGMAP_I2C
select SND_SOC_CS35L45_TABLES
select SND_SOC_CS35L45
help
Enable support for Cirrus Logic CS35L45 smart speaker amplifier
@ -703,6 +721,13 @@ config SND_SOC_CS42L42
select REGMAP_I2C
select SND_SOC_CS42L42_CORE
config SND_SOC_CS42L42_SDW
tristate "Cirrus Logic CS42L42 CODEC on Soundwire"
depends on SOUNDWIRE
select SND_SOC_CS42L42_CORE
help
Enable support for Cirrus Logic CS42L42 codec with Soundwire control
config SND_SOC_CS42L51
tristate
@ -972,6 +997,16 @@ config SND_SOC_HDA
config SND_SOC_ICS43432
tristate "ICS43423 and compatible i2s microphones"
config SND_SOC_IDT821034
tristate "Renesas IDT821034 quad PCM codec"
depends on SPI
help
Enable support for the Renesas IDT821034 quad PCM with
programmable gain codec.
To compile this driver as a module, choose M here: the module
will be called snd-soc-idt821034.
config SND_SOC_INNO_RK3036
tristate "Inno codec driver for RK3036 SoC"
select REGMAP_MMIO
@ -1205,6 +1240,17 @@ config SND_SOC_PCM512x_SPI
select SND_SOC_PCM512x
select REGMAP_SPI
config SND_SOC_PEB2466
tristate "Infineon PEB2466 quad PCM codec"
depends on SPI
select REGMAP_SPI
help
Enable support for the Infineon PEB2466 quad PCM codec,
also named SICOFI 4-uC.
To compile this driver as a module, choose M here: the module
will be called snd-soc-peb2466.
config SND_SOC_RK3328
tristate "Rockchip RK3328 audio CODEC"
select REGMAP_MMIO
@ -1425,6 +1471,12 @@ config SND_SOC_RT711_SDCA_SDW
select REGMAP_SOUNDWIRE
select REGMAP_SOUNDWIRE_MBQ
config SND_SOC_RT712_SDCA_SDW
tristate "Realtek RT712 SDCA Codec - SDW"
depends on SOUNDWIRE
select REGMAP_SOUNDWIRE
select REGMAP_SOUNDWIRE_MBQ
config SND_SOC_RT715
tristate
@ -1492,6 +1544,12 @@ config SND_SOC_SIMPLE_MUX
tristate "Simple Audio Mux"
depends on GPIOLIB
config SND_SOC_SMA1303
tristate "Iron Device SMA1303 Audio Amplifier"
depends on I2C
help
Enable support for Iron Device SMA1303 Boosted Class-D amplifier
config SND_SOC_SPDIF
tristate "S/PDIF CODEC"
@ -2111,7 +2169,6 @@ config SND_SOC_MT6660
config SND_SOC_NAU8315
tristate "Nuvoton Technology Corporation NAU8315 CODEC"
depends on GPIOLIB
config SND_SOC_NAU8540
tristate "Nuvoton Technology Corporation NAU85L40 CODEC"

View File

@ -46,6 +46,9 @@ snd-soc-ak5386-objs := ak5386.o
snd-soc-ak5558-objs := ak5558.o
snd-soc-arizona-objs := arizona.o arizona-jack.o
snd-soc-aw8738-objs := aw8738.o
snd-soc-aw88395-lib-objs := aw88395/aw88395_lib.o
snd-soc-aw88395-objs := aw88395/aw88395.o \
aw88395/aw88395_device.o
snd-soc-bd28623-objs := bd28623.o
snd-soc-bt-sco-objs := bt-sco.o
snd-soc-cpcap-objs := cpcap.o
@ -60,12 +63,12 @@ snd-soc-cs35l41-lib-objs := cs35l41-lib.o
snd-soc-cs35l41-objs := cs35l41.o
snd-soc-cs35l41-spi-objs := cs35l41-spi.o
snd-soc-cs35l41-i2c-objs := cs35l41-i2c.o
snd-soc-cs35l45-tables-objs := cs35l45-tables.o
snd-soc-cs35l45-objs := cs35l45.o
snd-soc-cs35l45-objs := cs35l45.o cs35l45-tables.o
snd-soc-cs35l45-spi-objs := cs35l45-spi.o
snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o
snd-soc-cs42l42-objs := cs42l42.o
snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o
snd-soc-cs42l42-sdw-objs := cs42l42-sdw.o
snd-soc-cs42l51-objs := cs42l51.o
snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
snd-soc-cs42l52-objs := cs42l52.o
@ -111,6 +114,7 @@ snd-soc-hdac-hdmi-objs := hdac_hdmi.o
snd-soc-hdac-hda-objs := hdac_hda.o
snd-soc-hda-codec-objs := hda.o hda-dai.o
snd-soc-ics43432-objs := ics43432.o
snd-soc-idt821034-objs := idt821034.o
snd-soc-inno-rk3036-objs := inno_rk3036.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
@ -183,6 +187,7 @@ snd-soc-pcm5102a-objs := pcm5102a.o
snd-soc-pcm512x-objs := pcm512x.o
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-peb2466-objs := peb2466.o
snd-soc-rk3328-objs := rk3328_codec.o
snd-soc-rk817-objs := rk817_codec.o
snd-soc-rl6231-objs := rl6231.o
@ -222,6 +227,7 @@ snd-soc-rt5682s-objs := rt5682s.o
snd-soc-rt700-objs := rt700.o rt700-sdw.o
snd-soc-rt711-objs := rt711.o rt711-sdw.o
snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o
snd-soc-rt712-sdca-objs := rt712-sdca.o rt712-sdca-sdw.o
snd-soc-rt715-objs := rt715.o rt715-sdw.o
snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o
snd-soc-rt9120-objs := rt9120.o
@ -233,6 +239,7 @@ snd-soc-sigmadsp-objs := sigmadsp.o
snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o
snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
snd-soc-si476x-objs := si476x.o
snd-soc-sma1303-objs := sma1303.o
snd-soc-spdif-tx-objs := spdif_transmitter.o
snd-soc-spdif-rx-objs := spdif_receiver.o
snd-soc-src4xxx-objs := src4xxx.o
@ -407,6 +414,8 @@ obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
obj-$(CONFIG_SND_SOC_AW8738) += snd-soc-aw8738.o
obj-$(CONFIG_SND_SOC_AW88395_LIB) += snd-soc-aw88395-lib.o
obj-$(CONFIG_SND_SOC_AW88395) +=snd-soc-aw88395.o
obj-$(CONFIG_SND_SOC_BD28623) += snd-soc-bd28623.o
obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
@ -421,12 +430,12 @@ obj-$(CONFIG_SND_SOC_CS35L41) += snd-soc-cs35l41.o
obj-$(CONFIG_SND_SOC_CS35L41_LIB) += snd-soc-cs35l41-lib.o
obj-$(CONFIG_SND_SOC_CS35L41_SPI) += snd-soc-cs35l41-spi.o
obj-$(CONFIG_SND_SOC_CS35L41_I2C) += snd-soc-cs35l41-i2c.o
obj-$(CONFIG_SND_SOC_CS35L45_TABLES) += snd-soc-cs35l45-tables.o
obj-$(CONFIG_SND_SOC_CS35L45) += snd-soc-cs35l45.o
obj-$(CONFIG_SND_SOC_CS35L45_SPI) += snd-soc-cs35l45-spi.o
obj-$(CONFIG_SND_SOC_CS35L45_I2C) += snd-soc-cs35l45-i2c.o
obj-$(CONFIG_SND_SOC_CS42L42_CORE) += snd-soc-cs42l42.o
obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42-i2c.o
obj-$(CONFIG_SND_SOC_CS42L42_SDW) += snd-soc-cs42l42-sdw.o
obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o
obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
@ -472,6 +481,7 @@ obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o
obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-soc-hdac-hda.o
obj-$(CONFIG_SND_SOC_HDA) += snd-soc-hda-codec.o
obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o
obj-$(CONFIG_SND_SOC_IDT821034) += snd-soc-idt821034.o
obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
@ -539,6 +549,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o
obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
obj-$(CONFIG_SND_SOC_PEB2466) += snd-soc-peb2466.o
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
@ -579,6 +590,7 @@ obj-$(CONFIG_SND_SOC_RT5682S) += snd-soc-rt5682s.o
obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o
obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o
obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o
obj-$(CONFIG_SND_SOC_RT712_SDCA_SDW) += snd-soc-rt712-sdca.o
obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o
obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o
obj-$(CONFIG_SND_SOC_RT9120) += snd-soc-rt9120.o
@ -588,6 +600,7 @@ obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o
obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o
obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
obj-$(CONFIG_SND_SOC_SMA1303) += snd-soc-sma1303.o
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
obj-$(CONFIG_SND_SOC_SRC4XXX) += snd-soc-src4xxx.o
obj-$(CONFIG_SND_SOC_SRC4XXX_I2C) += snd-soc-src4xxx-i2c.o

View File

@ -127,18 +127,12 @@ static int ac97_probe(struct platform_device *pdev)
&soc_component_dev_ac97, &ac97_dai, 1);
}
static int ac97_remove(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver ac97_codec_driver = {
.driver = {
.name = "ac97-codec",
},
.probe = ac97_probe,
.remove = ac97_remove,
};
module_platform_driver(ac97_codec_driver);

View File

@ -100,11 +100,6 @@ static int adau7002_probe(struct platform_device *pdev)
&adau7002_dai, 1);
}
static int adau7002_remove(struct platform_device *pdev)
{
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id adau7002_dt_ids[] = {
{ .compatible = "adi,adau7002", },
@ -128,7 +123,6 @@ static struct platform_driver adau7002_driver = {
.acpi_match_table = ACPI_PTR(adau7002_acpi_match),
},
.probe = adau7002_probe,
.remove = adau7002_remove,
};
module_platform_driver(adau7002_driver);

View File

@ -0,0 +1,579 @@
// SPDX-License-Identifier: GPL-2.0-only
//
// aw88395.c -- ALSA SoC AW88395 codec support
//
// Copyright (c) 2022-2023 AWINIC Technology CO., LTD
//
// Author: Bruce zhao <zhaolei@awinic.com>
// Author: Weidong Wang <wangweidong.a@awinic.com>
//
#include <linux/i2c.h>
#include <linux/firmware.h>
#include <linux/of_gpio.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include "aw88395.h"
#include "aw88395_device.h"
#include "aw88395_lib.h"
#include "aw88395_reg.h"
static const struct regmap_config aw88395_remap_config = {
.val_bits = 16,
.reg_bits = 8,
.max_register = AW88395_REG_MAX - 1,
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
.val_format_endian = REGMAP_ENDIAN_BIG,
};
static void aw88395_start_pa(struct aw88395 *aw88395)
{
int ret, i;
for (i = 0; i < AW88395_START_RETRIES; i++) {
ret = aw88395_dev_start(aw88395->aw_pa);
if (ret) {
dev_err(aw88395->aw_pa->dev, "aw88395 device start failed. retry = %d", i);
ret = aw88395_dev_fw_update(aw88395->aw_pa, AW88395_DSP_FW_UPDATE_ON, true);
if (ret < 0) {
dev_err(aw88395->aw_pa->dev, "fw update failed");
continue;
}
} else {
dev_info(aw88395->aw_pa->dev, "start success\n");
break;
}
}
}
static void aw88395_startup_work(struct work_struct *work)
{
struct aw88395 *aw88395 =
container_of(work, struct aw88395, start_work.work);
mutex_lock(&aw88395->lock);
aw88395_start_pa(aw88395);
mutex_unlock(&aw88395->lock);
}
static void aw88395_start(struct aw88395 *aw88395, bool sync_start)
{
int ret;
if (aw88395->aw_pa->fw_status != AW88395_DEV_FW_OK)
return;
if (aw88395->aw_pa->status == AW88395_DEV_PW_ON)
return;
ret = aw88395_dev_fw_update(aw88395->aw_pa, AW88395_DSP_FW_UPDATE_OFF, true);
if (ret < 0) {
dev_err(aw88395->aw_pa->dev, "fw update failed.");
return;
}
if (sync_start == AW88395_SYNC_START)
aw88395_start_pa(aw88395);
else
queue_delayed_work(system_wq,
&aw88395->start_work,
AW88395_START_WORK_DELAY_MS);
}
static struct snd_soc_dai_driver aw88395_dai[] = {
{
.name = "aw88395-aif",
.id = 1,
.playback = {
.stream_name = "Speaker_Playback",
.channels_min = 1,
.channels_max = 2,
.rates = AW88395_RATES,
.formats = AW88395_FORMATS,
},
.capture = {
.stream_name = "Speaker_Capture",
.channels_min = 1,
.channels_max = 2,
.rates = AW88395_RATES,
.formats = AW88395_FORMATS,
},
},
};
static int aw88395_get_fade_in_time(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(component);
struct aw_device *aw_dev = aw88395->aw_pa;
ucontrol->value.integer.value[0] = aw_dev->fade_in_time;
return 0;
}
static int aw88395_set_fade_in_time(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(component);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
struct aw_device *aw_dev = aw88395->aw_pa;
int time;
time = ucontrol->value.integer.value[0];
if (time < mc->min || time > mc->max)
return -EINVAL;
if (time != aw_dev->fade_in_time) {
aw_dev->fade_in_time = time;
return 1;
}
return 0;
}
static int aw88395_get_fade_out_time(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(component);
struct aw_device *aw_dev = aw88395->aw_pa;
ucontrol->value.integer.value[0] = aw_dev->fade_out_time;
return 0;
}
static int aw88395_set_fade_out_time(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(component);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
struct aw_device *aw_dev = aw88395->aw_pa;
int time;
time = ucontrol->value.integer.value[0];
if (time < mc->min || time > mc->max)
return -EINVAL;
if (time != aw_dev->fade_out_time) {
aw_dev->fade_out_time = time;
return 1;
}
return 0;
}
static int aw88395_profile_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(codec);
const char *prof_name;
char *name;
int count;
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
count = aw88395_dev_get_profile_count(aw88395->aw_pa);
if (count <= 0) {
uinfo->value.enumerated.items = 0;
return 0;
}
uinfo->value.enumerated.items = count;
if (uinfo->value.enumerated.item >= count)
uinfo->value.enumerated.item = count - 1;
name = uinfo->value.enumerated.name;
count = uinfo->value.enumerated.item;
prof_name = aw88395_dev_get_prof_name(aw88395->aw_pa, count);
if (!prof_name) {
strscpy(uinfo->value.enumerated.name, "null",
strlen("null") + 1);
return 0;
}
strscpy(name, prof_name, sizeof(uinfo->value.enumerated.name));
return 0;
}
static int aw88395_profile_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(codec);
ucontrol->value.integer.value[0] = aw88395_dev_get_profile_index(aw88395->aw_pa);
return 0;
}
static int aw88395_profile_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(codec);
int ret;
/* pa stop or stopping just set profile */
mutex_lock(&aw88395->lock);
ret = aw88395_dev_set_profile_index(aw88395->aw_pa, ucontrol->value.integer.value[0]);
if (ret < 0) {
dev_dbg(codec->dev, "profile index does not change");
mutex_unlock(&aw88395->lock);
return 0;
}
if (aw88395->aw_pa->status) {
aw88395_dev_stop(aw88395->aw_pa);
aw88395_start(aw88395, AW88395_SYNC_START);
}
mutex_unlock(&aw88395->lock);
return 1;
}
static int aw88395_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(codec);
struct aw_volume_desc *vol_desc = &aw88395->aw_pa->volume_desc;
ucontrol->value.integer.value[0] = vol_desc->ctl_volume;
return 0;
}
static int aw88395_volume_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(codec);
struct aw_volume_desc *vol_desc = &aw88395->aw_pa->volume_desc;
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int value;
value = ucontrol->value.integer.value[0];
if (value < mc->min || value > mc->max)
return -EINVAL;
if (vol_desc->ctl_volume != value) {
vol_desc->ctl_volume = value;
aw88395_dev_set_volume(aw88395->aw_pa, vol_desc->ctl_volume);
return 1;
}
return 0;
}
static int aw88395_get_fade_step(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(codec);
ucontrol->value.integer.value[0] = aw88395->aw_pa->fade_step;
return 0;
}
static int aw88395_set_fade_step(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(codec);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int value;
value = ucontrol->value.integer.value[0];
if (value < mc->min || value > mc->max)
return -EINVAL;
if (aw88395->aw_pa->fade_step != value) {
aw88395->aw_pa->fade_step = value;
return 1;
}
return 0;
}
static int aw88395_re_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(codec);
struct aw_device *aw_dev = aw88395->aw_pa;
ucontrol->value.integer.value[0] = aw_dev->cali_desc.cali_re;
return 0;
}
static int aw88395_re_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(codec);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
struct aw_device *aw_dev = aw88395->aw_pa;
int value;
value = ucontrol->value.integer.value[0];
if (value < mc->min || value > mc->max)
return -EINVAL;
if (aw_dev->cali_desc.cali_re != value) {
aw_dev->cali_desc.cali_re = value;
return 1;
}
return 0;
}
static const struct snd_kcontrol_new aw88395_controls[] = {
SOC_SINGLE_EXT("PCM Playback Volume", AW88395_SYSCTRL2_REG,
6, AW88395_MUTE_VOL, 0, aw88395_volume_get,
aw88395_volume_set),
SOC_SINGLE_EXT("Fade Step", 0, 0, AW88395_MUTE_VOL, 0,
aw88395_get_fade_step, aw88395_set_fade_step),
SOC_SINGLE_EXT("Volume Ramp Up Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN,
aw88395_get_fade_in_time, aw88395_set_fade_in_time),
SOC_SINGLE_EXT("Volume Ramp Down Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN,
aw88395_get_fade_out_time, aw88395_set_fade_out_time),
SOC_SINGLE_EXT("Calib", 0, 0, 100, 0,
aw88395_re_get, aw88395_re_set),
AW88395_PROFILE_EXT("Profile Set", aw88395_profile_info,
aw88395_profile_get, aw88395_profile_set),
};
static int aw88395_playback_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(component);
mutex_lock(&aw88395->lock);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
aw88395_start(aw88395, AW88395_ASYNC_START);
break;
case SND_SOC_DAPM_POST_PMD:
aw88395_dev_stop(aw88395->aw_pa);
break;
default:
break;
}
mutex_unlock(&aw88395->lock);
return 0;
}
static const struct snd_soc_dapm_widget aw88395_dapm_widgets[] = {
/* playback */
SND_SOC_DAPM_AIF_IN_E("AIF_RX", "Speaker_Playback", 0, 0, 0, 0,
aw88395_playback_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_OUTPUT("DAC Output"),
/* capture */
SND_SOC_DAPM_AIF_OUT("AIF_TX", "Speaker_Capture", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_INPUT("ADC Input"),
};
static const struct snd_soc_dapm_route aw88395_audio_map[] = {
{"DAC Output", NULL, "AIF_RX"},
{"AIF_TX", NULL, "ADC Input"},
};
static int aw88395_codec_probe(struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(component);
int ret;
INIT_DELAYED_WORK(&aw88395->start_work, aw88395_startup_work);
/* add widgets */
ret = snd_soc_dapm_new_controls(dapm, aw88395_dapm_widgets,
ARRAY_SIZE(aw88395_dapm_widgets));
if (ret < 0)
return ret;
/* add route */
ret = snd_soc_dapm_add_routes(dapm, aw88395_audio_map,
ARRAY_SIZE(aw88395_audio_map));
if (ret < 0)
return ret;
ret = snd_soc_add_component_controls(component, aw88395_controls,
ARRAY_SIZE(aw88395_controls));
return ret;
}
static void aw88395_codec_remove(struct snd_soc_component *aw_codec)
{
struct aw88395 *aw88395 = snd_soc_component_get_drvdata(aw_codec);
cancel_delayed_work_sync(&aw88395->start_work);
}
static const struct snd_soc_component_driver soc_codec_dev_aw88395 = {
.probe = aw88395_codec_probe,
.remove = aw88395_codec_remove,
};
static struct aw88395 *aw88395_malloc_init(struct i2c_client *i2c)
{
struct aw88395 *aw88395 = devm_kzalloc(&i2c->dev,
sizeof(struct aw88395), GFP_KERNEL);
if (!aw88395)
return NULL;
mutex_init(&aw88395->lock);
return aw88395;
}
static void aw88395_hw_reset(struct aw88395 *aw88395)
{
if (aw88395->reset_gpio) {
gpiod_set_value_cansleep(aw88395->reset_gpio, 0);
usleep_range(AW88395_1000_US, AW88395_1000_US + 10);
gpiod_set_value_cansleep(aw88395->reset_gpio, 1);
usleep_range(AW88395_1000_US, AW88395_1000_US + 10);
} else {
dev_err(aw88395->aw_pa->dev, "%s failed", __func__);
}
}
static int aw88395_request_firmware_file(struct aw88395 *aw88395)
{
const struct firmware *cont = NULL;
int ret;
aw88395->aw_pa->fw_status = AW88395_DEV_FW_FAILED;
ret = request_firmware(&cont, AW88395_ACF_FILE, aw88395->aw_pa->dev);
if ((ret < 0) || (!cont)) {
dev_err(aw88395->aw_pa->dev, "load [%s] failed!", AW88395_ACF_FILE);
return ret;
}
dev_info(aw88395->aw_pa->dev, "loaded %s - size: %zu\n",
AW88395_ACF_FILE, cont ? cont->size : 0);
aw88395->aw_cfg = devm_kzalloc(aw88395->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL);
if (!aw88395->aw_cfg) {
release_firmware(cont);
return -ENOMEM;
}
aw88395->aw_cfg->len = (int)cont->size;
memcpy(aw88395->aw_cfg->data, cont->data, cont->size);
release_firmware(cont);
ret = aw88395_dev_load_acf_check(aw88395->aw_pa, aw88395->aw_cfg);
if (ret < 0) {
dev_err(aw88395->aw_pa->dev, "Load [%s] failed ....!", AW88395_ACF_FILE);
return ret;
}
dev_dbg(aw88395->aw_pa->dev, "%s : bin load success\n", __func__);
mutex_lock(&aw88395->lock);
/* aw device init */
ret = aw88395_dev_init(aw88395->aw_pa, aw88395->aw_cfg);
if (ret < 0)
dev_err(aw88395->aw_pa->dev, "dev init failed");
mutex_unlock(&aw88395->lock);
return ret;
}
static int aw88395_i2c_probe(struct i2c_client *i2c)
{
struct aw88395 *aw88395;
int ret;
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
dev_err(&i2c->dev, "check_functionality failed");
return -EIO;
}
aw88395 = aw88395_malloc_init(i2c);
if (!aw88395) {
dev_err(&i2c->dev, "malloc aw88395 failed");
return -ENOMEM;
}
i2c_set_clientdata(i2c, aw88395);
aw88395->reset_gpio = devm_gpiod_get_optional(&i2c->dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(aw88395->reset_gpio))
dev_info(&i2c->dev, "reset gpio not defined\n");
/* hardware reset */
aw88395_hw_reset(aw88395);
aw88395->regmap = devm_regmap_init_i2c(i2c, &aw88395_remap_config);
if (IS_ERR(aw88395->regmap)) {
ret = PTR_ERR(aw88395->regmap);
dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
return ret;
}
/* aw pa init */
ret = aw88395_init(&aw88395->aw_pa, i2c, aw88395->regmap);
if (ret < 0)
return ret;
ret = aw88395_request_firmware_file(aw88395);
if (ret < 0) {
dev_err(&i2c->dev, "%s failed\n", __func__);
return ret;
}
ret = devm_snd_soc_register_component(&i2c->dev,
&soc_codec_dev_aw88395,
aw88395_dai, ARRAY_SIZE(aw88395_dai));
if (ret < 0) {
dev_err(&i2c->dev, "failed to register aw88395: %d", ret);
return ret;
}
return 0;
}
static const struct i2c_device_id aw88395_i2c_id[] = {
{ AW88395_I2C_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, aw88395_i2c_id);
static struct i2c_driver aw88395_i2c_driver = {
.driver = {
.name = AW88395_I2C_NAME,
},
.probe_new = aw88395_i2c_probe,
.id_table = aw88395_i2c_id,
};
module_i2c_driver(aw88395_i2c_driver);
MODULE_DESCRIPTION("ASoC AW88395 Smart PA Driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0-only
//
// aw88395.h -- ALSA SoC AW88395 codec support
//
// Copyright (c) 2022-2023 AWINIC Technology CO., LTD
//
// Author: Bruce zhao <zhaolei@awinic.com>
//
#ifndef __AW88395_H__
#define __AW88395_H__
#define AW88395_CHIP_ID_REG (0x00)
#define AW88395_START_RETRIES (5)
#define AW88395_START_WORK_DELAY_MS (0)
#define AW88395_DSP_16_DATA_MASK (0x0000ffff)
#define AW88395_I2C_NAME "aw88395_smartpa"
#define AW88395_RATES (SNDRV_PCM_RATE_8000_48000 | \
SNDRV_PCM_RATE_96000)
#define AW88395_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
#define FADE_TIME_MAX 100000
#define FADE_TIME_MIN 0
#define AW88395_PROFILE_EXT(xname, profile_info, profile_get, profile_set) \
{ \
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.info = profile_info, \
.get = profile_get, \
.put = profile_set, \
}
enum {
AW88395_SYNC_START = 0,
AW88395_ASYNC_START,
};
enum {
AW88395_STREAM_CLOSE = 0,
AW88395_STREAM_OPEN,
};
struct aw88395 {
struct aw_device *aw_pa;
struct mutex lock;
struct gpio_desc *reset_gpio;
struct delayed_work start_work;
struct regmap *regmap;
struct aw_container *aw_cfg;
};
#endif

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