Commit 86a4d29e authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-v6.1' of...

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

ASoC: Updates for v6.1

This has been a very quiet release for the core but quite a busy one for
drivers with a big crop of new drivers and lots of feature additions and
fixes to existing ones:

 - A new string helper parse_int_array_user().
 - Improvements to the SOF IPC4 code, especially around trace.
 - Support for AMD Rembrant DSPs, AMD Pink Sardine ACP 6.2, Apple Silcon
   systems, Everest ES8326, Intel Sky Lake and Kaby Lake, MediaTek
   MT8186 support, NXP i.MX8ULP DSPs, Qualcomm SC8280XP, SM8250 and SM8450
   and Texas Instruments SRC4392

There is a conflict with the conversion of I2C remove functions to void
in the cs42l42 driver which is fairly straightforward to resolve but
should be highlighted to Linus.
parents 02f2e785 f0c8d746
......@@ -20,6 +20,7 @@ properties:
- fsl,imx8qxp-dsp
- fsl,imx8qm-dsp
- fsl,imx8mp-dsp
- fsl,imx8ulp-dsp
- fsl,imx8qxp-hifi4
- fsl,imx8qm-hifi4
- fsl,imx8mp-hifi4
......
......@@ -20,6 +20,9 @@ properties:
- qcom,apr-v2
- qcom,gpr
power-domains:
maxItems: 1
qcom,apr-domain:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [1, 2, 3, 4, 5, 6, 7]
......@@ -52,6 +55,26 @@ properties:
2 = Audio DSP Domain
3 = Application Processor Domain
qcom,glink-channels:
$ref: /schemas/types.yaml#/definitions/string-array
description: Channel name used for the communication
items:
- const: apr_audio_svc
qcom,intents:
$ref: /schemas/types.yaml#/definitions/uint32-array
description:
List of (size, amount) pairs describing what intents should be
preallocated for this virtual channel. This can be used to tweak the
default intents available for the channel to meet expectations of the
remote.
qcom,smd-channels:
$ref: /schemas/types.yaml#/definitions/string-array
description: Channel name used for the communication
items:
- const: apr_audio_svc
'#address-cells':
const: 1
......@@ -97,6 +120,26 @@ patternProperties:
3 = AMDB Service.
4 = Voice processing manager.
clock-controller:
$ref: /schemas/sound/qcom,q6dsp-lpass-clocks.yaml#
description: Qualcomm DSP LPASS clock controller
unevaluatedProperties: false
dais:
type: object
oneOf:
- $ref: /schemas/sound/qcom,q6apm-dai.yaml#
- $ref: /schemas/sound/qcom,q6dsp-lpass-ports.yaml#
- $ref: /schemas/sound/qcom,q6asm-dais.yaml#
unevaluatedProperties: false
description: Qualcomm DSP audio ports
routing:
type: object
$ref: /schemas/sound/qcom,q6adm-routing.yaml#
unevaluatedProperties: false
description: Qualcomm DSP LPASS audio routing
qcom,protection-domain:
$ref: /schemas/types.yaml#/definitions/string-array
description: protection domain service name and path for apr service
......@@ -107,17 +150,44 @@ patternProperties:
"tms/servreg", "msm/modem/wlan_pd".
"tms/servreg", "msm/slpi/sensor_pd".
'#address-cells':
const: 1
allOf:
- if:
properties:
compatible:
enum:
- qcom,q6afe
then:
properties:
dais:
properties:
compatible:
const: qcom,q6afe-dais
'#size-cells':
const: 0
- if:
properties:
compatible:
enum:
- qcom,q6apm
then:
properties:
dais:
properties:
compatible:
enum:
- qcom,q6apm-dais
- qcom,q6apm-lpass-dais
patternProperties:
"^.*@[0-9a-f]+$":
type: object
description:
Service based devices like clock controllers or digital audio interfaces.
- if:
properties:
compatible:
enum:
- qcom,q6asm
then:
properties:
dais:
properties:
compatible:
const: qcom,q6asm-dais
additionalProperties: false
......@@ -125,6 +195,30 @@ required:
- compatible
- qcom,domain
allOf:
- if:
properties:
compatible:
enum:
- qcom,gpr
then:
properties:
power-domains: false
- if:
required:
- qcom,glink-channels
then:
properties:
qcom,smd-channels: false
- if:
required:
- qcom,smd-channels
then:
properties:
qcom,glink-channels: false
additionalProperties: false
examples:
......
......@@ -78,6 +78,40 @@ properties:
interleaved on a single output channel.
type: boolean
adi,dmon-stuck-enable:
description:
Enables the "data monitor stuck" feature. Once the data monitor is
enabled, it actively monitors the selected input data (from DIN) to the
speaker amplifier. Once a data error is detected, the data monitor
automatically places the device into software shutdown.
type: boolean
adi,dmon-stuck-threshold-bits:
description:
Sets the threshold for the "data monitor stuck" feature, in bits.
enum: [9, 11, 13, 15]
default: 15
adi,dmon-magnitude-enable:
description:
Enables the "data monitor magnitude" feature. Once the data monitor is
enabled, it actively monitors the selected input data (from DIN) to the
speaker amplifier. Once a data error is detected, the data monitor
automatically places the device into software shutdown.
type: boolean
adi,dmon-magnitude-threshold-bits:
description:
Sets the threshold for the "data monitor magnitude" feature, in bits.
enum: [2, 3, 4, 5]
default: 5
adi,dmon-duration-ms:
description:
Sets the duration for the "data monitor" feature, in milliseconds.
enum: [64, 256, 1024, 4096]
default: 64
reset-gpios:
maxItems: 1
......
# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/allwinner,sun50i-h6-dmic.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner H6 DMIC
maintainers:
- Ban Tao <fengzheng923@gmail.com>
properties:
compatible:
const: allwinner,sun50i-h6-dmic
"#sound-dai-cells":
const: 0
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: Bus Clock
- description: Module Clock
clock-names:
items:
- const: bus
- const: mod
dmas:
items:
- description: RX DMA Channel
dma-names:
items:
- const: rx
resets:
maxItems: 1
required:
- "#sound-dai-cells"
- compatible
- reg
- interrupts
- clocks
- clock-names
- dmas
- dma-names
- resets
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/sun50i-h6-ccu.h>
#include <dt-bindings/reset/sun50i-h6-ccu.h>
dmic: dmic@5095000 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun50i-h6-dmic";
reg = <0x05095000 0x400>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_DMIC>, <&ccu CLK_DMIC>;
clock-names = "bus", "mod";
dmas = <&dma 7>;
dma-names = "rx";
resets = <&ccu RST_BUS_DMIC>;
};
...
......@@ -40,6 +40,7 @@ properties:
patternProperties:
"^dai-link-[0-9]+$":
type: object
additionalProperties: false
description: |-
dai-link child nodes:
Container for dai-link level properties and the CODEC sub-nodes.
......@@ -63,6 +64,7 @@ patternProperties:
patternProperties:
"^codec-[0-9]+$":
type: object
additionalProperties: false
description: |-
Codecs:
dai-link representing backend links should have at least one subnode.
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/apple,mca.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Apple MCA I2S transceiver
description: |
MCA is an I2S transceiver peripheral found on M1 and other Apple chips. It is
composed of a number of identical clusters which can operate independently
or in an interlinked fashion. Up to 6 clusters have been seen on an MCA.
maintainers:
- Martin Povišer <povik+lin@cutebit.org>
properties:
compatible:
items:
- enum:
- apple,t6000-mca
- apple,t8103-mca
- const: apple,mca
reg:
items:
- description: Register region of the MCA clusters proper
- description: Register region of the DMA glue and its FIFOs
interrupts:
minItems: 4
maxItems: 6
description:
One interrupt per each cluster
'#address-cells':
const: 1
'#size-cells':
const: 0
dmas:
minItems: 16
maxItems: 24
description:
DMA channels corresponding to the SERDES units in the peripheral. They are
listed in groups of four per cluster, and within the group they are given
as associated to the TXA, RXA, TXB, RXB units.
dma-names:
minItems: 16
items:
- const: tx0a
- const: rx0a
- const: tx0b
- const: rx0b
- const: tx1a
- const: rx1a
- const: tx1b
- const: rx1b
- const: tx2a
- const: rx2a
- const: tx2b
- const: rx2b
- const: tx3a
- const: rx3a
- const: tx3b
- const: rx3b
- const: tx4a
- const: rx4a
- const: tx4b
- const: rx4b
- const: tx5a
- const: rx5a
- const: tx5b
- const: rx5b
description: |
Names for the DMA channels: 'tx'/'rx', then cluster number, then 'a'/'b'
based on the associated SERDES unit.
clocks:
minItems: 4
maxItems: 6
description:
Clusters' input reference clock.
resets:
maxItems: 1
power-domains:
minItems: 5
maxItems: 7
description:
First a general power domain for register access, then the power
domains of individual clusters for their operation.
'#sound-dai-cells':
const: 1
required:
- compatible
- reg
- dmas
- dma-names
- clocks
- power-domains
- '#sound-dai-cells'
additionalProperties: false
examples:
- |
mca: i2s@9b600000 {
compatible = "apple,t6000-mca", "apple,mca";
reg = <0x9b600000 0x10000>,
<0x9b200000 0x20000>;
clocks = <&nco 0>, <&nco 1>, <&nco 2>, <&nco 3>;
power-domains = <&ps_audio_p>, <&ps_mca0>, <&ps_mca1>,
<&ps_mca2>, <&ps_mca3>;
dmas = <&admac 0>, <&admac 1>, <&admac 2>, <&admac 3>,
<&admac 4>, <&admac 5>, <&admac 6>, <&admac 7>,
<&admac 8>, <&admac 9>, <&admac 10>, <&admac 11>,
<&admac 12>, <&admac 13>, <&admac 14>, <&admac 15>;
dma-names = "tx0a", "rx0a", "tx0b", "rx0b",
"tx1a", "rx1a", "tx1b", "rx1b",
"tx2a", "rx2a", "tx2b", "rx2b",
"tx3a", "rx3a", "tx3b", "rx3b";
#sound-dai-cells = <1>;
};
......@@ -19,14 +19,17 @@ properties:
description: "device name prefix"
$ref: /schemas/types.yaml#/definitions/string
convert-rate:
description: CPU to Codec rate convert.
$ref: /schemas/types.yaml#/definitions/uint32
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate"
convert-channels:
description: CPU to Codec rate channels.
$ref: /schemas/types.yaml#/definitions/uint32
$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]+)?":
$ref: /schemas/graph.yaml#/$defs/endpoint-base
unevaluatedProperties: false
properties:
mclk-fs:
description: |
......@@ -65,12 +68,18 @@ patternProperties:
- msb
- lsb
convert-rate:
description: CPU to Codec rate convert.
$ref: /schemas/types.yaml#/definitions/uint32
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate"
convert-channels:
description: CPU to Codec rate channels.
$ref: /schemas/types.yaml#/definitions/uint32
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels"
convert-sample-format:
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format"
dai-tdm-slot-num:
description: Number of slots in use.
$ref: /schemas/types.yaml#/definitions/uint32
dai-tdm-slot-width:
description: Width in bits for each slot.
$ref: /schemas/types.yaml#/definitions/uint32
dai-tdm-slot-width-map:
description: Mapping of sample widths to slot widths. For hardware
that cannot support a fixed slot width or a slot width always
......
......@@ -27,11 +27,12 @@ properties:
description: User specified audio sound widgets.
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
convert-rate:
description: CPU to Codec rate convert.
$ref: /schemas/types.yaml#/definitions/uint32
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate"
convert-channels:
description: CPU to Codec rate channels.
$ref: /schemas/types.yaml#/definitions/uint32
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels"
convert-sample-format:
$ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format"
pa-gpios:
maxItems: 1
hp-det-gpio:
......
......@@ -19,6 +19,7 @@ properties:
compatible:
enum:
- cirrus,cs42l42
- cirrus,cs42l83
reg:
description:
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/dai-params.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Digital Audio Interface (DAI) Stream Parameters
maintainers:
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
select: false
$defs:
dai-channels:
description: Number of audio channels used by DAI
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1
maximum: 32
dai-sample-format:
description: Audio sample format used by DAI
$ref: /schemas/types.yaml#/definitions/string
enum:
- s8
- s16_le
- s24_le
- s24_3le
- s32_le
dai-sample-rate:
description: Audio sample rate used by DAI
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 8000
maximum: 192000
properties: {}
additionalProperties: true
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/everest,es8326.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Everest ES8326 audio CODEC
maintainers:
- David Yang <yangxiaohua@everest-semi.com>
properties:
compatible:
const: everest,es8326
reg:
maxItems: 1
clocks:
items:
- description: clock for master clock (MCLK)
clock-names:
items:
- const: mclk
"#sound-dai-cells":
const: 0
everest,jack-pol:
$ref: /schemas/types.yaml#/definitions/uint8
description: |
just the value of reg 57. Bit(3) decides whether the jack polarity is inverted.
Bit(2) decides whether the button on the headset is inverted.
Bit(1)/(0) decides the mic properity to be OMTP/CTIA or auto.
minimum: 0x00
maximum: 0x0f
default: 0x0f
everest,mic1-src:
$ref: /schemas/types.yaml#/definitions/uint8
description:
the value of reg 2A when headset plugged.
minimum: 0x00
maximum: 0x77
default: 0x22
everest,mic2-src:
$ref: /schemas/types.yaml#/definitions/uint8
description:
the value of reg 2A when headset unplugged.
minimum: 0x00
maximum: 0x77
default: 0x44
everest,jack-detect-inverted:
$ref: /schemas/types.yaml#/definitions/flag
description:
Defined to invert the jack detection.
everest,interrupt-src:
$ref: /schemas/types.yaml#/definitions/uint8
description: |
value of reg 0x58, Defines the interrupt source.
Bit(2) 1 means button press triggers irq, 0 means not.
Bit(3) 1 means PIN9 is the irq source for jack detection. When set to 0,
bias change on PIN9 do not triggers irq.
Bit(4) 1 means PIN27 is the irq source for jack detection.
Bit(5) 1 means PIN9 is the irq source after MIC detect.
Bit(6) 1 means PIN27 is the irq source after MIC detect.
minimum: 0
maximum: 0x3c
default: 0x08
everest,interrupt-clk:
$ref: /schemas/types.yaml#/definitions/uint8
description: |
value of reg 0x59, Defines the interrupt output behavior.
Bit(0-3) 0 means irq pulse equals 512*internal clock
1 means irq pulse equals 1024*internal clock
2 means ...
7 means irq pulse equals 65536*internal clock
8 means irq mutes PA
9 means irq mutes PA and DAC output
Bit(4) 1 means we invert the interrupt output.
Bit(6) 1 means the chip do not detect jack type after button released.
0 means the chip detect jack type again after button released.
minimum: 0
maximum: 0x7f
default: 0x45
required:
- compatible
- reg
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
es8326: codec@19 {
compatible = "everest,es8326";
reg = <0x19>;
clocks = <&clks 10>;
clock-names = "mclk";
#sound-dai-cells = <0>;
everest,mic1-src = [22];
everest,mic2-src = [44];
everest,jack-pol = [0e];
everest,interrupt-src = [08];
everest,interrupt-clk = [45];
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/fsl,sai.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale Synchronous Audio Interface (SAI).
maintainers:
- Shengjiu Wang <shengjiu.wang@nxp.com>
description: |
The SAI is based on I2S module that used communicating with audio codecs,
which provides a synchronous audio interface that supports fullduplex
serial interfaces with frame synchronization such as I2S, AC97, TDM, and
codec/DSP interfaces.
properties:
compatible:
oneOf:
- enum:
- fsl,vf610-sai
- fsl,imx6sx-sai
- fsl,imx6ul-sai
- fsl,imx7ulp-sai
- fsl,imx8mq-sai
- fsl,imx8qm-sai
- fsl,imx8ulp-sai
- items:
- enum:
- fsl,imx8mm-sai
- fsl,imx8mn-sai
- fsl,imx8mp-sai
- const: fsl,imx8mq-sai
reg:
maxItems: 1
interrupts:
items:
- description: receive and transmit interrupt
dmas:
maxItems: 2
dma-names:
maxItems: 2
clocks:
items:
- description: The ipg clock for register access
- description: master clock source 0 (obsoleted)
- description: master clock source 1
- description: master clock source 2
- description: master clock source 3
- description: PLL clock source for 8kHz series
- description: PLL clock source for 11kHz series
minItems: 4
clock-names:
oneOf:
- items:
- const: bus
- const: mclk0
- const: mclk1
- const: mclk2
- const: mclk3
- const: pll8k
- const: pll11k
minItems: 4
- items:
- const: bus
- const: mclk1
- const: mclk2
- const: mclk3
- const: pll8k
- const: pll11k
minItems: 4
lsb-first:
description: |
Configures whether the LSB or the MSB is transmitted
first for the fifo data. If this property is absent,
the MSB is transmitted first as default, or the LSB
is transmitted first.
type: boolean
big-endian:
description: |
required if all the SAI registers are big-endian rather than little-endian.
type: boolean
fsl,sai-synchronous-rx:
description: |
SAI will work in the synchronous mode (sync Tx with Rx) which means
both the transmitter and the receiver will send and receive data by
following receiver's bit clocks and frame sync clocks.
type: boolean
fsl,sai-asynchronous:
description: |
SAI will work in the asynchronous mode, which means both transmitter
and receiver will send and receive data by following their own bit clocks
and frame sync clocks separately.
If both fsl,sai-asynchronous and fsl,sai-synchronous-rx are absent, the
default synchronous mode (sync Rx with Tx) will be used, which means both
transmitter and receiver will send and receive data by following clocks
of transmitter.
type: boolean
fsl,dataline:
$ref: /schemas/types.yaml#/definitions/uint32-matrix
description: |
Configure the dataline. It has 3 value for each configuration
maxItems: 16
items:
items:
- description: format Default(0), I2S(1) or PDM(2)
enum: [0, 1, 2]
- description: dataline mask for 'rx'
- description: dataline mask for 'tx'
fsl,sai-mclk-direction-output:
description: SAI will output the SAI MCLK clock.
type: boolean
fsl,shared-interrupt:
description: Interrupt is shared with other modules.
type: boolean
"#sound-dai-cells":
const: 0
description: optional, some dts node didn't add it.
allOf:
- 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
then:
properties:
fsl,sai-synchronous-rx: false
required:
- compatible
- reg
- interrupts
- dmas
- dma-names
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/vf610-clock.h>
sai2: sai@40031000 {
compatible = "fsl,vf610-sai";
reg = <0x40031000 0x1000>;
interrupts = <86 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai2_1>;
clocks = <&clks VF610_CLK_PLATFORM_BUS>,
<&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>;
big-endian;
lsb-first;
};
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/imx8mm-clock.h>
sai1: sai@30010000 {
compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai";
reg = <0x30010000 0x10000>;
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MM_CLK_SAI1_IPG>,
<&clk IMX8MM_CLK_DUMMY>,
<&clk IMX8MM_CLK_SAI1_ROOT>,
<&clk IMX8MM_CLK_DUMMY>, <&clk IMX8MM_CLK_DUMMY>;
clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
dmas = <&sdma2 0 2 0>, <&sdma2 1 2 0>;
dma-names = "rx", "tx";
fsl,dataline = <1 0xff 0xff 2 0xff 0x11>;
#sound-dai-cells = <0>;
};
Freescale Synchronous Audio Interface (SAI).
The SAI is based on I2S module that used communicating with audio codecs,
which provides a synchronous audio interface that supports fullduplex
serial interfaces with frame synchronization such as I2S, AC97, TDM, and
codec/DSP interfaces.
Required properties:
- compatible : Compatible list, contains "fsl,vf610-sai",
"fsl,imx6sx-sai", "fsl,imx6ul-sai",
"fsl,imx7ulp-sai", "fsl,imx8mq-sai",
"fsl,imx8qm-sai", "fsl,imx8mm-sai",
"fsl,imx8mn-sai", "fsl,imx8mp-sai", or
"fsl,imx8ulp-sai".
- reg : Offset and length of the register set for the device.
- clocks : Must contain an entry for each entry in clock-names.
- clock-names : Must include the "bus" for register access and
"mclk1", "mclk2", "mclk3" for bit clock and frame
clock providing.
"pll8k", "pll11k" are optional, they are the clock
source for root clock, one is for 8kHz series rates
another one is for 11kHz series rates.
- dmas : Generic dma devicetree binding as described in
Documentation/devicetree/bindings/dma/dma.txt.
- dma-names : Two dmas have to be defined, "tx" and "rx".
- pinctrl-names : Must contain a "default" entry.
- pinctrl-NNN : One property must exist for each entry in
pinctrl-names. See ../pinctrl/pinctrl-bindings.txt
for details of the property values.
- lsb-first : Configures whether the LSB or the MSB is transmitted
first for the fifo data. If this property is absent,
the MSB is transmitted first as default, or the LSB
is transmitted first.
- fsl,sai-synchronous-rx: This is a boolean property. If present, indicating
that SAI will work in the synchronous mode (sync Tx
with Rx) which means both the transmitter and the
receiver will send and receive data by following
receiver's bit clocks and frame sync clocks.
- fsl,sai-asynchronous: This is a boolean property. If present, indicating
that SAI will work in the asynchronous mode, which
means both transmitter and receiver will send and
receive data by following their own bit clocks and
frame sync clocks separately.
- fsl,dataline : configure the dataline. it has 3 value for each configuration
first one means the type: I2S(1) or PDM(2)
second one is dataline mask for 'rx'
third one is dataline mask for 'tx'.
for example: fsl,dataline = <1 0xff 0xff 2 0xff 0x11>;
it means I2S type rx mask is 0xff, tx mask is 0xff, PDM type
rx mask is 0xff, tx mask is 0x11 (dataline 1 and 4 enabled).
Optional properties:
- big-endian : Boolean property, required if all the SAI
registers are big-endian rather than little-endian.
Optional properties (for mx6ul):
- fsl,sai-mclk-direction-output: This is a boolean property. If present,
indicates that SAI will output the SAI MCLK clock.
Note:
- If both fsl,sai-asynchronous and fsl,sai-synchronous-rx are absent, the
default synchronous mode (sync Rx with Tx) will be used, which means both
transmitter and receiver will send and receive data by following clocks
of transmitter.
- fsl,sai-asynchronous and fsl,sai-synchronous-rx are exclusive.
Example:
sai2: sai@40031000 {
compatible = "fsl,vf610-sai";
reg = <0x40031000 0x1000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai2_1>;
clocks = <&clks VF610_CLK_PLATFORM_BUS>,
<&clks VF610_CLK_SAI2>,
<&clks 0>, <&clks 0>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
dma-names = "tx", "rx";
dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
<&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
big-endian;
lsb-first;
};
......@@ -61,6 +61,8 @@ patternProperties:
cpu:
description: Holds subnode which indicates cpu dai.
type: object
additionalProperties: false
properties:
sound-dai:
maxItems: 1
......@@ -68,6 +70,8 @@ patternProperties:
codec:
description: Holds subnode which indicates codec dai.
type: object
additionalProperties: false
properties:
sound-dai:
maxItems: 1
......
......@@ -58,6 +58,7 @@ patternProperties:
cpu:
description: Holds subnode which indicates cpu dai.
type: object
additionalProperties: false
properties:
sound-dai:
maxItems: 1
......@@ -65,6 +66,7 @@ patternProperties:
codec:
description: Holds subnode which indicates codec dai.
type: object
additionalProperties: false
properties:
sound-dai:
minItems: 1
......
......@@ -43,6 +43,16 @@ properties:
required:
- sound-dai
mediatek,adsp:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8186 ADSP platform.
mediatek,dai-link:
$ref: /schemas/types.yaml#/definitions/string-array
description:
A list of the desired dai-links in the sound card. Each entry is a
name defined in the machine driver.
additionalProperties: false
required:
......
......@@ -43,6 +43,16 @@ properties:
required:
- sound-dai
mediatek,adsp:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8186 ADSP platform.
mediatek,dai-link:
$ref: /schemas/types.yaml#/definitions/string-array
description:
A list of the desired dai-links in the sound card. Each entry is a
name defined in the machine driver.
additionalProperties: false
required:
......
......@@ -30,6 +30,8 @@ properties:
headset-codec:
type: object
additionalProperties: false
properties:
sound-dai:
$ref: /schemas/types.yaml#/definitions/phandle
......@@ -38,6 +40,8 @@ properties:
speaker-codecs:
type: object
additionalProperties: false
properties:
sound-dai:
minItems: 1
......
......@@ -71,6 +71,9 @@ Optional properties:
- nuvoton,crosstalk-enable: make crosstalk function enable if set.
- nuvoton,adcout-drive-strong: make the drive strength of ADCOUT IO PIN strong if set.
Otherwise, the drive keeps normal strength.
- clocks: list of phandle and clock specifier pairs according to common clock bindings for the
clocks described in clock-names
- clock-names: should include "mclk" for the MCLK master clock
......
......@@ -14,6 +14,8 @@ properties:
enum:
- qcom,sc7280-lpass-rx-macro
- qcom,sm8250-lpass-rx-macro
- qcom,sm8450-lpass-rx-macro
- qcom,sc8280xp-lpass-rx-macro
reg:
maxItems: 1
......
......@@ -14,6 +14,8 @@ properties:
enum:
- qcom,sc7280-lpass-tx-macro
- qcom,sm8250-lpass-tx-macro
- qcom,sm8450-lpass-tx-macro
- qcom,sc8280xp-lpass-tx-macro
reg:
maxItems: 1
......
......@@ -14,6 +14,8 @@ properties:
enum:
- qcom,sc7280-lpass-va-macro
- qcom,sm8250-lpass-va-macro
- qcom,sm8450-lpass-va-macro
- qcom,sc8280xp-lpass-va-macro
reg:
maxItems: 1
......
......@@ -14,6 +14,8 @@ properties:
enum:
- qcom,sc7280-lpass-wsa-macro
- qcom,sm8250-lpass-wsa-macro
- qcom,sm8450-lpass-wsa-macro
- qcom,sc8280xp-lpass-wsa-macro
reg:
maxItems: 1
......
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,q6adm-routing.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Audio Device Manager (Q6ADM) routing
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
description:
Qualcomm Audio Device Manager (Q6ADM) routing node represents routing
specific configuration.
properties:
compatible:
enum:
- qcom,q6adm-routing
"#sound-dai-cells":
const: 0
required:
- compatible
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/soc/qcom,apr.h>
#include <dt-bindings/sound/qcom,q6asm.h>
apr {
compatible = "qcom,apr-v2";
qcom,domain = <APR_DOMAIN_ADSP>;
#address-cells = <1>;
#size-cells = <0>;
service@8 {
compatible = "qcom,q6adm";
reg = <APR_SVC_ADM>;
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
routing {
compatible = "qcom,q6adm-routing";
#sound-dai-cells = <0>;
};
};
};
Qualcomm Audio Device Manager (Q6ADM) binding
Q6ADM is one of the APR audio service on Q6DSP.
Please refer to qcom,apr.txt for details of the coommon apr service bindings
used by the apr service device.
- but must contain the following property:
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6adm-v<MAJOR-NUMBER>.<MINOR-NUMBER>".
Or "qcom,q6adm" where the version number can be queried
from DSP.
example "qcom,q6adm-v2.0"
= ADM routing
"routing" subnode of the ADM node represents adm routing specific configuration
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6adm-routing".
- #sound-dai-cells
Usage: required
Value type: <u32>
Definition: Must be 0
= EXAMPLE
apr-service@8 {
compatible = "qcom,q6adm";
reg = <APR_SVC_ADM>;
q6routing: routing {
compatible = "qcom,q6adm-routing";
#sound-dai-cells = <0>;
};
};
Qualcomm Audio Front End (Q6AFE) binding
AFE is one of the APR audio service on Q6DSP
Please refer to qcom,apr.txt for details of the common apr service bindings
used by all apr services. Must contain the following properties.
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6afe-v<MAJOR-NUMBER>.<MINOR-NUMBER>"
Or "qcom,q6afe" where the version number can be queried
from DSP.
example "qcom,q6afe"
= EXAMPLE
apr-service@4 {
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
};
......@@ -16,16 +16,12 @@ properties:
compatible:
const: qcom,q6apm-dais
reg:
maxItems: 1
iommus:
maxItems: 1
required:
- compatible
- iommus
- reg
additionalProperties: false
......@@ -37,17 +33,14 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
qcom,domain = <GPR_DOMAIN_ID_ADSP>;
service@1 {
compatible = "qcom,q6apm";
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
apm-dai@1 {
compatible = "qcom,q6apm-dais";
iommus = <&apps_smmu 0x1801 0x0>;
service@1 {
compatible = "qcom,q6apm";
reg = <1>;
};
dais {
compatible = "qcom,q6apm-dais";
iommus = <&apps_smmu 0x1801 0x0>;
};
};
};
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,q6asm-dais.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Audio Stream Manager (Q6ASM)
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
description:
Q6ASM is one of the APR audio services on Q6DSP. Each of its subnodes
represent a dai with board specific configuration.
properties:
compatible:
enum:
- qcom,q6asm-dais
iommus:
maxItems: 1
"#sound-dai-cells":
const: 1
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"^dai@[0-9]+$":
type: object
description:
Q6ASM Digital Audio Interface
properties:
reg:
maxItems: 1
direction:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2]
description: |
The direction of the dai stream::
- Q6ASM_DAI_TX_RX (0) for both tx and rx
- Q6ASM_DAI_TX (1) for only tx (Capture/Encode)
- Q6ASM_DAI_RX (2) for only rx (Playback/Decode)
is-compress-dai:
type: boolean
description:
Compress offload dai.
dependencies:
is-compress-dai: ["direction"]
required:
- reg
additionalProperties: false
required:
- compatible
- "#sound-dai-cells"
- "#address-cells"
- "#size-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/soc/qcom,apr.h>
#include <dt-bindings/sound/qcom,q6asm.h>
apr {
compatible = "qcom,apr-v2";
qcom,domain = <APR_DOMAIN_ADSP>;
#address-cells = <1>;
#size-cells = <0>;
service@7 {
compatible = "qcom,q6asm";
reg = <APR_SVC_ASM>;
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
dais {
compatible = "qcom,q6asm-dais";
iommus = <&apps_smmu 0x1821 0x0>;
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <1>;
dai@0 {
reg = <0>;
};
dai@1 {
reg = <1>;
};
dai@2 {
reg = <2>;
is-compress-dai;
direction = <1>;
};
};
};
};
Qualcomm Audio Stream Manager (Q6ASM) binding
Q6ASM is one of the APR audio service on Q6DSP.
Please refer to qcom,apr.txt for details of the common apr service bindings
used by the apr service device.
- but must contain the following property:
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6asm-v<MAJOR-NUMBER>.<MINOR-NUMBER>".
Or "qcom,q6asm" where the version number can be queried
from DSP.
example "qcom,q6asm-v2.0"
= ASM DAIs (Digital Audio Interface)
"dais" subnode of the ASM node represents dai specific configuration
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6asm-dais".
- #sound-dai-cells
Usage: required
Value type: <u32>
Definition: Must be 1
== ASM DAI is subnode of "dais" and represent a dai, it includes board specific
configuration of each dai. Must contain the following properties.
- reg
Usage: required
Value type: <u32>
Definition: Must be dai id
- direction:
Usage: Required for Compress offload dais
Value type: <u32>
Definition: Specifies the direction of the dai stream
Q6ASM_DAI_TX_RX (0) for both tx and rx
Q6ASM_DAI_TX (1) for only tx (Capture/Encode)
Q6ASM_DAI_RX (2) for only rx (Playback/Decode)
- is-compress-dai:
Usage: Required for Compress offload dais
Value type: <boolean>
Definition: present for Compress offload dais
= EXAMPLE
#include <dt-bindings/sound/qcom,q6asm.h>
apr-service@7 {
compatible = "qcom,q6asm";
reg = <APR_SVC_ASM>;
q6asmdai: dais {
compatible = "qcom,q6asm-dais";
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <1>;
dai@0 {
reg = <0>;
direction = <Q6ASM_DAI_RX>;
is-compress-dai;
};
};
};
Qualcomm ADSP Core service binding
Q6CORE is one of the APR audio service on Q6DSP.
Please refer to qcom,apr.txt for details of the common apr service bindings
used by the apr service device.
- but must contain the following property:
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6core-v<MAJOR-NUMBER>.<MINOR-NUMBER>".
Or "qcom,q6core" where the version number can be queried
from DSP.
example "qcom,q6core-v2.0"
= EXAMPLE
apr-service@3 {
compatible = "qcom,q6core";
reg = <APR_SVC_ADSP_CORE>;
};
......@@ -18,9 +18,6 @@ properties:
- qcom,q6afe-clocks
- qcom,q6prm-lpass-clocks
reg:
maxItems: 1
'#clock-cells':
const: 2
description:
......@@ -32,7 +29,6 @@ properties:
required:
- compatible
- reg
- "#clock-cells"
additionalProperties: false
......@@ -42,19 +38,22 @@ examples:
#include <dt-bindings/soc/qcom,apr.h>
#include <dt-bindings/sound/qcom,q6afe.h>
apr {
compatible = "qcom,apr-v2";
qcom,domain = <APR_DOMAIN_ADSP>;
#address-cells = <1>;
#size-cells = <0>;
apr-service@4 {
service@4 {
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
#address-cells = <1>;
#size-cells = <0>;
clock-controller@2 {
compatible = "qcom,q6afe-clocks";
reg = <2>;
#clock-cells = <2>;
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
clock-controller {
compatible = "qcom,q6afe-clocks";
#clock-cells = <2>;
};
};
};
};
- |
#include <dt-bindings/soc/qcom,gpr.h>
......@@ -63,15 +62,14 @@ examples:
qcom,domain = <GPR_DOMAIN_ID_ADSP>;
#address-cells = <1>;
#size-cells = <0>;
service@2 {
reg = <GPR_PRM_MODULE_IID>;
compatible = "qcom,q6prm";
#address-cells = <1>;
#size-cells = <0>;
clock-controller@2 {
compatible = "qcom,q6prm-lpass-clocks";
reg = <2>;
#clock-cells = <2>;
clock-controller {
compatible = "qcom,q6prm-lpass-clocks";
#clock-cells = <2>;
};
};
};
};
......@@ -18,9 +18,6 @@ properties:
- qcom,q6afe-dais
- qcom,q6apm-lpass-dais
reg:
maxItems: 1
'#sound-dai-cells':
const: 1
......@@ -145,7 +142,6 @@ patternProperties:
required:
- compatible
- reg
- "#sound-dai-cells"
- "#address-cells"
- "#size-cells"
......@@ -157,26 +153,29 @@ examples:
#include <dt-bindings/soc/qcom,apr.h>
#include <dt-bindings/sound/qcom,q6afe.h>
apr {
compatible = "qcom,apr-v2";
#address-cells = <1>;
#size-cells = <0>;
apr-service@4 {
qcom,domain = <APR_DOMAIN_ADSP>;
service@4 {
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
#address-cells = <1>;
#size-cells = <0>;
q6afedai@1 {
compatible = "qcom,q6afe-dais";
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <1>;
dai@22 {
reg = <QUATERNARY_MI2S_RX>;
qcom,sd-lines = <0 1 2 3>;
};
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
dais {
compatible = "qcom,q6afe-dais";
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <1>;
dai@22 {
reg = <QUATERNARY_MI2S_RX>;
qcom,sd-lines = <0 1 2 3>;
};
};
};
};
};
- |
#include <dt-bindings/soc/qcom,gpr.h>
gpr {
......@@ -184,22 +183,21 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
qcom,domain = <GPR_DOMAIN_ID_ADSP>;
service@1 {
compatible = "qcom,q6apm";
reg = <GPR_APM_MODULE_IID>;
#address-cells = <1>;
#size-cells = <0>;
q6apmdai@1 {
compatible = "qcom,q6apm-lpass-dais";
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <1>;
dai@22 {
reg = <QUATERNARY_MI2S_RX>;
qcom,sd-lines = <0 1 2 3>;
};
dais {
compatible = "qcom,q6apm-lpass-dais";
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <1>;
dai@22 {
reg = <QUATERNARY_MI2S_RX>;
qcom,sd-lines = <0 1 2 3>;
};
};
};
};
};
......@@ -20,9 +20,11 @@ properties:
- 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,qrb5165-rb5-sndcard
- qcom,sm8450-sndcard
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
......@@ -71,6 +73,8 @@ patternProperties:
cpu:
description: Holds subnode which indicates cpu dai.
type: object
additionalProperties: false
properties:
sound-dai:
maxItems: 1
......@@ -78,6 +82,8 @@ patternProperties:
platform:
description: Holds subnode which indicates platform dai.
type: object
additionalProperties: false
properties:
sound-dai:
maxItems: 1
......@@ -85,6 +91,8 @@ patternProperties:
codec:
description: Holds subnode which indicates codec dai.
type: object
additionalProperties: false
properties:
sound-dai:
minItems: 1
......
......@@ -129,6 +129,8 @@ properties:
patternProperties:
"^dvc-[0-1]$":
type: object
additionalProperties: false
properties:
dmas:
maxItems: 1
......@@ -145,7 +147,7 @@ properties:
patternProperties:
"^mix-[0-1]$":
type: object
# no properties
additionalProperties: false
additionalProperties: false
rcar_sound,ctu:
......@@ -154,7 +156,7 @@ properties:
patternProperties:
"^ctu-[0-7]$":
type: object
# no properties
additionalProperties: false
additionalProperties: false
rcar_sound,src:
......@@ -163,6 +165,8 @@ properties:
patternProperties:
"^src-[0-9]$":
type: object
additionalProperties: false
properties:
interrupts:
maxItems: 1
......@@ -186,6 +190,8 @@ properties:
patternProperties:
"^ssiu-[0-9]+$":
type: object
additionalProperties: false
properties:
dmas:
maxItems: 2
......@@ -206,6 +212,8 @@ properties:
patternProperties:
"^ssi-[0-9]$":
type: object
additionalProperties: false
properties:
interrupts:
maxItems: 1
......@@ -243,6 +251,8 @@ properties:
patternProperties:
"^dai([0-9]+)?$":
type: object
additionalProperties: false
properties:
playback:
$ref: /schemas/types.yaml#/definitions/phandle-array
......
......@@ -23,6 +23,7 @@ properties:
cpu:
type: object
additionalProperties: false
properties:
sound-dai:
minItems: 2
......@@ -34,6 +35,7 @@ properties:
- sound-dai
codec:
additionalProperties: false
type: object
properties:
sound-dai:
......
......@@ -19,6 +19,7 @@ properties:
cpu:
type: object
additionalProperties: false
properties:
sound-dai:
maxItems: 1
......@@ -28,6 +29,7 @@ properties:
codec:
type: object
additionalProperties: false
properties:
sound-dai:
maxItems: 1
......
......@@ -19,6 +19,7 @@ properties:
codec:
type: object
additionalProperties: false
properties:
sound-dai:
description: List of phandles to the CODEC and HDMI IP nodes.
......@@ -30,6 +31,7 @@ properties:
cpu:
type: object
additionalProperties: false
properties:
sound-dai:
description: Phandle to the Samsung I2S controller.
......
......@@ -60,6 +60,7 @@ required:
patternProperties:
"^audio-controller@[0-9a-f]+$":
type: object
additionalProperties: false
description:
Two subnodes corresponding to SAI sub-block instances A et B
can be defined. Subnode can be omitted for unsused sub-block.
......@@ -121,6 +122,10 @@ patternProperties:
description: Configure the SAI device as master clock provider.
const: 0
port:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
required:
- compatible
- "#sound-dai-cells"
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,src4xxx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments SRC4392 Device Tree Bindings
description: |
The SRC4392 is a digital audio codec that can be connected via
I2C or SPI. Currently, only I2C bus is supported.
maintainers:
- Matt Flax <flatmax@flatmax.com>
allOf:
- $ref: name-prefix.yaml#
properties:
compatible:
const: ti,src4392
"#sound-dai-cells":
const: 0
reg:
maxItems: 1
required:
- "#sound-dai-cells"
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@70 {
#sound-dai-cells = <0>;
compatible = "ti,src4392";
reg = <0x70>;
};
};
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/ti,ts3a227e.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TS3A227E
Autonomous Audio Accessory Detection and Configuration Switch
maintainers:
- Dylan Reid <dgreid@chromium.org>
description: |
The TS3A227E detect headsets of 3-ring and 4-ring standards and
switches automatically to route the microphone correctly. It also
handles key press detection in accordance with the Android audio
headset specification v1.0.
properties:
compatible:
enum:
- ti,ts3a227e
reg:
const: 0x3b
interrupts:
maxItems: 1
ti,micbias:
$ref: /schemas/types.yaml#/definitions/uint32
description: Intended MICBIAS voltage (datasheet section 9.6.7).
enum:
- 0 # 2.1 V
- 1 # 2.2 V
- 2 # 2.3 V
- 3 # 2.4 V
- 4 # 2.5 V
- 5 # 2.6 V
- 6 # 2.7 V
- 7 # 2.8 V
default: 1
ti,debounce-release-ms:
description: key release debounce time in ms (datasheet section 9.6.7).
enum:
- 0
- 20
default: 20
ti,debounce-press-ms:
description: key press debounce time in ms (datasheet section 9.6.7).
enum:
- 2
- 40
- 80
- 120
default: 80
ti,debounce-insertion-ms:
description: headset insertion debounce time in ms (datasheet section 9.6.5).
enum:
- 2
- 30
- 60
- 90
- 120
- 150
- 1000
- 2000
default: 90
required:
- compatible
- reg
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
codec: audio-controller@3b {
compatible = "ti,ts3a227e";
reg = <0x3b>;
interrupt-parent = <&gpio1>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
};
};
...
Texas Instruments TS3A227E
Autonomous Audio Accessory Detection and Configuration Switch
The TS3A227E detect headsets of 3-ring and 4-ring standards and
switches automatically to route the microphone correctly. It also
handles key press detection in accordance with the Android audio
headset specification v1.0.
Required properties:
- compatible: Should contain "ti,ts3a227e".
- reg: The i2c address. Should contain <0x3b>.
- interrupts: Interrupt number for /INT pin from the 227e
Optional properies:
- ti,micbias: Intended MICBIAS voltage (datasheet section 9.6.7).
Select 0/1/2/3/4/5/6/7 to specify MICBIAS voltage
2.1V/2.2V/2.3V/2.4V/2.5V/2.6V/2.7V/2.8V
Default value is "1" (2.2V).
Examples:
i2c {
ts3a227e@3b {
compatible = "ti,ts3a227e";
reg = <0x3b>;
interrupt-parent = <&gpio>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
};
};
......@@ -85,8 +85,9 @@ examples:
compatible = "mediatek,mt8173-nor";
reg = <0 0x1100d000 0 0xe0>;
interrupts = <1>;
clocks = <&pericfg CLK_PERI_SPI>, <&topckgen CLK_TOP_SPINFI_IFR_SEL>;
clock-names = "spi", "sf";
clocks = <&pericfg CLK_PERI_SPI>, <&topckgen CLK_TOP_SPINFI_IFR_SEL>,
<&pericfg CLK_PERI_NFI>;
clock-names = "spi", "sf", "axi";
#address-cells = <1>;
#size-cells = <0>;
......
......@@ -820,6 +820,13 @@ L: linux-media@vger.kernel.org
S: Maintained
F: drivers/staging/media/sunxi/cedrus/
ALLWINNER DMIC DRIVERS
M: Ban Tao <fengzheng923@gmail.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.yaml
F: sound/soc/sunxi/sun50i-dmic.c
ALPHA PORT
M: Richard Henderson <richard.henderson@linaro.org>
M: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
......@@ -1899,6 +1906,15 @@ F: include/dt-bindings/pinctrl/apple.h
F: include/linux/apple-mailbox.h
F: include/linux/soc/apple/*
ARM/APPLE MACHINE SOUND DRIVERS
M: Martin Povišer <povik+lin@cutebit.org>
L: asahi@lists.linux.dev
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/apple,*
F: sound/soc/apple/*
F: sound/soc/codecs/cs42l83-i2c.c
ARM/ARTPEC MACHINE SUPPORT
M: Jesper Nilsson <jesper.nilsson@axis.com>
M: Lars Persson <lars.persson@axis.com>
......@@ -16614,6 +16630,9 @@ M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
M: Banajit Goswami <bgoswami@quicinc.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Supported
F: Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml
F: Documentation/devicetree/bindings/sound/qcom,*
F: drivers/soc/qcom/apr.c
F: include/dt-bindings/sound/qcom,wcd9335.h
F: sound/soc/codecs/lpass-rx-macro.*
F: sound/soc/codecs/lpass-tx-macro.*
......
......@@ -297,6 +297,38 @@ int sdw_transfer(struct sdw_bus *bus, struct sdw_msg *msg)
return ret;
}
/**
* sdw_show_ping_status() - Direct report of PING status, to be used by Peripheral drivers
* @bus: SDW bus
* @sync_delay: Delay before reading status
*/
void sdw_show_ping_status(struct sdw_bus *bus, bool sync_delay)
{
u32 status;
if (!bus->ops->read_ping_status)
return;
/*
* wait for peripheral to sync if desired. 10-15ms should be more than
* enough in most cases.
*/
if (sync_delay)
usleep_range(10000, 15000);
mutex_lock(&bus->msg_lock);
status = bus->ops->read_ping_status(bus);
mutex_unlock(&bus->msg_lock);
if (!status)
dev_warn(bus->dev, "%s: no peripherals attached\n", __func__);
else
dev_dbg(bus->dev, "PING status: %#x\n", status);
}
EXPORT_SYMBOL(sdw_show_ping_status);
/**
* sdw_transfer_defer() - Asynchronously transfer message to a SDW Slave device
* @bus: SDW bus
......
......@@ -756,6 +756,14 @@ cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num)
}
EXPORT_SYMBOL(cdns_reset_page_addr);
u32 cdns_read_ping_status(struct sdw_bus *bus)
{
struct sdw_cdns *cdns = bus_to_cdns(bus);
return cdns_readl(cdns, CDNS_MCP_SLAVE_STAT);
}
EXPORT_SYMBOL(cdns_read_ping_status);
/*
* IRQ handling
*/
......
......@@ -177,6 +177,8 @@ enum sdw_command_response
cdns_xfer_msg_defer(struct sdw_bus *bus,
struct sdw_msg *msg, struct sdw_defer *defer);
u32 cdns_read_ping_status(struct sdw_bus *bus);
int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params);
int cdns_set_sdw_stream(struct snd_soc_dai *dai,
......
......@@ -1262,6 +1262,7 @@ static struct sdw_master_ops sdw_intel_ops = {
.set_bus_conf = cdns_bus_conf,
.pre_bank_switch = intel_pre_bank_switch,
.post_bank_switch = intel_post_bank_switch,
.read_ping_status = cdns_read_ping_status,
};
static int intel_init(struct sdw_intel *sdw)
......
......@@ -193,6 +193,24 @@
#define LPASS_CLK_ID_RX_CORE_MCLK 59
#define LPASS_CLK_ID_RX_CORE_NPL_MCLK 60
#define LPASS_CLK_ID_VA_CORE_2X_MCLK 61
/* Clock ID for MCLK for WSA2 core */
#define LPASS_CLK_ID_WSA2_CORE_MCLK 62
/* Clock ID for NPL MCLK for WSA2 core */
#define LPASS_CLK_ID_WSA2_CORE_2X_MCLK 63
/* Clock ID for RX Core TX MCLK */
#define LPASS_CLK_ID_RX_CORE_TX_MCLK 64
/* Clock ID for RX CORE TX 2X MCLK */
#define LPASS_CLK_ID_RX_CORE_TX_2X_MCLK 65
/* Clock ID for WSA core TX MCLK */
#define LPASS_CLK_ID_WSA_CORE_TX_MCLK 66
/* Clock ID for WSA core TX 2X MCLK */
#define LPASS_CLK_ID_WSA_CORE_TX_2X_MCLK 67
/* Clock ID for WSA2 core TX MCLK */
#define LPASS_CLK_ID_WSA2_CORE_TX_MCLK 68
/* Clock ID for WSA2 core TX 2X MCLK */
#define LPASS_CLK_ID_WSA2_CORE_TX_2X_MCLK 69
/* Clock ID for RX CORE MCLK2 2X MCLK */
#define LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK 70
#define LPASS_HW_AVTIMER_VOTE 101
#define LPASS_HW_MACRO_VOTE 102
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* SSM2518 amplifier audio driver
*
* Copyright 2013 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
#ifndef __LINUX_PLATFORM_DATA_SSM2518_H__
#define __LINUX_PLATFORM_DATA_SSM2518_H__
/**
* struct ssm2518_platform_data - Platform data for the ssm2518 driver
* @enable_gpio: GPIO connected to the nSD pin. Set to -1 if the nSD pin is
* hardwired.
*/
struct ssm2518_platform_data {
int enable_gpio;
};
#endif
......@@ -839,6 +839,8 @@ struct sdw_defer {
* @set_bus_conf: Set the bus configuration
* @pre_bank_switch: Callback for pre bank switch
* @post_bank_switch: Callback for post bank switch
* @read_ping_status: Read status from PING frames, reported with two bits per Device.
* Bits 31:24 are reserved.
*/
struct sdw_master_ops {
int (*read_prop)(struct sdw_bus *bus);
......@@ -855,6 +857,7 @@ struct sdw_master_ops {
struct sdw_bus_params *params);
int (*pre_bank_switch)(struct sdw_bus *bus);
int (*post_bank_switch)(struct sdw_bus *bus);
u32 (*read_ping_status)(struct sdw_bus *bus);
};
......@@ -919,6 +922,8 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
struct fwnode_handle *fwnode);
void sdw_bus_master_delete(struct sdw_bus *bus);
void sdw_show_ping_status(struct sdw_bus *bus, bool sync_delay);
/**
* sdw_port_config: Master or Slave Port configuration
*
......
......@@ -21,6 +21,8 @@ enum string_size_units {
void string_get_size(u64 size, u64 blk_size, enum string_size_units units,
char *buf, int len);
int parse_int_array_user(const char __user *from, size_t count, int **array);
#define UNESCAPE_SPACE BIT(0)
#define UNESCAPE_OCTAL BIT(1)
#define UNESCAPE_HEX BIT(2)
......
This diff is collapsed.
......@@ -40,6 +40,7 @@
#define CS42L42_PAGE_30 0x3000
#define CS42L42_CHIP_ID 0x42A42
#define CS42L83_CHIP_ID 0x42A83
/* Page 0x10 Global Registers */
#define CS42L42_DEVID_AB (CS42L42_PAGE_10 + 0x01)
......
......@@ -136,6 +136,8 @@ bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, u8 link_type);
int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8 device_type);
int intel_nhlt_ssp_mclk_mask(struct nhlt_acpi_table *nhlt, int ssp_num);
struct nhlt_specific_cfg *
intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
u32 bus_id, u8 link_type, u8 vbps, u8 bps,
......@@ -169,6 +171,11 @@ static inline int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8
return 0;
}
static inline int intel_nhlt_ssp_mclk_mask(struct nhlt_acpi_table *nhlt, int ssp_num)
{
return 0;
}
static inline struct nhlt_specific_cfg *
intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
u32 bus_id, u8 link_type, u8 vbps, u8 bps,
......
......@@ -39,6 +39,7 @@ struct asoc_simple_dai {
struct asoc_simple_data {
u32 convert_rate;
u32 convert_channels;
const char *convert_sample_format;
};
struct asoc_simple_jack {
......
......@@ -14,7 +14,6 @@
* these tables are not constants, some fields can be used for
* pdata or machine ops
*/
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_haswell_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_broadwell_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cherrytrail_machines[];
......@@ -30,6 +29,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[];
......@@ -38,6 +38,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[];
/*
......
......@@ -31,31 +31,31 @@
#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xreg, .shift = shift_left, \
.rshift = shift_right, .max = xmax, .platform_max = xmax, \
.rshift = shift_right, .max = xmax, \
.invert = xinvert, .autodisable = xautodisable})
#define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, xinvert, xautodisable) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xreg, .shift = shift_left, \
.rshift = shift_right, .min = xmin, .max = xmax, .platform_max = xmax, \
.rshift = shift_right, .min = xmin, .max = xmax, \
.sign_bit = xsign_bit, .invert = xinvert, .autodisable = xautodisable})
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \
SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable)
#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
{.reg = xreg, .max = xmax, .invert = xinvert})
#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
.max = xmax, .platform_max = xmax, .invert = xinvert})
.max = xmax, .invert = xinvert})
#define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
.max = xmax, .min = xmin, .platform_max = xmax, .sign_bit = xsign_bit, \
.max = xmax, .min = xmin, .sign_bit = xsign_bit, \
.invert = xinvert})
#define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
.min = xmin, .max = xmax, .platform_max = xmax, .invert = xinvert})
.min = xmin, .max = xmax, .invert = xinvert})
#define SOC_SINGLE(xname, reg, shift, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
......@@ -68,7 +68,7 @@
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xreg, .shift = xshift, \
.rshift = xshift, .min = xmin, .max = xmax, \
.platform_max = xmax, .invert = xinvert} }
.invert = xinvert} }
#define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
......@@ -99,7 +99,7 @@
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xreg, .shift = xshift, \
.rshift = xshift, .min = xmin, .max = xmax, \
.platform_max = xmax, .invert = xinvert} }
.invert = xinvert} }
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
......@@ -199,7 +199,7 @@
.put = snd_soc_put_volsw, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xreg, \
.min = xmin, .max = xmax, .platform_max = xmax, \
.min = xmin, .max = xmax, \
.sign_bit = 7,} }
#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
......@@ -273,7 +273,7 @@
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xreg, .shift = xshift, \
.rshift = xshift, .min = xmin, .max = xmax, \
.platform_max = xmax, .invert = xinvert} }
.invert = xinvert} }
#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\
xhandler_get, xhandler_put, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
......@@ -1062,7 +1062,8 @@ struct snd_soc_pcm_runtime {
unsigned int params_select; /* currently selected param for dai link */
/* Dynamic PCM BE runtime data */
struct snd_soc_dpcm_runtime dpcm[2];
struct snd_soc_dpcm_runtime dpcm[SNDRV_PCM_STREAM_LAST + 1];
struct snd_soc_dapm_widget *c2c_widget[SNDRV_PCM_STREAM_LAST + 1];
long pmdown_time;
......@@ -1078,11 +1079,6 @@ struct snd_soc_pcm_runtime {
* asoc_rtd_to_codec()
*/
struct snd_soc_dai **dais;
unsigned int num_codecs;
unsigned int num_cpus;
struct snd_soc_dapm_widget *playback_widget;
struct snd_soc_dapm_widget *capture_widget;
struct delayed_work delayed_work;
void (*close_delayed_work_func)(struct snd_soc_pcm_runtime *rtd);
......@@ -1108,7 +1104,7 @@ struct snd_soc_pcm_runtime {
};
/* see soc_new_pcm_runtime() */
#define asoc_rtd_to_cpu(rtd, n) (rtd)->dais[n]
#define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->num_cpus]
#define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus]
#define asoc_substream_to_rtd(substream) \
(struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream)
......@@ -1118,15 +1114,15 @@ struct snd_soc_pcm_runtime {
(i)++)
#define for_each_rtd_cpu_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < rtd->num_cpus) && ((dai) = asoc_rtd_to_cpu(rtd, i)); \
((i) < rtd->dai_link->num_cpus) && ((dai) = asoc_rtd_to_cpu(rtd, i)); \
(i)++)
#define for_each_rtd_codec_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < rtd->num_codecs) && ((dai) = asoc_rtd_to_codec(rtd, i)); \
((i) < rtd->dai_link->num_codecs) && ((dai) = asoc_rtd_to_codec(rtd, i)); \
(i)++)
#define for_each_rtd_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \
((i) < (rtd)->dai_link->num_cpus + (rtd)->dai_link->num_codecs) && \
((dai) = (rtd)->dais[i]); \
(i)++)
......
......@@ -89,6 +89,7 @@ struct snd_sof_pdata {
/* machine */
struct platform_device *pdev_mach;
const struct snd_soc_acpi_mach *machine;
const struct snd_sof_of_mach *of_machine;
void *hw_pdata;
......@@ -102,6 +103,7 @@ struct snd_sof_pdata {
struct sof_dev_desc {
/* list of machines using this configuration */
struct snd_soc_acpi_mach *machines;
struct snd_sof_of_mach *of_machines;
/* alternate list of machines using this configuration */
struct snd_soc_acpi_mach *alt_machines;
......
......@@ -117,11 +117,11 @@ struct sof_ipc_ctrl_data {
/* control data - add new types if needed */
union {
/* channel values can be used by volume type controls */
struct sof_ipc_ctrl_value_chan chanv[0];
DECLARE_FLEX_ARRAY(struct sof_ipc_ctrl_value_chan, chanv);
/* component values used by routing controls like mux, mixer */
struct sof_ipc_ctrl_value_comp compv[0];
DECLARE_FLEX_ARRAY(struct sof_ipc_ctrl_value_comp, compv);
/* data can be used by binary controls */
struct sof_abi_hdr data[0];
DECLARE_FLEX_ARRAY(struct sof_abi_hdr, data);
};
} __packed;
......
......@@ -84,6 +84,7 @@ enum sof_ipc_dai_type {
SOF_DAI_AMD_BT, /**< AMD ACP BT*/
SOF_DAI_AMD_SP, /**< AMD ACP SP */
SOF_DAI_AMD_DMIC, /**< AMD ACP DMIC */
SOF_DAI_AMD_HS, /**< Amd HS */
SOF_DAI_MEDIATEK_AFE, /**< Mediatek AFE */
};
......@@ -112,6 +113,7 @@ struct sof_ipc_dai_config {
struct sof_ipc_dai_acp_params acpbt;
struct sof_ipc_dai_acp_params acpsp;
struct sof_ipc_dai_acpdmic_params acpdmic;
struct sof_ipc_dai_acp_params acphs;
struct sof_ipc_dai_mtk_afe_params afe;
};
} __packed;
......
......@@ -427,6 +427,11 @@ struct sof_ipc4_dx_state_info {
#define SOF_IPC4_NOTIFICATION_TYPE_GET(x) (((x) & SOF_IPC4_NOTIFICATION_TYPE_MASK) >> \
SOF_IPC4_NOTIFICATION_TYPE_SHIFT)
#define SOF_IPC4_LOG_CORE_SHIFT 12
#define SOF_IPC4_LOG_CORE_MASK GENMASK(15, 12)
#define SOF_IPC4_LOG_CORE_GET(x) (((x) & SOF_IPC4_LOG_CORE_MASK) >> \
SOF_IPC4_LOG_CORE_SHIFT)
/* Value of notification type field - must fit into 8 bits */
enum sof_ipc4_notification_type {
/* Phrase detected (notification from WoV module) */
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright(c) 2022 Intel Corporation. All rights reserved.
*
* Author: Noah Klayman <noah.klayman@intel.com>
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM sof
#if !defined(_TRACE_SOF_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_SOF_H
#include <linux/tracepoint.h>
#include <linux/types.h>
#include <sound/sof/stream.h>
#include "../../../sound/soc/sof/sof-audio.h"
DECLARE_EVENT_CLASS(sof_widget_template,
TP_PROTO(struct snd_sof_widget *swidget),
TP_ARGS(swidget),
TP_STRUCT__entry(
__string(name, swidget->widget->name)
__field(int, use_count)
),
TP_fast_assign(
__assign_str(name, swidget->widget->name);
__entry->use_count = swidget->use_count;
),
TP_printk("name=%s use_count=%d", __get_str(name), __entry->use_count)
);
DEFINE_EVENT(sof_widget_template, sof_widget_setup,
TP_PROTO(struct snd_sof_widget *swidget),
TP_ARGS(swidget)
);
DEFINE_EVENT(sof_widget_template, sof_widget_free,
TP_PROTO(struct snd_sof_widget *swidget),
TP_ARGS(swidget)
);
TRACE_EVENT(sof_ipc3_period_elapsed_position,
TP_PROTO(struct snd_sof_dev *sdev, struct sof_ipc_stream_posn *posn),
TP_ARGS(sdev, posn),
TP_STRUCT__entry(
__string(device_name, dev_name(sdev->dev))
__field(u64, host_posn)
__field(u64, dai_posn)
__field(u64, wallclock)
),
TP_fast_assign(
__assign_str(device_name, dev_name(sdev->dev));
__entry->host_posn = posn->host_posn;
__entry->dai_posn = posn->dai_posn;
__entry->wallclock = posn->wallclock;
),
TP_printk("device_name=%s host_posn=%#llx dai_posn=%#llx wallclock=%#llx",
__get_str(device_name), __entry->host_posn, __entry->dai_posn,
__entry->wallclock)
);
TRACE_EVENT(sof_pcm_pointer_position,
TP_PROTO(struct snd_sof_dev *sdev,
struct snd_sof_pcm *spcm,
struct snd_pcm_substream *substream,
snd_pcm_uframes_t dma_posn,
snd_pcm_uframes_t dai_posn
),
TP_ARGS(sdev, spcm, substream, dma_posn, dai_posn),
TP_STRUCT__entry(
__string(device_name, dev_name(sdev->dev))
__field(u32, pcm_id)
__field(int, stream)
__field(unsigned long, dma_posn)
__field(unsigned long, dai_posn)
),
TP_fast_assign(
__assign_str(device_name, dev_name(sdev->dev));
__entry->pcm_id = le32_to_cpu(spcm->pcm.pcm_id);
__entry->stream = substream->stream;
__entry->dma_posn = dma_posn;
__entry->dai_posn = dai_posn;
),
TP_printk("device_name=%s pcm_id=%d stream=%d dma_posn=%lu dai_posn=%lu",
__get_str(device_name), __entry->pcm_id, __entry->stream,
__entry->dma_posn, __entry->dai_posn)
);
TRACE_EVENT(sof_stream_position_ipc_rx,
TP_PROTO(struct device *dev),
TP_ARGS(dev),
TP_STRUCT__entry(
__string(device_name, dev_name(dev))
),
TP_fast_assign(
__assign_str(device_name, dev_name(dev));
),
TP_printk("device_name=%s", __get_str(device_name))
);
TRACE_EVENT(sof_ipc4_fw_config,
TP_PROTO(struct snd_sof_dev *sdev, char *key, u32 value),
TP_ARGS(sdev, key, value),
TP_STRUCT__entry(
__string(device_name, dev_name(sdev->dev))
__string(key, key)
__field(u32, value)
),
TP_fast_assign(
__assign_str(device_name, dev_name(sdev->dev));
__assign_str(key, key);
__entry->value = value;
),
TP_printk("device_name=%s key=%s value=%d",
__get_str(device_name), __get_str(key), __entry->value)
);
#endif /* _TRACE_SOF_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright(c) 2022 Intel Corporation. All rights reserved.
*
* Author: Noah Klayman <noah.klayman@intel.com>
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM sof_intel
#if !defined(_TRACE_SOF_INTEL_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_SOF_INTEL_H
#include <linux/tracepoint.h>
#include <sound/hdaudio.h>
#include "../../../sound/soc/sof/sof-audio.h"
TRACE_EVENT(sof_intel_hda_irq,
TP_PROTO(struct snd_sof_dev *sdev, char *source),
TP_ARGS(sdev, source),
TP_STRUCT__entry(
__string(device_name, dev_name(sdev->dev))
__string(source, source)
),
TP_fast_assign(
__assign_str(device_name, dev_name(sdev->dev));
__assign_str(source, source);
),
TP_printk("device_name=%s source=%s",
__get_str(device_name), __get_str(source))
);
DECLARE_EVENT_CLASS(sof_intel_ipc_firmware_template,
TP_ARGS(struct snd_sof_dev *sdev, u32 msg, u32 msg_ext),
TP_PROTO(sdev, msg, msg_ext),
TP_STRUCT__entry(
__string(device_name, dev_name(sdev->dev))
__field(u32, msg)
__field(u32, msg_ext)
),
TP_fast_assign(
__assign_str(device_name, dev_name(sdev->dev));
__entry->msg = msg;
__entry->msg_ext = msg_ext;
),
TP_printk("device_name=%s msg=%#x msg_ext=%#x",
__get_str(device_name), __entry->msg, __entry->msg_ext)
);
DEFINE_EVENT(sof_intel_ipc_firmware_template, sof_intel_ipc_firmware_response,
TP_PROTO(struct snd_sof_dev *sdev, u32 msg, u32 msg_ext),
TP_ARGS(sdev, msg, msg_ext)
);
DEFINE_EVENT(sof_intel_ipc_firmware_template, sof_intel_ipc_firmware_initiated,
TP_PROTO(struct snd_sof_dev *sdev, u32 msg, u32 msg_ext),
TP_ARGS(sdev, msg, msg_ext)
);
TRACE_EVENT(sof_intel_D0I3C_updated,
TP_PROTO(struct snd_sof_dev *sdev, u8 reg),
TP_ARGS(sdev, reg),
TP_STRUCT__entry(
__string(device_name, dev_name(sdev->dev))
__field(u8, reg)
),
TP_fast_assign(
__assign_str(device_name, dev_name(sdev->dev));
__entry->reg = reg;
),
TP_printk("device_name=%s register=%#x",
__get_str(device_name), __entry->reg)
);
TRACE_EVENT(sof_intel_hda_irq_ipc_check,
TP_PROTO(struct snd_sof_dev *sdev, u32 irq_status),
TP_ARGS(sdev, irq_status),
TP_STRUCT__entry(
__string(device_name, dev_name(sdev->dev))
__field(u32, irq_status)
),
TP_fast_assign(
__assign_str(device_name, dev_name(sdev->dev));
__entry->irq_status = irq_status;
),
TP_printk("device_name=%s irq_status=%#x",
__get_str(device_name), __entry->irq_status)
);
TRACE_EVENT(sof_intel_hda_dsp_pcm,
TP_PROTO(struct snd_sof_dev *sdev,
struct hdac_stream *hstream,
struct snd_pcm_substream *substream,
snd_pcm_uframes_t pos
),
TP_ARGS(sdev, hstream, substream, pos),
TP_STRUCT__entry(
__string(device_name, dev_name(sdev->dev))
__field(u32, hstream_index)
__field(u32, substream)
__field(unsigned long, pos)
),
TP_fast_assign(
__assign_str(device_name, dev_name(sdev->dev));
__entry->hstream_index = hstream->index;
__entry->substream = substream->stream;
__entry->pos = pos;
),
TP_printk("device_name=%s hstream_index=%d substream=%d pos=%lu",
__get_str(device_name), __entry->hstream_index,
__entry->substream, __entry->pos)
);
TRACE_EVENT(sof_intel_hda_dsp_stream_status,
TP_PROTO(struct device *dev, struct hdac_stream *s, u32 status),
TP_ARGS(dev, s, status),
TP_STRUCT__entry(
__string(device_name, dev_name(dev))
__field(u32, stream)
__field(u32, status)
),
TP_fast_assign(
__assign_str(device_name, dev_name(dev));
__entry->stream = s->index;
__entry->status = status;
),
TP_printk("device_name=%s stream=%d status=%#x",
__get_str(device_name), __entry->stream, __entry->status)
);
TRACE_EVENT(sof_intel_hda_dsp_check_stream_irq,
TP_PROTO(struct snd_sof_dev *sdev, u32 status),
TP_ARGS(sdev, status),
TP_STRUCT__entry(
__string(device_name, dev_name(sdev->dev))
__field(u32, status)
),
TP_fast_assign(
__assign_str(device_name, dev_name(sdev->dev));
__entry->status = status;
),
TP_printk("device_name=%s status=%#x",
__get_str(device_name), __entry->status)
);
#endif /* _TRACE_SOF_INTEL_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
......@@ -131,6 +131,50 @@ void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
}
EXPORT_SYMBOL(string_get_size);
/**
* parse_int_array_user - Split string into a sequence of integers
* @from: The user space buffer to read from
* @count: The maximum number of bytes to read
* @array: Returned pointer to sequence of integers
*
* On success @array is allocated and initialized with a sequence of
* integers extracted from the @from plus an additional element that
* begins the sequence and specifies the integers count.
*
* Caller takes responsibility for freeing @array when it is no longer
* needed.
*/
int parse_int_array_user(const char __user *from, size_t count, int **array)
{
int *ints, nints;
char *buf;
int ret = 0;
buf = memdup_user_nul(from, count);
if (IS_ERR(buf))
return PTR_ERR(buf);
get_options(buf, 0, &nints);
if (!nints) {
ret = -ENOENT;
goto free_buf;
}
ints = kcalloc(nints + 1, sizeof(*ints), GFP_KERNEL);
if (!ints) {
ret = -ENOMEM;
goto free_buf;
}
get_options(buf, nints + 1, ints);
*array = ints;
free_buf:
kfree(buf);
return ret;
}
EXPORT_SYMBOL(parse_int_array_user);
static bool unescape_space(char **src, char **dst)
{
char *p = *dst, *q = *src;
......
......@@ -427,6 +427,11 @@ static const struct config_entry config_table[] = {
.device = 0x51cd,
},
/* Alderlake-PS */
{
.flags = FLAG_SOF,
.device = 0x51c9,
.codec_hid = &essx_83x6,
},
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x51c9,
......
......@@ -157,6 +157,85 @@ int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8 device_type)
}
EXPORT_SYMBOL(intel_nhlt_ssp_endpoint_mask);
#define SSP_BLOB_V1_0_SIZE 84
#define SSP_BLOB_V1_0_MDIVC_OFFSET 19 /* offset in u32 */
#define SSP_BLOB_V1_5_SIZE 96
#define SSP_BLOB_V1_5_MDIVC_OFFSET 21 /* offset in u32 */
#define SSP_BLOB_VER_1_5 0xEE000105
#define SSP_BLOB_V2_0_SIZE 88
#define SSP_BLOB_V2_0_MDIVC_OFFSET 20 /* offset in u32 */
#define SSP_BLOB_VER_2_0 0xEE000200
int intel_nhlt_ssp_mclk_mask(struct nhlt_acpi_table *nhlt, int ssp_num)
{
struct nhlt_endpoint *epnt;
struct nhlt_fmt *fmt;
struct nhlt_fmt_cfg *cfg;
int mclk_mask = 0;
int i, j;
if (!nhlt)
return 0;
epnt = (struct nhlt_endpoint *)nhlt->desc;
for (i = 0; i < nhlt->endpoint_count; i++) {
/* we only care about endpoints connected to an audio codec over SSP */
if (epnt->linktype == NHLT_LINK_SSP &&
epnt->device_type == NHLT_DEVICE_I2S &&
epnt->virtual_bus_id == ssp_num) {
fmt = (struct nhlt_fmt *)(epnt->config.caps + epnt->config.size);
cfg = fmt->fmt_config;
/*
* In theory all formats should use the same MCLK but it doesn't hurt to
* double-check that the configuration is consistent
*/
for (j = 0; j < fmt->fmt_count; j++) {
u32 *blob;
int mdivc_offset;
int size;
/* first check we have enough data to read the blob type */
if (cfg->config.size < 8)
return -EINVAL;
blob = (u32 *)cfg->config.caps;
if (blob[1] == SSP_BLOB_VER_2_0) {
mdivc_offset = SSP_BLOB_V2_0_MDIVC_OFFSET;
size = SSP_BLOB_V2_0_SIZE;
} else if (blob[1] == SSP_BLOB_VER_1_5) {
mdivc_offset = SSP_BLOB_V1_5_MDIVC_OFFSET;
size = SSP_BLOB_V1_5_SIZE;
} else {
mdivc_offset = SSP_BLOB_V1_0_MDIVC_OFFSET;
size = SSP_BLOB_V1_0_SIZE;
}
/* make sure we have enough data for the fixed part of the blob */
if (cfg->config.size < size)
return -EINVAL;
mclk_mask |= blob[mdivc_offset] & GENMASK(1, 0);
cfg = (struct nhlt_fmt_cfg *)(cfg->config.caps + cfg->config.size);
}
}
epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
}
/* make sure only one MCLK is used */
if (hweight_long(mclk_mask) != 1)
return -EINVAL;
return mclk_mask;
}
EXPORT_SYMBOL(intel_nhlt_ssp_mclk_mask);
static struct nhlt_specific_cfg *
nhlt_get_specific_cfg(struct device *dev, struct nhlt_fmt *fmt, u8 num_ch,
u32 rate, u8 vbps, u8 bps)
......
......@@ -68,6 +68,7 @@ config SND_SOC_ACPI
# All the supported SoCs
source "sound/soc/adi/Kconfig"
source "sound/soc/amd/Kconfig"
source "sound/soc/apple/Kconfig"
source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
source "sound/soc/bcm/Kconfig"
......
......@@ -34,6 +34,7 @@ obj-$(CONFIG_SND_SOC_ACPI) += snd-soc-acpi.o
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
obj-$(CONFIG_SND_SOC) += codecs/
obj-$(CONFIG_SND_SOC) += generic/
obj-$(CONFIG_SND_SOC) += apple/
obj-$(CONFIG_SND_SOC) += adi/
obj-$(CONFIG_SND_SOC) += amd/
obj-$(CONFIG_SND_SOC) += atmel/
......
......@@ -122,8 +122,29 @@ config SND_SOC_AMD_RPL_ACP6x
tristate "AMD Audio Coprocessor-v6.2 RPL support"
depends on X86 && PCI
help
This option enables Audio Coprocessor i.e ACP v6.2 support on
This option enables Audio Coprocessor i.e. ACP v6.2 support on
AMD RPL platform. By enabling this flag build will be
triggered for ACP PCI driver.
Say m if you have such a device.
If unsure select "N".
config SND_SOC_AMD_PS
tristate "AMD Audio Coprocessor-v6.2 Pink Sardine support"
depends on X86 && PCI && ACPI
help
This option enables Audio Coprocessor i.e ACP v6.2 support on
AMD Pink sardine platform. By enabling this flag build will be
triggered for ACP PCI driver, ACP PDM DMA driver.
Say m if you have such a device.
If unsure select "N".
config SND_SOC_AMD_PS_MACH
tristate "AMD PINK SARDINE support for DMIC"
select SND_SOC_DMIC
depends on SND_SOC_AMD_PS
help
This option enables machine driver for Pink Sardine platform
using dmic. ACP IP has PDM Decoder block with DMA controller.
DMIC can be connected directly to ACP IP.
Say m if you have such a device.
If unsure select "N".
......@@ -18,3 +18,4 @@ obj-$(CONFIG_SND_SOC_AMD_ACP6x) += yc/
obj-$(CONFIG_SND_SOC_AMD_ACP_COMMON) += acp/
obj-$(CONFIG_SND_AMD_ACP_CONFIG) += snd-acp-config.o
obj-$(CONFIG_SND_SOC_AMD_RPL_ACP6x) += rpl/
obj-$(CONFIG_SND_SOC_AMD_PS) += ps/
......@@ -25,6 +25,65 @@
#define DRV_NAME "acp_i2s_playcap"
static int acp_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
struct acp_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
int mode;
mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
switch (mode) {
case SND_SOC_DAIFMT_I2S:
adata->tdm_mode = TDM_DISABLE;
break;
case SND_SOC_DAIFMT_DSP_A:
adata->tdm_mode = TDM_ENABLE;
break;
default:
return -EINVAL;
}
return 0;
}
static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask,
int slots, int slot_width)
{
struct device *dev = dai->component->dev;
struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai);
struct acp_stream *stream;
int slot_len;
switch (slot_width) {
case SLOT_WIDTH_8:
slot_len = 8;
break;
case SLOT_WIDTH_16:
slot_len = 16;
break;
case SLOT_WIDTH_24:
slot_len = 24;
break;
case SLOT_WIDTH_32:
slot_len = 0;
break;
default:
dev_err(dev, "Unsupported bitdepth %d\n", slot_width);
return -EINVAL;
}
spin_lock_irq(&adata->acp_lock);
list_for_each_entry(stream, &adata->stream_list, list) {
if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
adata->tdm_tx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 15) | (slot_len << 18);
else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
adata->tdm_rx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 15) | (slot_len << 18);
}
spin_unlock_irq(&adata->acp_lock);
return 0;
}
static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
......@@ -33,7 +92,7 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
struct acp_resource *rsrc;
u32 val;
u32 xfer_resolution;
u32 reg_val;
u32 reg_val, fmt_reg, tdm_fmt;
u32 lrclk_div_val, bclk_div_val;
adata = snd_soc_dai_get_drvdata(dai);
......@@ -62,12 +121,15 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
switch (dai->driver->id) {
case I2S_BT_INSTANCE:
reg_val = ACP_BTTDM_ITER;
fmt_reg = ACP_BTTDM_TXFRMT;
break;
case I2S_SP_INSTANCE:
reg_val = ACP_I2STDM_ITER;
fmt_reg = ACP_I2STDM_TXFRMT;
break;
case I2S_HS_INSTANCE:
reg_val = ACP_HSTDM_ITER;
fmt_reg = ACP_HSTDM_TXFRMT;
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
......@@ -77,12 +139,15 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
switch (dai->driver->id) {
case I2S_BT_INSTANCE:
reg_val = ACP_BTTDM_IRER;
fmt_reg = ACP_BTTDM_RXFRMT;
break;
case I2S_SP_INSTANCE:
reg_val = ACP_I2STDM_IRER;
fmt_reg = ACP_I2STDM_RXFRMT;
break;
case I2S_HS_INSTANCE:
reg_val = ACP_HSTDM_IRER;
fmt_reg = ACP_HSTDM_RXFRMT;
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
......@@ -95,6 +160,16 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
val = val | (xfer_resolution << 3);
writel(val, adata->acp_base + reg_val);
if (adata->tdm_mode) {
val = readl(adata->acp_base + reg_val);
writel(val | BIT(1), adata->acp_base + reg_val);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
tdm_fmt = adata->tdm_tx_fmt[dai->driver->id - 1];
else
tdm_fmt = adata->tdm_rx_fmt[dai->driver->id - 1];
writel(tdm_fmt, adata->acp_base + fmt_reg);
}
if (rsrc->soc_mclk) {
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
......@@ -443,6 +518,7 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
stream->id = dai->driver->id + dir;
stream->dai_id = dai->driver->id;
stream->irq_bit = irq_bit;
stream->dir = substream->stream;
return 0;
}
......@@ -452,6 +528,8 @@ const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
.hw_params = acp_i2s_hwparams,
.prepare = acp_i2s_prepare,
.trigger = acp_i2s_trigger,
.set_fmt = acp_i2s_set_fmt,
.set_tdm_slot = acp_i2s_set_tdm_slot,
};
EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
......
......@@ -584,7 +584,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
if (drv_data->dmic_cpu_id)
num_links++;
links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL);
if (!links)
return -ENOMEM;
......@@ -749,7 +749,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
if (drv_data->dmic_cpu_id)
num_links++;
links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL);
if (!links)
return -ENOMEM;
......
......@@ -62,10 +62,9 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
if (!chip)
return -ENOMEM;
if (pci_enable_device(pci)) {
dev_err(&pci->dev, "pci_enable_device failed\n");
return -ENODEV;
}
if (pci_enable_device(pci))
return dev_err_probe(&pci->dev, -ENODEV,
"pci_enable_device failed\n");
ret = pci_request_regions(pci, "AMD ACP3x audio");
if (ret < 0) {
......@@ -105,14 +104,13 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
chip->base = devm_ioremap(&pci->dev, addr, pci_resource_len(pci, 0));
if (!chip->base) {
ret = -ENOMEM;
goto release_regions;
goto unregister_dmic_dev;
}
res = devm_kzalloc(&pci->dev, sizeof(struct resource) * num_res, GFP_KERNEL);
res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL);
if (!res) {
platform_device_unregister(dmic_dev);
ret = -ENOMEM;
goto release_regions;
goto unregister_dmic_dev;
}
for (i = 0; i < num_res; i++, res_acp++) {
......@@ -139,13 +137,14 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
pdev = platform_device_register_full(&pdevinfo);
if (IS_ERR(pdev)) {
dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name);
platform_device_unregister(dmic_dev);
ret = PTR_ERR(pdev);
goto release_regions;
goto unregister_dmic_dev;
}
return ret;
unregister_dmic_dev:
platform_device_unregister(dmic_dev);
release_regions:
pci_release_regions(pci);
disable_pci:
......
......@@ -94,7 +94,7 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
struct acp_resource *rsrc = adata->rsrc;
struct acp_stream *stream;
u16 i2s_flag = 0;
u32 ext_intr_stat, ext_intr_stat1, i;
u32 ext_intr_stat, ext_intr_stat1;
if (!adata)
return IRQ_NONE;
......@@ -104,25 +104,24 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
for (i = 0; i < ACP_MAX_STREAM; i++) {
stream = adata->stream[i];
if (stream && (ext_intr_stat & stream->irq_bit)) {
spin_lock(&adata->acp_lock);
list_for_each_entry(stream, &adata->stream_list, list) {
if (ext_intr_stat & stream->irq_bit) {
writel(stream->irq_bit,
ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
snd_pcm_period_elapsed(stream->substream);
i2s_flag = 1;
break;
}
if (adata->rsrc->no_of_ctrls == 2) {
if (stream && (ext_intr_stat1 & stream->irq_bit)) {
if (ext_intr_stat1 & stream->irq_bit) {
writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(adata,
(rsrc->irqp_used - 1)));
snd_pcm_period_elapsed(stream->substream);
i2s_flag = 1;
break;
}
}
}
spin_unlock(&adata->acp_lock);
if (i2s_flag)
return IRQ_HANDLED;
......@@ -146,9 +145,8 @@ static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream
writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
}
static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
static void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size)
{
struct acp_stream *stream = adata->stream[cpu_id];
struct snd_pcm_substream *substream = stream->substream;
struct acp_resource *rsrc = adata->rsrc;
dma_addr_t addr = substream->dma_buffer.addr;
......@@ -174,13 +172,10 @@ static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
struct snd_pcm_runtime *runtime = substream->runtime;
struct device *dev = component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
struct acp_stream *stream;
int stream_id = cpu_dai->driver->id * 2 + substream->stream;
int ret;
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
......@@ -188,7 +183,10 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
return -ENOMEM;
stream->substream = substream;
adata->stream[stream_id] = stream;
spin_lock_irq(&adata->acp_lock);
list_add_tail(&stream->list, &adata->stream_list);
spin_unlock_irq(&adata->acp_lock);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
runtime->hw = acp_pcm_hardware_playback;
......@@ -212,16 +210,13 @@ static int acp_dma_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
struct acp_dev_data *adata = snd_soc_component_get_drvdata(component);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
struct acp_stream *stream = substream->runtime->private_data;
int stream_id = cpu_dai->driver->id * 2 + substream->stream;
u64 size = params_buffer_bytes(params);
/* Configure ACP DMA block with params */
config_pte_for_stream(adata, stream);
config_acp_dma(adata, stream_id, size);
config_acp_dma(adata, stream, size);
return 0;
}
......@@ -261,16 +256,15 @@ static int acp_dma_new(struct snd_soc_component *component,
static int acp_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
struct device *dev = component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
struct acp_stream *stream;
int stream_id = cpu_dai->driver->id * 2 + substream->stream;
struct acp_stream *stream = substream->runtime->private_data;
stream = adata->stream[stream_id];
/* Remove entry from list */
spin_lock_irq(&adata->acp_lock);
list_del(&stream->list);
spin_unlock_irq(&adata->acp_lock);
kfree(stream);
adata->stream[stream_id] = NULL;
return 0;
}
......@@ -305,6 +299,10 @@ int acp_platform_register(struct device *dev)
dev_err(dev, "Fail to register acp i2s component\n");
return status;
}
INIT_LIST_HEAD(&adata->stream_list);
spin_lock_init(&adata->acp_lock);
return 0;
}
EXPORT_SYMBOL_NS_GPL(acp_platform_register, SND_SOC_ACP_COMMON);
......
......@@ -21,9 +21,9 @@
#define ACP3X_DEV 3
#define ACP6X_DEV 6
#define I2S_SP_INSTANCE 0x00
#define I2S_BT_INSTANCE 0x01
#define DMIC_INSTANCE 0x02
#define DMIC_INSTANCE 0x00
#define I2S_SP_INSTANCE 0x01
#define I2S_BT_INSTANCE 0x02
#define I2S_HS_INSTANCE 0x03
#define MEM_WINDOW_START 0x4080000
......@@ -84,6 +84,14 @@
#define ACP_MAX_STREAM 8
#define TDM_ENABLE 1
#define TDM_DISABLE 0
#define SLOT_WIDTH_8 0x8
#define SLOT_WIDTH_16 0x10
#define SLOT_WIDTH_24 0x18
#define SLOT_WIDTH_32 0x20
struct acp_chip_info {
char *name; /* Platform name */
unsigned int acp_rev; /* ACP Revision id */
......@@ -91,10 +99,12 @@ struct acp_chip_info {
};
struct acp_stream {
struct list_head list;
struct snd_pcm_substream *substream;
int irq_bit;
int dai_id;
int id;
int dir;
u64 bytescount;
u32 reg_offset;
u32 pte_offset;
......@@ -119,11 +129,13 @@ struct acp_dev_data {
void __iomem *acp_base;
unsigned int i2s_irq;
bool tdm_mode;
/* SOC specific dais */
struct snd_soc_dai_driver *dai_driver;
int num_dai;
struct acp_stream *stream[ACP_MAX_STREAM];
struct list_head stream_list;
spinlock_t acp_lock;
struct snd_soc_acpi_mach *machines;
struct platform_device *mach_dev;
......@@ -132,6 +144,8 @@ struct acp_dev_data {
u32 lrclk_div;
struct acp_resource *rsrc;
u32 tdm_tx_fmt[3];
u32 tdm_rx_fmt[3];
};
union acp_i2stdm_mstrclkgen {
......
# SPDX-License-Identifier: GPL-2.0+
# Pink Sardine platform Support
snd-pci-ps-objs := pci-ps.o
snd-ps-pdm-dma-objs := ps-pdm-dma.o
snd-soc-ps-mach-objs := ps-mach.o
obj-$(CONFIG_SND_SOC_AMD_PS) += snd-pci-ps.o
obj-$(CONFIG_SND_SOC_AMD_PS) += snd-ps-pdm-dma.o
obj-$(CONFIG_SND_SOC_AMD_PS_MACH) += snd-soc-ps-mach.o
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* AMD ALSA SoC PDM Driver
*
* Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.
*/
#include <sound/acp62_chip_offset_byte.h>
#define ACP_DEVICE_ID 0x15E2
#define ACP6x_REG_START 0x1240000
#define ACP6x_REG_END 0x1250200
#define ACP6x_DEVS 3
#define ACP6x_PDM_MODE 1
#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001
#define ACP_PGFSM_CNTL_POWER_ON_MASK 1
#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0
#define ACP_PGFSM_STATUS_MASK 3
#define ACP_POWERED_ON 0
#define ACP_POWER_ON_IN_PROGRESS 1
#define ACP_POWERED_OFF 2
#define ACP_POWER_OFF_IN_PROGRESS 3
#define ACP_ERROR_MASK 0x20000000
#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
#define PDM_DMA_STAT 0x10
#define PDM_DMA_INTR_MASK 0x10000
#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_PDM_ENABLE 1
#define ACP_PDM_DISABLE 0
#define ACP_PDM_DMA_EN_STATUS 2
#define TWO_CH 2
#define DELAY_US 5
#define ACP_COUNTER 20000
#define ACP_SRAM_PTE_OFFSET 0x03800000
#define PAGE_SIZE_4K_ENABLE 2
#define PDM_PTE_OFFSET 0
#define PDM_MEM_WINDOW_START 0x4000000
#define CAPTURE_MIN_NUM_PERIODS 4
#define CAPTURE_MAX_NUM_PERIODS 4
#define CAPTURE_MAX_PERIOD_SIZE 8192
#define CAPTURE_MIN_PERIOD_SIZE 4096
#define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS)
#define MIN_BUFFER MAX_BUFFER
/* time in ms for runtime suspend delay */
#define ACP_SUSPEND_DELAY_MS 2000
enum acp_config {
ACP_CONFIG_0 = 0,
ACP_CONFIG_1,
ACP_CONFIG_2,
ACP_CONFIG_3,
ACP_CONFIG_4,
ACP_CONFIG_5,
ACP_CONFIG_6,
ACP_CONFIG_7,
ACP_CONFIG_8,
ACP_CONFIG_9,
ACP_CONFIG_10,
ACP_CONFIG_11,
ACP_CONFIG_12,
ACP_CONFIG_13,
ACP_CONFIG_14,
ACP_CONFIG_15,
};
struct pdm_stream_instance {
u16 num_pages;
u16 channels;
dma_addr_t dma_addr;
u64 bytescount;
void __iomem *acp62_base;
};
struct pdm_dev_data {
u32 pdm_irq;
void __iomem *acp62_base;
struct snd_pcm_substream *capture_stream;
};
static inline u32 acp62_readl(void __iomem *base_addr)
{
return readl(base_addr);
}
static inline void acp62_writel(u32 val, void __iomem *base_addr)
{
writel(val, base_addr);
}
// SPDX-License-Identifier: GPL-2.0+
/*
* AMD Pink Sardine ACP PCI Driver
*
* Copyright 2022 Advanced Micro Devices, Inc.
*/
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/interrupt.h>
#include <sound/pcm_params.h>
#include <linux/pm_runtime.h>
#include "acp62.h"
struct acp62_dev_data {
void __iomem *acp62_base;
struct resource *res;
bool acp62_audio_mode;
struct platform_device *pdev[ACP6x_DEVS];
};
static int acp62_power_on(void __iomem *acp_base)
{
u32 val;
int timeout;
val = acp62_readl(acp_base + ACP_PGFSM_STATUS);
if (!val)
return val;
if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS)
acp62_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
timeout = 0;
while (++timeout < 500) {
val = acp62_readl(acp_base + ACP_PGFSM_STATUS);
if (!val)
return 0;
udelay(1);
}
return -ETIMEDOUT;
}
static int acp62_reset(void __iomem *acp_base)
{
u32 val;
int timeout;
acp62_writel(1, acp_base + ACP_SOFT_RESET);
timeout = 0;
while (++timeout < 500) {
val = acp62_readl(acp_base + ACP_SOFT_RESET);
if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK)
break;
cpu_relax();
}
acp62_writel(0, acp_base + ACP_SOFT_RESET);
timeout = 0;
while (++timeout < 500) {
val = acp62_readl(acp_base + ACP_SOFT_RESET);
if (!val)
return 0;
cpu_relax();
}
return -ETIMEDOUT;
}
static void acp62_enable_interrupts(void __iomem *acp_base)
{
acp62_writel(1, acp_base + ACP_EXTERNAL_INTR_ENB);
}
static void acp62_disable_interrupts(void __iomem *acp_base)
{
acp62_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base +
ACP_EXTERNAL_INTR_STAT);
acp62_writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL);
acp62_writel(0, acp_base + ACP_EXTERNAL_INTR_ENB);
}
static int acp62_init(void __iomem *acp_base, struct device *dev)
{
int ret;
ret = acp62_power_on(acp_base);
if (ret) {
dev_err(dev, "ACP power on failed\n");
return ret;
}
acp62_writel(0x01, acp_base + ACP_CONTROL);
ret = acp62_reset(acp_base);
if (ret) {
dev_err(dev, "ACP reset failed\n");
return ret;
}
acp62_writel(0x03, acp_base + ACP_CLKMUX_SEL);
acp62_enable_interrupts(acp_base);
return 0;
}
static int acp62_deinit(void __iomem *acp_base, struct device *dev)
{
int ret;
acp62_disable_interrupts(acp_base);
ret = acp62_reset(acp_base);
if (ret) {
dev_err(dev, "ACP reset failed\n");
return ret;
}
acp62_writel(0, acp_base + ACP_CLKMUX_SEL);
acp62_writel(0, acp_base + ACP_CONTROL);
return 0;
}
static irqreturn_t acp62_irq_handler(int irq, void *dev_id)
{
struct acp62_dev_data *adata;
struct pdm_dev_data *ps_pdm_data;
u32 val;
adata = dev_id;
if (!adata)
return IRQ_NONE;
val = acp62_readl(adata->acp62_base + ACP_EXTERNAL_INTR_STAT);
if (val & BIT(PDM_DMA_STAT)) {
ps_pdm_data = dev_get_drvdata(&adata->pdev[0]->dev);
acp62_writel(BIT(PDM_DMA_STAT), adata->acp62_base + ACP_EXTERNAL_INTR_STAT);
if (ps_pdm_data->capture_stream)
snd_pcm_period_elapsed(ps_pdm_data->capture_stream);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
static int snd_acp62_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
struct acp62_dev_data *adata;
struct platform_device_info pdevinfo[ACP6x_DEVS];
int index, ret;
int val = 0x00;
struct acpi_device *adev;
const union acpi_object *obj;
u32 addr;
unsigned int irqflags;
irqflags = IRQF_SHARED;
/* Pink Sardine device check */
switch (pci->revision) {
case 0x63:
break;
default:
dev_dbg(&pci->dev, "acp62 pci device not found\n");
return -ENODEV;
}
if (pci_enable_device(pci)) {
dev_err(&pci->dev, "pci_enable_device failed\n");
return -ENODEV;
}
ret = pci_request_regions(pci, "AMD ACP6.2 audio");
if (ret < 0) {
dev_err(&pci->dev, "pci_request_regions failed\n");
goto disable_pci;
}
adata = devm_kzalloc(&pci->dev, sizeof(struct acp62_dev_data),
GFP_KERNEL);
if (!adata) {
ret = -ENOMEM;
goto release_regions;
}
addr = pci_resource_start(pci, 0);
adata->acp62_base = devm_ioremap(&pci->dev, addr,
pci_resource_len(pci, 0));
if (!adata->acp62_base) {
ret = -ENOMEM;
goto release_regions;
}
pci_set_master(pci);
pci_set_drvdata(pci, adata);
ret = acp62_init(adata->acp62_base, &pci->dev);
if (ret)
goto release_regions;
val = acp62_readl(adata->acp62_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 + (ACP6x_REG_END - ACP6x_REG_START);
adata->acp62_audio_mode = ACP6x_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 < ACP6x_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, acp62_irq_handler,
irqflags, "ACP_PCI_IRQ", adata);
if (ret) {
dev_err(&pci->dev, "ACP PCI IRQ request failed\n");
goto unregister_devs;
}
}
}
break;
}
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 (acp62_deinit(adata->acp62_base, &pci->dev))
dev_err(&pci->dev, "ACP de-init failed\n");
release_regions:
pci_release_regions(pci);
disable_pci:
pci_disable_device(pci);
return ret;
}
static int __maybe_unused snd_acp62_suspend(struct device *dev)
{
struct acp62_dev_data *adata;
int ret;
adata = dev_get_drvdata(dev);
ret = acp62_deinit(adata->acp62_base, dev);
if (ret)
dev_err(dev, "ACP de-init failed\n");
return ret;
}
static int __maybe_unused snd_acp62_resume(struct device *dev)
{
struct acp62_dev_data *adata;
int ret;
adata = dev_get_drvdata(dev);
ret = acp62_init(adata->acp62_base, dev);
if (ret)
dev_err(dev, "ACP init failed\n");
return ret;
}
static const struct dev_pm_ops acp62_pm_ops = {
SET_RUNTIME_PM_OPS(snd_acp62_suspend, snd_acp62_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(snd_acp62_suspend, snd_acp62_resume)
};
static void snd_acp62_remove(struct pci_dev *pci)
{
struct acp62_dev_data *adata;
int ret, index;
adata = pci_get_drvdata(pci);
if (adata->acp62_audio_mode == ACP6x_PDM_MODE) {
for (index = 0; index < ACP6x_DEVS; index++)
platform_device_unregister(adata->pdev[index]);
}
ret = acp62_deinit(adata->acp62_base, &pci->dev);
if (ret)
dev_err(&pci->dev, "ACP de-init failed\n");
pm_runtime_forbid(&pci->dev);
pm_runtime_get_noresume(&pci->dev);
pci_release_regions(pci);
pci_disable_device(pci);
}
static const struct pci_device_id snd_acp62_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID),
.class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
.class_mask = 0xffffff },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, snd_acp62_ids);
static struct pci_driver ps_acp62_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_acp62_ids,
.probe = snd_acp62_probe,
.remove = snd_acp62_remove,
.driver = {
.pm = &acp62_pm_ops,
}
};
module_pci_driver(ps_acp62_driver);
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
MODULE_AUTHOR("Syed.SabaKareem@amd.com");
MODULE_DESCRIPTION("AMD ACP Pink Sardine PCI driver");
MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0+
/*
* Machine driver for AMD Pink Sardine platform using DMIC
*
* Copyright 2022 Advanced Micro Devices, Inc.
*/
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <linux/io.h>
#include <linux/dmi.h>
#include "acp62.h"
#define DRV_NAME "acp_ps_mach"
SND_SOC_DAILINK_DEF(acp62_pdm,
DAILINK_COMP_ARRAY(COMP_CPU("acp_ps_pdm_dma.0")));
SND_SOC_DAILINK_DEF(dmic_codec,
DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec.0",
"dmic-hifi")));
SND_SOC_DAILINK_DEF(pdm_platform,
DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_ps_pdm_dma.0")));
static struct snd_soc_dai_link acp62_dai_pdm[] = {
{
.name = "acp62-dmic-capture",
.stream_name = "DMIC capture",
.capture_only = 1,
SND_SOC_DAILINK_REG(acp62_pdm, dmic_codec, pdm_platform),
},
};
static struct snd_soc_card acp62_card = {
.name = "acp62",
.owner = THIS_MODULE,
.dai_link = acp62_dai_pdm,
.num_links = 1,
};
static int acp62_probe(struct platform_device *pdev)
{
struct acp62_pdm *machine = NULL;
struct snd_soc_card *card;
int ret;
platform_set_drvdata(pdev, &acp62_card);
card = platform_get_drvdata(pdev);
acp62_card.dev = &pdev->dev;
snd_soc_card_set_drvdata(card, machine);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
return dev_err_probe(&pdev->dev, ret,
"snd_soc_register_card(%s) failed\n",
card->name);
}
return 0;
}
static struct platform_driver acp62_mach_driver = {
.driver = {
.name = "acp_ps_mach",
.pm = &snd_soc_pm_ops,
},
.probe = acp62_probe,
};
module_platform_driver(acp62_mach_driver);
MODULE_AUTHOR("Syed.SabaKareem@amd.com");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
This diff is collapsed.
......@@ -172,7 +172,7 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *codec_dai;
int ret, i;
unsigned int num_codecs = rtd->num_codecs;
unsigned int num_codecs = rtd->dai_link->num_codecs;
unsigned int bclk_val;
ret = 0;
......
......@@ -171,6 +171,20 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "21J6"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "82"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "UM5302TA"),
}
},
{}
};
......
config SND_SOC_APPLE_MCA
tristate "Apple Silicon MCA driver"
depends on ARCH_APPLE || COMPILE_TEST
select SND_DMAENGINE_PCM
default ARCH_APPLE
help
This option enables an ASoC platform driver for MCA peripherals found
on Apple Silicon SoCs.
snd-soc-apple-mca-objs := mca.o
obj-$(CONFIG_SND_SOC_APPLE_MCA) += snd-soc-apple-mca.o
This diff is collapsed.
......@@ -891,7 +891,6 @@ static int asoc_ssc_init(struct device *dev)
int atmel_ssc_set_audio(int ssc_id)
{
struct ssc_device *ssc;
int ret;
/* If we can grab the SSC briefly to parent the DAI device off it */
ssc = ssc_request(ssc_id);
......@@ -903,9 +902,7 @@ int atmel_ssc_set_audio(int ssc_id)
ssc_info[ssc_id].ssc = ssc;
}
ret = asoc_ssc_init(&ssc->pdev->dev);
return ret;
return asoc_ssc_init(&ssc->pdev->dev);
}
EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
......
......@@ -172,7 +172,7 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
ret = snd_soc_register_card(card);
if (ret) {
dev_err_probe(&pdev->dev, ret,
"snd_soc_register_card() failed: %d\n", ret);
"snd_soc_register_card() failed\n");
goto err;
}
......
......@@ -841,14 +841,9 @@ static int bcm2835_i2s_probe(struct platform_device *pdev)
/* get the clock */
dev->clk_prepared = false;
dev->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk)) {
ret = PTR_ERR(dev->clk);
if (ret == -EPROBE_DEFER)
dev_dbg(&pdev->dev, "could not get clk: %d\n", ret);
else
dev_err(&pdev->dev, "could not get clk: %d\n", ret);
return ret;
}
if (IS_ERR(dev->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk),
"could not get clk\n");
/* Request ioarea */
base = devm_platform_ioremap_resource(pdev, 0);
......
......@@ -98,6 +98,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_DA9055
imply SND_SOC_DMIC
imply SND_SOC_ES8316
imply SND_SOC_ES8326
imply SND_SOC_ES8328_SPI
imply SND_SOC_ES8328_I2C
imply SND_SOC_ES7134
......@@ -205,6 +206,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_SIMPLE_AMPLIFIER
imply SND_SOC_SIMPLE_MUX
imply SND_SOC_SPDIF
imply SND_SOC_SRC4XXX_I2C
imply SND_SOC_SSM2305
imply SND_SOC_SSM2518
imply SND_SOC_SSM2602_SPI
......@@ -608,7 +610,7 @@ config SND_SOC_BT_SCO
config SND_SOC_CPCAP
tristate "Motorola CPCAP codec"
depends on MFD_CPCAP
depends on MFD_CPCAP || COMPILE_TEST
config SND_SOC_CQ0093VC
tristate
......@@ -690,9 +692,15 @@ config SND_SOC_CS35L45_I2C
Enable support for Cirrus Logic CS35L45 smart speaker amplifier
with I2C control.
config SND_SOC_CS42L42_CORE
tristate
config SND_SOC_CS42L42
tristate "Cirrus Logic CS42L42 CODEC"
tristate "Cirrus Logic CS42L42 CODEC (I2C)"
depends on I2C
select REGMAP
select REGMAP_I2C
select SND_SOC_CS42L42_CORE
config SND_SOC_CS42L51
tristate
......@@ -714,6 +722,13 @@ config SND_SOC_CS42L73
tristate "Cirrus Logic CS42L73 CODEC"
depends on I2C
config SND_SOC_CS42L83
tristate "Cirrus Logic CS42L83 CODEC"
depends on I2C
select REGMAP
select REGMAP_I2C
select SND_SOC_CS42L42_CORE
config SND_SOC_CS4234
tristate "Cirrus Logic CS4234 CODEC"
depends on I2C
......@@ -913,6 +928,10 @@ config SND_SOC_ES8316
tristate "Everest Semi ES8316 CODEC"
depends on I2C
config SND_SOC_ES8326
tristate "Everest Semi ES8326 CODEC"
depends on I2C
config SND_SOC_ES8328
tristate
......@@ -966,7 +985,7 @@ config SND_SOC_LM49453
config SND_SOC_LOCHNAGAR_SC
tristate "Lochnagar Sound Card"
depends on MFD_LOCHNAGAR
depends on MFD_LOCHNAGAR || COMPILE_TEST
help
This driver support the sound card functionality of the Cirrus
Logic Lochnagar audio development board.
......@@ -1191,8 +1210,7 @@ config SND_SOC_RK3328
config SND_SOC_RK817
tristate "Rockchip RK817 audio CODEC"
depends on MFD_RK808
select REGMAP_I2C
depends on MFD_RK808 || COMPILE_TEST
config SND_SOC_RL6231
tristate
......@@ -1471,6 +1489,18 @@ config SND_SOC_SIMPLE_MUX
config SND_SOC_SPDIF
tristate "S/PDIF CODEC"
config SND_SOC_SRC4XXX_I2C
tristate "Texas Instruments SRC4XXX DIR/DIT and SRC codecs"
depends on I2C
select SND_SOC_SRC4XXX
help
Enable support for the TI SRC4XXX family of codecs. These include the
scr4392 which has digital receivers, transmitters, and
a sample rate converter, including numerous ports.
config SND_SOC_SRC4XXX
tristate
config SND_SOC_SSM2305
tristate "Analog Devices SSM2305 Class-D Amplifier"
help
......@@ -1726,8 +1756,10 @@ config SND_SOC_WCD_MBHC
config SND_SOC_WCD934X
tristate "WCD9340/WCD9341 Codec"
depends on COMMON_CLK
depends on SLIMBUS
select REGMAP_SLIMBUS
select SND_SOC_WCD_MBHC
depends on MFD_WCD934X
depends on MFD_WCD934X || COMPILE_TEST
help
The WCD9340/9341 is a audio codec IC Integrated in
Qualcomm SoCs like SDM845.
......
......@@ -65,11 +65,13 @@ snd-soc-cs35l45-objs := cs35l45.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-cs42l51-objs := cs42l51.o
snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
snd-soc-cs42l52-objs := cs42l52.o
snd-soc-cs42l56-objs := cs42l56.o
snd-soc-cs42l73-objs := cs42l73.o
snd-soc-cs42l83-i2c-objs := cs42l83-i2c.o
snd-soc-cs4234-objs := cs4234.o
snd-soc-cs4265-objs := cs4265.o
snd-soc-cs4270-objs := cs4270.o
......@@ -100,6 +102,7 @@ snd-soc-dmic-objs := dmic.o
snd-soc-es7134-objs := es7134.o
snd-soc-es7241-objs := es7241.o
snd-soc-es8316-objs := es8316.o
snd-soc-es8326-objs := es8326.o
snd-soc-es8328-objs := es8328.o
snd-soc-es8328-i2c-objs := es8328-i2c.o
snd-soc-es8328-spi-objs := es8328-spi.o
......@@ -231,6 +234,8 @@ snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
snd-soc-si476x-objs := si476x.o
snd-soc-spdif-tx-objs := spdif_transmitter.o
snd-soc-spdif-rx-objs := spdif_receiver.o
snd-soc-src4xxx-objs := src4xxx.o
snd-soc-src4xxx-i2c-objs := src4xxx-i2c.o
snd-soc-ssm2305-objs := ssm2305.o
snd-soc-ssm2518-objs := ssm2518.o
snd-soc-ssm2602-objs := ssm2602.o
......@@ -419,12 +424,14 @@ 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) += snd-soc-cs42l42.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_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
obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o
obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o
obj-$(CONFIG_SND_SOC_CS42L83) += snd-soc-cs42l83-i2c.o
obj-$(CONFIG_SND_SOC_CS4234) += snd-soc-cs4234.o
obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
......@@ -455,6 +462,7 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_ES7134) += snd-soc-es7134.o
obj-$(CONFIG_SND_SOC_ES7241) += snd-soc-es7241.o
obj-$(CONFIG_SND_SOC_ES8316) += snd-soc-es8316.o
obj-$(CONFIG_SND_SOC_ES8326) += snd-soc-es8326.o
obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
......@@ -579,6 +587,8 @@ 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_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
obj-$(CONFIG_SND_SOC_SSM2305) += snd-soc-ssm2305.o
obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
......
......@@ -447,6 +447,13 @@ static int ak4458_hw_params(struct snd_pcm_substream *substream,
snd_soc_component_update_bits(component, AK4458_0B_CONTROL7,
AK4458_DCHAIN_MASK, dchn);
if (ak4458->drvdata->type == AK4497) {
ret = snd_soc_component_update_bits(component, AK4458_09_DSD2,
0x4, (ak4458->dsd_path << 2));
if (ret < 0)
return ret;
}
ret = ak4458_rstn_control(component, 0);
if (ret)
return ret;
......@@ -629,48 +636,6 @@ static void ak4458_reset(struct ak4458_priv *ak4458, bool active)
}
}
static int ak4458_init(struct snd_soc_component *component)
{
struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
int ret;
/* External Mute ON */
if (ak4458->mute_gpiod)
gpiod_set_value_cansleep(ak4458->mute_gpiod, 1);
ak4458_reset(ak4458, false);
ret = snd_soc_component_update_bits(component, AK4458_00_CONTROL1,
0x80, 0x80); /* ACKS bit = 1; 10000000 */
if (ret < 0)
return ret;
if (ak4458->drvdata->type == AK4497) {
ret = snd_soc_component_update_bits(component, AK4458_09_DSD2,
0x4, (ak4458->dsd_path << 2));
if (ret < 0)
return ret;
}
return ak4458_rstn_control(component, 1);
}
static int ak4458_probe(struct snd_soc_component *component)
{
struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
ak4458->fs = 48000;
return ak4458_init(component);
}
static void ak4458_remove(struct snd_soc_component *component)
{
struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
ak4458_reset(ak4458, true);
}
#ifdef CONFIG_PM
static int __maybe_unused ak4458_runtime_suspend(struct device *dev)
{
......@@ -714,8 +679,6 @@ static int __maybe_unused ak4458_runtime_resume(struct device *dev)
#endif /* CONFIG_PM */
static const struct snd_soc_component_driver soc_codec_dev_ak4458 = {
.probe = ak4458_probe,
.remove = ak4458_remove,
.controls = ak4458_snd_controls,
.num_controls = ARRAY_SIZE(ak4458_snd_controls),
.dapm_widgets = ak4458_dapm_widgets,
......@@ -728,8 +691,6 @@ static const struct snd_soc_component_driver soc_codec_dev_ak4458 = {
};
static const struct snd_soc_component_driver soc_codec_dev_ak4497 = {
.probe = ak4458_probe,
.remove = ak4458_remove,
.controls = ak4497_snd_controls,
.num_controls = ARRAY_SIZE(ak4497_snd_controls),
.dapm_widgets = ak4497_dapm_widgets,
......@@ -820,12 +781,16 @@ static int ak4458_i2c_probe(struct i2c_client *i2c)
pm_runtime_enable(&i2c->dev);
regcache_cache_only(ak4458->regmap, true);
ak4458_reset(ak4458, false);
return 0;
}
static int ak4458_i2c_remove(struct i2c_client *i2c)
{
struct ak4458_priv *ak4458 = i2c_get_clientdata(i2c);
ak4458_reset(ak4458, true);
pm_runtime_disable(&i2c->dev);
return 0;
......
This diff is collapsed.
This diff is collapsed.
......@@ -12,17 +12,16 @@
#ifndef __CS42L42_H__
#define __CS42L42_H__
#include <dt-bindings/sound/cs42l42.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <sound/jack.h>
#include <sound/cs42l42.h>
static const char *const cs42l42_supply_names[CS42L42_NUM_SUPPLIES] = {
"VA",
"VP",
"VCP",
"VD_FILT",
"VL",
};
#include <sound/soc-component.h>
#include <sound/soc-dai.h>
struct cs42l42_private {
struct regmap *regmap;
......@@ -32,9 +31,11 @@ struct cs42l42_private {
struct completion pdn_done;
struct snd_soc_jack *jack;
struct mutex irq_lock;
int devid;
int irq;
int pll_config;
int bclk;
u32 sclk;
u32 bclk_ratio;
u32 srate;
u8 plug_state;
u8 hs_type;
......@@ -50,6 +51,24 @@ struct cs42l42_private {
u8 stream_use;
bool hp_adc_up_pending;
bool suspended;
bool init_done;
};
extern const struct regmap_range_cfg cs42l42_page_range;
extern const struct regmap_config cs42l42_regmap;
extern const struct snd_soc_component_driver cs42l42_soc_component;
extern struct snd_soc_dai_driver cs42l42_dai;
bool cs42l42_readable_register(struct device *dev, unsigned int reg);
bool cs42l42_volatile_register(struct device *dev, unsigned int reg);
int cs42l42_suspend(struct device *dev);
int cs42l42_resume(struct device *dev);
void cs42l42_resume_restore(struct device *dev);
int cs42l42_common_probe(struct cs42l42_private *cs42l42,
const struct snd_soc_component_driver *component_drv,
struct snd_soc_dai_driver *dai);
int cs42l42_init(struct cs42l42_private *cs42l42);
void cs42l42_common_remove(struct cs42l42_private *cs42l42);
#endif /* __CS42L42_H__ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment