Commit 631d6914 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound updates from Takashi Iwai:
 "It was another busy development cycle, and the majority of changes are
  found in ASoC side. Below are Some highlights.

  ASoC core:
   - Lots of core cleanups and refactorings, still on-going work by
     Morimoto-san

  ASoC drivers:
   - Continued work on cleaning up and improving the Intel SOF stuff,
     along with new platform support including SoundWire

   - Fixes to make the Marvell SSPA driver work upstream

   - Support for AMD Renoir ACP, Dialog DA7212, Freescale EASRC and
     i.MX8M, Intel Elkhard Lake, Maxim MAX98390, Nuvoton NAU8812 and
     NAU8814 and Realtek RT1016.

  USB-audio:
   - Improvement for sync and implicit feedback streams with the more
     accurate frame size calculation and full-duplex support

   - Support for RME Babyface Pro and Prioneer DJ DJM

  HD-audio:
   - Fixes for Mic mute LED on HP machines

   - Re-enable support of Intel SST driver for SKL/KBL platforms

  FireWire:
   - Lots of refactoring, add support for RME FireFace and MOTU
     UltraLite-mk3"

* tag 'sound-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (428 commits)
  ALSA: es1688: Add the missed snd_card_free()
  ALSA: hda: add sienna_cichlid audio asic id for sienna_cichlid up
  ALSA: usb-audio: Add Pioneer DJ DJM-900NXS2 support
  ASoC: qcom: q6asm-dai: kCFI fix
  ASoC: soc-card: add snd_soc_card_remove_dai_link()
  ASoC: soc-card: add snd_soc_card_add_dai_link()
  ASoC: soc-card: add snd_soc_card_set_bias_level_post()
  ASoC: soc-card: add snd_soc_card_set_bias_level()
  ASoC: soc-card: add snd_soc_card_remove()
  ASoC: soc-card: add snd_soc_card_late_probe()
  ASoC: soc-card: add snd_soc_card_probe()
  ASoC: soc-card: add probed bit field to snd_soc_card
  ASoC: soc-card: add snd_soc_card_resume_post()
  ASoC: soc-card: add snd_soc_card_resume_pre()
  ASoC: soc-card: add snd_soc_card_suspend_post()
  ASoC: soc-card: add snd_soc_card_suspend_pre()
  ASoC: soc-card: move snd_soc_card_subclass to soc-card
  ASoC: soc-card: move snd_soc_card_get_codec_dai() to soc-card
  ASoC: soc-card: move snd_soc_card_set/get_drvdata() to soc-card
  ASoC: soc-card: move snd_soc_card_jack_new() to soc-card
  ...
parents a0a4d17e d9b8fbf1
......@@ -17,6 +17,8 @@ properties:
compatible:
enum:
- fsl,imx8qxp-dsp
- fsl,imx8qm-dsp
- fsl,imx8mp-dsp
reg:
description: Should contain register location and length
......
Dialog Semiconductor DA7213 Audio Codec bindings
Dialog Semiconductor DA7212/DA7213 Audio Codec bindings
======
Required properties:
- compatible : Should be "dlg,da7213"
- compatible : Should be "dlg,da7212" or "dlg,da7213"
- reg: Specifies the I2C slave address
Optional properties:
......@@ -21,6 +21,10 @@ Optional properties:
- dlg,dmic-clkrate : DMIC clock frequency (Hz).
[<1500000>, <3000000>]
- VDDA-supply : Regulator phandle for Analogue power supply
- VDDMIC-supply : Regulator phandle for Mic Bias
- VDDIO-supply : Regulator phandle for I/O power supply
======
Example:
......
......@@ -51,6 +51,10 @@ Optional properties:
will be in use as default. Otherwise, the big endian
mode will be in use for all the device registers.
- fsl,asrc-format : Defines a mutual sample format used by DPCM Back
Ends, which can replace the fsl,asrc-width.
The value is 2 (S16_LE), or 6 (S24_LE).
Example:
asrc: asrc@2034000 {
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/fsl,easrc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP Asynchronous Sample Rate Converter (ASRC) Controller
maintainers:
- Shengjiu Wang <shengjiu.wang@nxp.com>
properties:
$nodename:
pattern: "^easrc@.*"
compatible:
const: fsl,imx8mn-easrc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: Peripheral clock
clock-names:
items:
- const: mem
dmas:
maxItems: 8
dma-names:
items:
- const: ctx0_rx
- const: ctx0_tx
- const: ctx1_rx
- const: ctx1_tx
- const: ctx2_rx
- const: ctx2_tx
- const: ctx3_rx
- const: ctx3_tx
firmware-name:
allOf:
- $ref: /schemas/types.yaml#/definitions/string
- const: imx/easrc/easrc-imx8mn.bin
description: The coefficient table for the filters
fsl,asrc-rate:
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 8000
- maximum: 192000
description: Defines a mutual sample rate used by DPCM Back Ends
fsl,asrc-format:
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [2, 6, 10, 32, 36]
default: 2
description:
Defines a mutual sample format used by DPCM Back Ends
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- dmas
- dma-names
- firmware-name
- fsl,asrc-rate
- fsl,asrc-format
examples:
- |
#include <dt-bindings/clock/imx8mn-clock.h>
easrc: easrc@300c0000 {
compatible = "fsl,imx8mn-easrc";
reg = <0x0 0x300c0000 0x0 0x10000>;
interrupts = <0x0 122 0x4>;
clocks = <&clk IMX8MN_CLK_ASRC_ROOT>;
clock-names = "mem";
dmas = <&sdma2 16 23 0> , <&sdma2 17 23 0>,
<&sdma2 18 23 0> , <&sdma2 19 23 0>,
<&sdma2 20 23 0> , <&sdma2 21 23 0>,
<&sdma2 22 23 0> , <&sdma2 23 23 0>;
dma-names = "ctx0_rx", "ctx0_tx",
"ctx1_rx", "ctx1_tx",
"ctx2_rx", "ctx2_tx",
"ctx3_rx", "ctx3_tx";
firmware-name = "imx/easrc/easrc-imx8mn.bin";
fsl,asrc-rate = <8000>;
fsl,asrc-format = <2>;
};
......@@ -12,6 +12,7 @@ Required properties:
"fsl,imx35-esai",
"fsl,vf610-esai",
"fsl,imx6ull-esai",
"fsl,imx8qm-esai",
- reg : Offset and length of the register set for the device.
......
# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/marvell,mmp-sspa.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Marvel SSPA Digital Audio Interface Bindings
maintainers:
- Lubomir Rintel <lkundrak@v3.sk>
properties:
$nodename:
pattern: "^audio-controller(@.*)?$"
compatible:
const: marvell,mmp-sspa
reg:
items:
- description: RX block
- description: TX block
interrupts:
maxItems: 1
clocks:
items:
- description: Clock for the Audio block
- description: I2S bit clock
clock-names:
items:
- const: audio
- const: bitclk
power-domains:
maxItems: 1
'#sound-dai-cells':
const: 0
dmas:
items:
- description: TX DMA Channel
- description: RX DMA Channel
dma-names:
items:
- const: tx
- const: rx
port:
type: object
properties:
endpoint:
type: object
properties:
remote-endpoint: true
frame-master:
type: boolean
description: SoC generates the frame clock
bitclock-master:
type: boolean
description: SoC generates the bit clock
dai-format:
$ref: /schemas/types.yaml#/definitions/string
description: The digital audio format
const: i2s
required:
- remote-endpoint
required:
- endpoint
additionalProperties: false
required:
- "#sound-dai-cells"
- compatible
- reg
- interrupts
- clocks
- clock-names
- dmas
- dma-names
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/marvell,mmp2.h>
audio-controller@d42a0c00 {
compatible = "marvell,mmp-sspa";
reg = <0xd42a0c00 0x30>,
<0xd42a0c80 0x30>;
interrupts = <2>;
clock-names = "audio", "bitclk";
clocks = <&soc_clocks 127>,
<&audio_clk 1>;
#sound-dai-cells = <0>;
dmas = <&adma0 0>, <&adma0 1>;
dma-names = "tx", "rx";
port {
endpoint {
remote-endpoint = <&rt5631_0>;
frame-master;
bitclock-master;
dai-format = "i2s";
};
};
};
...
NAU8810 audio CODEC
NAU8810/NAU8812/NAU8814 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "nuvoton,nau8810"
- compatible : One of "nuvoton,nau8810" or "nuvoton,nau8812" or
"nuvoton,nau8814"
- reg : the I2C address of the device.
......
......@@ -101,5 +101,5 @@ Example:
nuvoton,crosstalk-enable;
clock-names = "mclk";
clocks = <&tegra_car TEGRA210_CLK_CLK_OUT_2>;
clocks = <&tegra_pmc TEGRA_PMC_CLK_OUT_2>;
};
......@@ -29,6 +29,7 @@ Optional properties:
- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
- nvidia,int-mic-en-gpios : The GPIO that enables the internal microphone
- nvidia,ext-mic-en-gpios : The GPIO that enables the external microphone
- nvidia,headset : The Mic Jack represents state of the headset microphone pin
Example:
......
......@@ -30,6 +30,8 @@ Required properties:
- reg : Must contain an address for each entry in reg-names.
- reg-names : A list which must include the following entries:
* "lpass-lpaif"
- #address-cells : Must be 1
- #size-cells : Must be 0
......@@ -37,6 +39,20 @@ Optional properties:
- qcom,adsp : Phandle for the audio DSP node
By default, the driver uses up to 4 MI2S SD lines, for a total of 8 channels.
The SD lines to use can be configured by adding subnodes for each of the DAIs.
Required properties for each DAI (represented by a subnode):
- reg : Must be one of the DAI IDs
(usually part of dt-bindings header)
- qcom,playback-sd-lines: List of serial data lines to use for playback
Each SD line should be represented by a number from 0-3.
- qcom,capture-sd-lines : List of serial data lines to use for capture
Each SD line should be represented by a number from 0-3.
Note that adding a subnode changes the default to "no lines configured",
so both playback and capture lines should be configured when a subnode is added.
Example:
lpass@28100000 {
......@@ -51,4 +67,13 @@ lpass@28100000 {
reg = <0x28100000 0x10000>;
reg-names = "lpass-lpaif";
qcom,adsp = <&adsp>;
#address-cells = <1>;
#size-cells = <0>;
/* Optional to set different MI2S SD lines */
dai@3 {
reg = <MI2S_QUATERNARY>;
qcom,playback-sd-lines = <0 1>;
};
};
......@@ -29,7 +29,7 @@ used by the apr service device.
Definition: Must be 0
= EXAMPLE
q6adm@8 {
apr-service@8 {
compatible = "qcom,q6adm";
reg = <APR_SVC_ADM>;
q6routing: routing {
......
......@@ -100,7 +100,7 @@ configuration of each dai. Must contain the following properties.
= EXAMPLE
q6afe@4 {
apr-service@4 {
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
......@@ -110,12 +110,12 @@ q6afe@4 {
#address-cells = <1>;
#size-cells = <0>;
hdmi@1 {
reg = <1>;
dai@1 {
reg = <HDMI_RX>;
};
tdm@24 {
reg = <24>;
dai@24 {
reg = <PRIMARY_TDM_RX_0>;
qcom,tdm-sync-mode = <1>:
qcom,tdm-sync-src = <1>;
qcom,tdm-data-out = <0>;
......@@ -125,8 +125,8 @@ q6afe@4 {
};
tdm@25 {
reg = <25>;
dai@25 {
reg = <PRIMARY_TDM_TX_0>;
qcom,tdm-sync-mode = <1>:
qcom,tdm-sync-src = <1>;
qcom,tdm-data-out = <0>;
......@@ -135,43 +135,43 @@ q6afe@4 {
qcom,tdm-data-align = <0>;
};
prim-mi2s-rx@16 {
reg = <16>;
dai@16 {
reg = <PRIMARY_MI2S_RX>;
qcom,sd-lines = <0 2>;
};
prim-mi2s-tx@17 {
reg = <17>;
dai@17 {
reg = <PRIMARY_MI2S_TX>;
qcom,sd-lines = <1>;
};
sec-mi2s-rx@18 {
reg = <18>;
dai@18 {
reg = <SECONDARY_MI2S_RX>;
qcom,sd-lines = <0 3>;
};
sec-mi2s-tx@19 {
reg = <19>;
dai@19 {
reg = <SECONDARY_MI2S_TX>;
qcom,sd-lines = <1>;
};
tert-mi2s-rx@20 {
reg = <20>;
dai@20 {
reg = <TERTIARY_MI2S_RX>;
qcom,sd-lines = <1 3>;
};
tert-mi2s-tx@21 {
reg = <21>;
dai@21 {
reg = <TERTIARY_MI2S_TX>;
qcom,sd-lines = <0>;
};
quat-mi2s-rx@22 {
reg = <22>;
dai@22 {
reg = <QUATERNARY_MI2S_RX>;
qcom,sd-lines = <0>;
};
quat-mi2s-tx@23 {
reg = <23>;
dai@23 {
reg = <QUATERNARY_MI2S_TX>;
qcom,sd-lines = <1>;
};
};
......
......@@ -51,13 +51,16 @@ configuration of each dai. Must contain the following properties.
= EXAMPLE
q6asm@7 {
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>;
mm@0 {
dai@0 {
reg = <0>;
direction = <2>;
is-compress-dai;
......
......@@ -15,7 +15,7 @@ used by the apr service device.
example "qcom,q6core-v2.0"
= EXAMPLE
q6core@3 {
apr-service@3 {
compatible = "qcom,q6core";
reg = <APR_SVC_ADSP_CORE>;
};
......@@ -263,6 +263,7 @@ Required properties:
"renesas,rcar_sound-gen2" if generation2 (or RZ/G1)
"renesas,rcar_sound-gen3" if generation3 (or RZ/G2)
Examples with soctypes are:
- "renesas,rcar_sound-r8a7742" (RZ/G1H)
- "renesas,rcar_sound-r8a7743" (RZ/G1M)
- "renesas,rcar_sound-r8a7744" (RZ/G1N)
- "renesas,rcar_sound-r8a7745" (RZ/G1E)
......
......@@ -24,6 +24,7 @@ properties:
- rockchip,rk3188-i2s
- rockchip,rk3228-i2s
- rockchip,rk3288-i2s
- rockchip,rk3308-i2s
- rockchip,rk3328-i2s
- rockchip,rk3366-i2s
- rockchip,rk3368-i2s
......@@ -47,12 +48,13 @@ properties:
- const: i2s_hclk
dmas:
items:
- description: TX DMA Channel
- description: RX DMA Channel
minItems: 1
maxItems: 2
dma-names:
items:
oneOf:
- const: rx
- items:
- const: tx
- const: rx
......
RT1016 Stereo Class D Audio Amplifier
This device supports I2C only.
Required properties:
- compatible : "realtek,rt1016".
- reg : The I2C address of the device.
Example:
rt1016: codec@1a {
compatible = "realtek,rt1016";
reg = <0x1a>;
};
File mode changed from 100755 to 100644
Simple-Card:
Simple-Card specifies audio DAI connections of SoC <-> codec.
Required properties:
- compatible : "simple-audio-card"
Optional properties:
- simple-audio-card,name : User specified audio sound card name, one string
property.
- simple-audio-card,widgets : Please refer to widgets.txt.
- simple-audio-card,routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the
connection's sink, the second being the connection's
source.
- simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec
mclk. When defined, mclk-fs property defined in
dai-link sub nodes are ignored.
- simple-audio-card,hp-det-gpio : Reference to GPIO that signals when
headphones are attached.
- simple-audio-card,mic-det-gpio : Reference to GPIO that signals when
a microphone is attached.
- simple-audio-card,aux-devs : List of phandles pointing to auxiliary devices, such
as amplifiers, to be added to the sound card.
- simple-audio-card,pin-switches : List of strings containing the widget names for
which pin switches must be created.
Optional subnodes:
- simple-audio-card,dai-link : Container for dai-link level
properties and the CPU and CODEC
sub-nodes. This container may be
omitted when the card has only one
DAI link. See the examples and the
section below.
Dai-link subnode properties and subnodes:
If dai-link subnode is omitted and the subnode properties are directly
under "sound"-node the subnode property and subnode names have to be
prefixed with "simple-audio-card,"-prefix.
Required dai-link subnodes:
- cpu : CPU sub-node
- codec : CODEC sub-node
Optional dai-link subnode properties:
- format : CPU/CODEC common audio format.
"i2s", "right_j", "left_j" , "dsp_a"
"dsp_b", "ac97", "pdm", "msb", "lsb"
- frame-master : Indicates dai-link frame master.
phandle to a cpu or codec subnode.
- bitclock-master : Indicates dai-link bit clock master.
phandle to a cpu or codec subnode.
- bitclock-inversion : bool property. Add this if the
dai-link uses bit clock inversion.
- frame-inversion : bool property. Add this if the
dai-link uses frame clock inversion.
- mclk-fs : Multiplication factor between stream
rate and codec mclk, applied only for
the dai-link.
For backward compatibility the frame-master and bitclock-master
properties can be used as booleans in codec subnode to indicate if the
codec is the dai-link frame or bit clock master. In this case there
should be no dai-link node, the same properties should not be present
at sound-node level, and the bitclock-inversion and frame-inversion
properties should also be placed in the codec node if needed.
Required CPU/CODEC subnodes properties:
- sound-dai : phandle and port of CPU/CODEC
Optional CPU/CODEC subnodes properties:
- dai-tdm-slot-num : Please refer to tdm-slot.txt.
- dai-tdm-slot-width : Please refer to tdm-slot.txt.
- clocks / system-clock-frequency : specify subnode's clock if needed.
it can be specified via "clocks" if system has
clock node (= common clock), or "system-clock-frequency"
(if system doens't support common clock)
If a clock is specified, it is
enabled with clk_prepare_enable()
in dai startup() and disabled with
clk_disable_unprepare() in dai
shutdown().
If a clock is specified and a
multiplication factor is given with
mclk-fs, the clock will be set to the
calculated mclk frequency when the
stream starts.
- system-clock-direction-out : specifies clock direction as 'out' on
initialization. It is useful for some aCPUs with
fixed clocks.
-------------------------------------------
Example 1 - single DAI link:
-------------------------------------------
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "VF610-Tower-Sound-Card";
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&dailink0_master>;
simple-audio-card,frame-master = <&dailink0_master>;
simple-audio-card,widgets =
"Microphone", "Microphone Jack",
"Headphone", "Headphone Jack",
"Speaker", "External Speaker";
simple-audio-card,routing =
"MIC_IN", "Microphone Jack",
"Headphone Jack", "HP_OUT",
"External Speaker", "LINE_OUT";
simple-audio-card,cpu {
sound-dai = <&sh_fsi2 0>;
};
dailink0_master: simple-audio-card,codec {
sound-dai = <&ak4648>;
clocks = <&osc>;
};
};
&i2c0 {
ak4648: ak4648@12 {
#sound-dai-cells = <0>;
compatible = "asahi-kasei,ak4648";
reg = <0x12>;
};
};
sh_fsi2: sh_fsi2@ec230000 {
#sound-dai-cells = <1>;
compatible = "renesas,sh_fsi2";
reg = <0xec230000 0x400>;
interrupt-parent = <&gic>;
interrupts = <0 146 0x4>;
};
-------------------------------------------
Example 2 - many DAI links:
-------------------------------------------
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "Cubox Audio";
simple-audio-card,dai-link@0 { /* I2S - HDMI */
reg = <0>;
format = "i2s";
cpu {
sound-dai = <&audio1 0>;
};
codec {
sound-dai = <&tda998x 0>;
};
};
simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */
reg = <1>;
cpu {
sound-dai = <&audio1 1>;
};
codec {
sound-dai = <&tda998x 1>;
};
};
simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */
reg = <2>;
cpu {
sound-dai = <&audio1 1>;
};
codec {
sound-dai = <&spdif_codec>;
};
};
};
-------------------------------------------
Example 3 - route audio from IMX6 SSI2 through TLV320DAC3100 codec
through TPA6130A2 amplifier to headphones:
-------------------------------------------
&i2c0 {
codec: tlv320dac3100@18 {
compatible = "ti,tlv320dac3100";
...
}
amp: tpa6130a2@60 {
compatible = "ti,tpa6130a2";
...
}
}
sound {
compatible = "simple-audio-card";
...
simple-audio-card,widgets =
"Headphone", "Headphone Jack";
simple-audio-card,routing =
"Headphone Jack", "HPLEFT",
"Headphone Jack", "HPRIGHT",
"LEFTIN", "HPL",
"RIGHTIN", "HPR";
simple-audio-card,aux-devs = <&amp>;
simple-audio-card,cpu {
sound-dai = <&ssi2>;
};
simple-audio-card,codec {
sound-dai = <&codec>;
clocks = ...
};
};
-------------------------------------------
Example 4. Sampling Rate Conversion
-------------------------------------------
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "rsnd-ak4643";
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&sndcodec>;
simple-audio-card,frame-master = <&sndcodec>;
simple-audio-card,convert-rate = <48000>;
simple-audio-card,prefix = "ak4642";
simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
"DAI0 Capture", "ak4642 Capture";
sndcpu: simple-audio-card,cpu {
sound-dai = <&rcar_sound>;
};
sndcodec: simple-audio-card,codec {
sound-dai = <&ak4643>;
system-clock-frequency = <11289600>;
};
};
-------------------------------------------
Example 5. 2 CPU 1 Codec (Mixing)
-------------------------------------------
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "rsnd-ak4643";
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&dpcmcpu>;
simple-audio-card,frame-master = <&dpcmcpu>;
simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
"ak4642 Playback", "DAI1 Playback";
dpcmcpu: cpu@0 {
sound-dai = <&rcar_sound 0>;
};
cpu@1 {
sound-dai = <&rcar_sound 1>;
};
codec {
prefix = "ak4642";
sound-dai = <&ak4643>;
clocks = <&audio_clock>;
};
};
-------------------------------------------
Example 6 - many DAI links with DPCM:
-------------------------------------------
CPU0 ------ ak4613
CPU1 ------ PCM3168A-p /* DPCM 1ch/2ch */
CPU2 --/ /* DPCM 3ch/4ch */
CPU3 --/ /* DPCM 5ch/6ch */
CPU4 --/ /* DPCM 7ch/8ch */
CPU5 ------ PCM3168A-c
sound {
compatible = "simple-audio-card";
simple-audio-card,routing =
"pcm3168a Playback", "DAI1 Playback",
"pcm3168a Playback", "DAI2 Playback",
"pcm3168a Playback", "DAI3 Playback",
"pcm3168a Playback", "DAI4 Playback";
simple-audio-card,dai-link@0 {
format = "left_j";
bitclock-master = <&sndcpu0>;
frame-master = <&sndcpu0>;
sndcpu0: cpu {
sound-dai = <&rcar_sound 0>;
};
codec {
sound-dai = <&ak4613>;
};
};
simple-audio-card,dai-link@1 {
format = "i2s";
bitclock-master = <&sndcpu1>;
frame-master = <&sndcpu1>;
convert-channels = <8>; /* TDM Split */
sndcpu1: cpu@0 {
sound-dai = <&rcar_sound 1>;
};
cpu@1 {
sound-dai = <&rcar_sound 2>;
};
cpu@2 {
sound-dai = <&rcar_sound 3>;
};
cpu@3 {
sound-dai = <&rcar_sound 4>;
};
codec {
mclk-fs = <512>;
prefix = "pcm3168a";
dai-tdm-slot-num = <8>;
sound-dai = <&pcm3168a 0>;
};
};
simple-audio-card,dai-link@2 {
format = "i2s";
bitclock-master = <&sndcpu2>;
frame-master = <&sndcpu2>;
sndcpu2: cpu {
sound-dai = <&rcar_sound 5>;
};
codec {
mclk-fs = <512>;
prefix = "pcm3168a";
sound-dai = <&pcm3168a 1>;
};
};
};
This diff is collapsed.
......@@ -63,6 +63,55 @@ properties:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [0, 1, 2]
ti,pdm-edge-select:
description: |
Defines the PDMCLK sampling edge configuration for the PDM inputs. This
array is defined as <PDMIN1 PDMIN2 PDMIN3 PDMIN4>.
0 - (default) Odd channel is latched on the negative edge and even
channel is latched on the the positive edge.
1 - Odd channel is latched on the positive edge and even channel is
latched on the the negative edge.
PDMIN1 - PDMCLK latching edge used for channel 1 and 2 data
PDMIN2 - PDMCLK latching edge used for channel 3 and 4 data
PDMIN3 - PDMCLK latching edge used for channel 5 and 6 data
PDMIN4 - PDMCLK latching edge used for channel 7 and 8 data
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- minItems: 1
maxItems: 4
items:
maximum: 1
default: [0, 0, 0, 0]
ti,gpi-config:
description: |
Defines the configuration for the general purpose input pins (GPI).
The array is defined as <GPI1 GPI2 GPI3 GPI4>.
0 - (default) disabled
1 - GPIX is configured as a general-purpose input (GPI)
2 - GPIX is configured as a master clock input (MCLK)
3 - GPIX is configured as an ASI input for daisy-chain (SDIN)
4 - GPIX is configured as a PDM data input for channel 1 and channel
(PDMDIN1)
5 - GPIX is configured as a PDM data input for channel 3 and channel
(PDMDIN2)
6 - GPIX is configured as a PDM data input for channel 5 and channel
(PDMDIN3)
7 - GPIX is configured as a PDM data input for channel 7 and channel
(PDMDIN4)
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- minItems: 1
maxItems: 4
items:
maximum: 7
default: [0, 0, 0, 0]
required:
- compatible
- reg
......@@ -77,6 +126,8 @@ examples:
compatible = "ti,tlv320adc5140";
reg = <0x4c>;
ti,mic-bias-source = <6>;
ti,pdm-edge-select = <0 1 0 1>;
ti,gpi-config = <4 5 6 7>;
reset-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
};
};
......@@ -14,9 +14,15 @@ Required properties:
- #gpio-cells : Must be 2. The first cell is the pin number and the
second cell is used to specify optional parameters (currently unused).
- AVDD2-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, CPVDD-supply,
SPKVDD1-supply, SPKVDD2-supply : power supplies for the device, as covered
in Documentation/devicetree/bindings/regulator/regulator.txt
- power supplies for the device, as covered in
Documentation/devicetree/bindings/regulator/regulator.txt, depending
on compatible:
- for wlf,wm1811 and wlf,wm8958:
AVDD1-supply, AVDD2-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply,
DCVDD-supply, CPVDD-supply, SPKVDD1-supply, SPKVDD2-supply
- for wlf,wm8994:
AVDD1-supply, AVDD2-supply, DBVDD-supply, DCVDD-supply, CPVDD-supply,
SPKVDD1-supply, SPKVDD2-supply
Optional properties:
......@@ -73,11 +79,11 @@ wm8994: codec@1a {
lineout1-se;
AVDD1-supply = <&regulator>;
AVDD2-supply = <&regulator>;
CPVDD-supply = <&regulator>;
DBVDD1-supply = <&regulator>;
DBVDD2-supply = <&regulator>;
DBVDD3-supply = <&regulator>;
DBVDD-supply = <&regulator>;
DCVDD-supply = <&regulator>;
SPKVDD1-supply = <&regulator>;
SPKVDD2-supply = <&regulator>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/zl38060.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ZL38060 Connected Home Audio Processor from Microsemi.
description: |
The ZL38060 is a "Connected Home Audio Processor" from Microsemi,
which consists of a Digital Signal Processor (DSP), several Digital
Audio Interfaces (DAIs), analog outputs, and a block of 14 GPIOs.
maintainers:
- Jaroslav Kysela <perex@perex.cz>
- Takashi Iwai <tiwai@suse.com>
properties:
compatible:
const: mscc,zl38060
reg:
description:
SPI device address.
maxItems: 1
spi-max-frequency:
maximum: 24000000
reset-gpios:
description:
A GPIO line handling reset of the chip. As the line is active low,
it should be marked GPIO_ACTIVE_LOW (see ../gpio/gpio.txt)
maxItems: 1
'#gpio-cells':
const: 2
gpio-controller: true
'#sound-dai-cells':
const: 0
required:
- compatible
- reg
- '#gpio-cells'
- gpio-controller
- '#sound-dai-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
spi0 {
#address-cells = <1>;
#size-cells = <0>;
codec: zl38060@0 {
gpio-controller;
#gpio-cells = <2>;
#sound-dai-cells = <0>;
compatible = "mscc,zl38060";
reg = <0>;
spi-max-frequency = <12000000>;
reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
};
};
......@@ -669,11 +669,11 @@ static int sdw_stream_setup(struct snd_pcm_substream *substream,
/* Set stream pointer on all CODEC DAIs */
for (i = 0; i < rtd->num_codecs; i++) {
ret = snd_soc_dai_set_sdw_stream(rtd->codec_dais[i], sdw_stream,
ret = snd_soc_dai_set_sdw_stream(asoc_rtd_to_codec(rtd, i), sdw_stream,
substream->stream);
if (ret < 0) {
dev_err(dai->dev, "failed to set stream pointer on codec dai %s",
rtd->codec_dais[i]->name);
asoc_rtd_to_codec(rtd, i)->name);
goto release_stream;
}
}
......
......@@ -75,7 +75,7 @@ struct snd_kcontrol {
unsigned long private_value;
void *private_data;
void (*private_free)(struct snd_kcontrol *kcontrol);
struct snd_kcontrol_volatile vd[0]; /* volatile data */
struct snd_kcontrol_volatile vd[]; /* volatile data */
};
#define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list)
......
......@@ -288,6 +288,10 @@ struct hda_codec {
#define dev_to_hda_codec(_dev) container_of(_dev, struct hda_codec, core.dev)
#define hda_codec_dev(_dev) (&(_dev)->core.dev)
#define hdac_to_hda_priv(_hdac) \
container_of(_hdac, struct hdac_hda_priv, codec.core)
#define hdac_to_hda_codec(_hdac) container_of(_hdac, struct hda_codec, core)
#define list_for_each_codec(c, bus) \
list_for_each_entry(c, &(bus)->core.codec_list, core.list)
#define list_for_each_codec_safe(c, n, bus) \
......@@ -362,13 +366,6 @@ struct hda_verb {
void snd_hda_sequence_write(struct hda_codec *codec,
const struct hda_verb *seq);
/* unsolicited event */
static inline void
snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
{
snd_hdac_bus_queue_event(&bus->core, res, res_ex);
}
/* cached write */
static inline int
snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
......
......@@ -207,8 +207,8 @@ static inline int snd_hdac_power_down_pm(struct hdac_device *codec) { return 0;
static inline int snd_hdac_keep_power_up(struct hdac_device *codec) { return 0; }
static inline void snd_hdac_enter_pm(struct hdac_device *codec) {}
static inline void snd_hdac_leave_pm(struct hdac_device *codec) {}
static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return 0; }
static inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return 1; }
static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return false; }
static inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return true; }
#endif
/*
......@@ -364,16 +364,16 @@ struct hdac_bus {
/* link management */
struct list_head hlink_list;
bool cmd_dma_state;
/* factor used to derive STRIPE control value */
unsigned int sdo_limit;
};
int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops);
void snd_hdac_bus_exit(struct hdac_bus *bus);
int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr,
unsigned int cmd, unsigned int *res);
int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr,
unsigned int cmd, unsigned int *res);
void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex);
static inline void snd_hdac_codec_link_up(struct hdac_device *codec)
{
......
......@@ -50,7 +50,7 @@ enum nhlt_device_type {
struct nhlt_specific_cfg {
u32 size;
u8 caps[0];
u8 caps[];
} __packed;
struct nhlt_fmt_cfg {
......@@ -60,7 +60,7 @@ struct nhlt_fmt_cfg {
struct nhlt_fmt {
u8 fmt_count;
struct nhlt_fmt_cfg fmt_config[0];
struct nhlt_fmt_cfg fmt_config[];
} __packed;
struct nhlt_endpoint {
......@@ -80,7 +80,7 @@ struct nhlt_endpoint {
struct nhlt_acpi_table {
struct acpi_table_header header;
u8 endpoint_count;
struct nhlt_endpoint desc[0];
struct nhlt_endpoint desc[];
} __packed;
struct nhlt_resource_desc {
......
/* SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0-only
*
* Copyright (C) 2013-15, Intel Corporation. All rights reserved.
*/
......
/* SPDX-License-Identifier: GPL-2.0
*
* soc-card.h
*
* Copyright (C) 2019 Renesas Electronics Corp.
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*/
#ifndef __SOC_CARD_H
#define __SOC_CARD_H
enum snd_soc_card_subclass {
SND_SOC_CARD_CLASS_INIT = 0,
SND_SOC_CARD_CLASS_RUNTIME = 1,
};
struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
const char *name);
int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
struct snd_soc_jack *jack,
struct snd_soc_jack_pin *pins, unsigned int num_pins);
int snd_soc_card_suspend_pre(struct snd_soc_card *card);
int snd_soc_card_suspend_post(struct snd_soc_card *card);
int snd_soc_card_resume_pre(struct snd_soc_card *card);
int snd_soc_card_resume_post(struct snd_soc_card *card);
int snd_soc_card_probe(struct snd_soc_card *card);
int snd_soc_card_late_probe(struct snd_soc_card *card);
int snd_soc_card_remove(struct snd_soc_card *card);
int snd_soc_card_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level);
int snd_soc_card_set_bias_level_post(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level);
int snd_soc_card_add_dai_link(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link);
void snd_soc_card_remove_dai_link(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link);
/* device driver data */
static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
void *data)
{
card->drvdata = data;
}
static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card)
{
return card->drvdata;
}
static inline
struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card,
const char *dai_name)
{
struct snd_soc_pcm_runtime *rtd;
for_each_card_rtds(card, rtd) {
if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name))
return asoc_rtd_to_codec(rtd, 0);
}
return NULL;
}
#endif /* __SOC_CARD_H */
......@@ -25,6 +25,44 @@
order++)
/* component interface */
struct snd_compress_ops {
int (*open)(struct snd_soc_component *component,
struct snd_compr_stream *stream);
int (*free)(struct snd_soc_component *component,
struct snd_compr_stream *stream);
int (*set_params)(struct snd_soc_component *component,
struct snd_compr_stream *stream,
struct snd_compr_params *params);
int (*get_params)(struct snd_soc_component *component,
struct snd_compr_stream *stream,
struct snd_codec *params);
int (*set_metadata)(struct snd_soc_component *component,
struct snd_compr_stream *stream,
struct snd_compr_metadata *metadata);
int (*get_metadata)(struct snd_soc_component *component,
struct snd_compr_stream *stream,
struct snd_compr_metadata *metadata);
int (*trigger)(struct snd_soc_component *component,
struct snd_compr_stream *stream, int cmd);
int (*pointer)(struct snd_soc_component *component,
struct snd_compr_stream *stream,
struct snd_compr_tstamp *tstamp);
int (*copy)(struct snd_soc_component *component,
struct snd_compr_stream *stream, char __user *buf,
size_t count);
int (*mmap)(struct snd_soc_component *component,
struct snd_compr_stream *stream,
struct vm_area_struct *vma);
int (*ack)(struct snd_soc_component *component,
struct snd_compr_stream *stream, size_t bytes);
int (*get_caps)(struct snd_soc_component *component,
struct snd_compr_stream *stream,
struct snd_compr_caps *caps);
int (*get_codec_caps)(struct snd_soc_component *component,
struct snd_compr_stream *stream,
struct snd_compr_codec_caps *codec);
};
struct snd_soc_component_driver {
const char *name;
......@@ -108,7 +146,7 @@ struct snd_soc_component_driver {
struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
const struct snd_compr_ops *compr_ops;
const struct snd_compress_ops *compress_ops;
/* probe ordering - for components with runtime dependencies */
int probe_order;
......@@ -351,10 +389,10 @@ static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c)
return dev_get_drvdata(c->dev);
}
static inline bool snd_soc_component_is_active(
struct snd_soc_component *component)
static inline unsigned int
snd_soc_component_active(struct snd_soc_component *component)
{
return component->active != 0;
return component->active;
}
/* component pin */
......
......@@ -154,21 +154,59 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream);
void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream);
int snd_soc_dai_prepare(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream);
int snd_soc_dai_trigger(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream, int cmd);
int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream, int cmd);
snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream);
void snd_soc_dai_suspend(struct snd_soc_dai *dai);
void snd_soc_dai_resume(struct snd_soc_dai *dai);
int snd_soc_dai_probe(struct snd_soc_dai *dai);
int snd_soc_dai_remove(struct snd_soc_dai *dai);
int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
struct snd_soc_pcm_runtime *rtd, int num);
bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream);
void snd_soc_dai_action(struct snd_soc_dai *dai,
int stream, int action);
static inline void snd_soc_dai_activate(struct snd_soc_dai *dai,
int stream)
{
snd_soc_dai_action(dai, stream, 1);
}
static inline void snd_soc_dai_deactivate(struct snd_soc_dai *dai,
int stream)
{
snd_soc_dai_action(dai, stream, -1);
}
int snd_soc_dai_active(struct snd_soc_dai *dai);
int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order);
int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order);
int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd);
int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream);
int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd);
int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
int cmd);
int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream);
void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream);
int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream, int cmd);
int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream,
struct snd_compr_params *params);
int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream,
struct snd_codec *params);
int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream,
size_t bytes);
int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream,
struct snd_compr_tstamp *tstamp);
int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream,
struct snd_compr_metadata *metadata);
int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,
struct snd_compr_stream *cstream,
struct snd_compr_metadata *metadata);
struct snd_soc_dai_ops {
/*
......@@ -326,8 +364,6 @@ struct snd_soc_dai {
/* DAI runtime info */
unsigned int stream_active[SNDRV_PCM_STREAM_LAST + 1]; /* usage count */
unsigned int active;
struct snd_soc_dapm_widget *playback_widget;
struct snd_soc_dapm_widget *capture_widget;
......@@ -443,4 +479,10 @@ static inline void *snd_soc_dai_get_sdw_stream(struct snd_soc_dai *dai,
return ERR_PTR(-ENOTSUPP);
}
static inline unsigned int
snd_soc_dai_stream_active(struct snd_soc_dai *dai, int stream)
{
return dai->stream_active[stream];
}
#endif
......@@ -689,7 +689,7 @@ struct snd_soc_dapm_context {
/* A list of widgets associated with an object, typically a snd_kcontrol */
struct snd_soc_dapm_widget_list {
int num_widgets;
struct snd_soc_dapm_widget *widgets[0];
struct snd_soc_dapm_widget *widgets[];
};
#define for_each_dapm_widgets(list, i, widget) \
......
/* SPDX-License-Identifier: GPL-2.0
*
* soc-link.h
*
* Copyright (C) 2019 Renesas Electronics Corp.
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*/
#ifndef __SOC_LINK_H
#define __SOC_LINK_H
int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd);
int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
int snd_soc_link_startup(struct snd_pcm_substream *substream);
void snd_soc_link_shutdown(struct snd_pcm_substream *substream);
int snd_soc_link_prepare(struct snd_pcm_substream *substream);
int snd_soc_link_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
void snd_soc_link_hw_free(struct snd_pcm_substream *substream);
int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd);
int snd_soc_link_compr_startup(struct snd_compr_stream *cstream);
void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream);
int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream);
#endif /* __SOC_LINK_H */
......@@ -414,11 +414,6 @@ enum snd_soc_pcm_subclass {
SND_SOC_PCM_CLASS_BE = 1,
};
enum snd_soc_card_subclass {
SND_SOC_CARD_CLASS_INIT = 0,
SND_SOC_CARD_CLASS_RUNTIME = 1,
};
int snd_soc_register_card(struct snd_soc_card *card);
int snd_soc_unregister_card(struct snd_soc_card *card);
int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card);
......@@ -468,8 +463,19 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link);
bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd);
void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream);
void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream);
void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd,
int stream, int action);
static inline void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd,
int stream)
{
snd_soc_runtime_action(rtd, stream, 1);
}
static inline void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd,
int stream)
{
snd_soc_runtime_action(rtd, stream, -1);
}
int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hardware *hw, int stream);
......@@ -498,10 +504,6 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
const struct snd_pcm_hardware *hw);
/* Jack reporting */
int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins,
unsigned int num_pins);
void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_pin *pins);
......@@ -571,8 +573,6 @@ static inline int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops)
struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
void *data, const char *long_name,
const char *prefix);
struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
const char *name);
int snd_soc_add_component_controls(struct snd_soc_component *component,
const struct snd_kcontrol_new *controls, unsigned int num_controls);
int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
......@@ -790,9 +790,6 @@ struct snd_soc_dai_link {
const struct snd_soc_pcm_stream *params;
unsigned int num_params;
struct snd_soc_dapm_widget *playback_widget;
struct snd_soc_dapm_widget *capture_widget;
unsigned int dai_fmt; /* format to set on init */
enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */
......@@ -809,7 +806,7 @@ struct snd_soc_dai_link {
const struct snd_soc_compr_ops *compr_ops;
/* Mark this pcm with non atomic ops */
bool nonatomic;
unsigned int nonatomic:1;
/* For unidirectional dai links */
unsigned int playback_only:1;
......@@ -1005,9 +1002,6 @@ struct snd_soc_card {
spinlock_t dpcm_lock;
bool instantiated;
bool topology_shortname_created;
int (*probe)(struct snd_soc_card *card);
int (*late_probe)(struct snd_soc_card *card);
int (*remove)(struct snd_soc_card *card);
......@@ -1068,8 +1062,6 @@ struct snd_soc_card {
int num_of_dapm_widgets;
const struct snd_soc_dapm_route *of_dapm_routes;
int num_of_dapm_routes;
bool fully_routed;
bool disable_route_checks;
/* lists of probed devices belonging to this card */
struct list_head component_dev_list;
......@@ -1096,6 +1088,13 @@ struct snd_soc_card {
#endif
u32 pop_time;
/* bit field */
unsigned int instantiated:1;
unsigned int topology_shortname_created:1;
unsigned int fully_routed:1;
unsigned int disable_route_checks:1;
unsigned int probed:1;
void *drvdata;
};
#define for_each_card_prelinks(card, i, link) \
......@@ -1146,16 +1145,21 @@ struct snd_soc_pcm_runtime {
/* runtime devices */
struct snd_pcm *pcm;
struct snd_compr *compr;
struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai;
struct snd_soc_dai **dais;
struct snd_soc_dai **codec_dais;
/*
* dais = cpu_dai + codec_dai
* see
* soc_new_pcm_runtime()
* asoc_rtd_to_cpu()
* asoc_rtd_to_codec()
*/
struct snd_soc_dai **dais;
unsigned int num_codecs;
struct snd_soc_dai **cpu_dais;
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);
#ifdef CONFIG_DEBUG_FS
......@@ -1170,28 +1174,28 @@ struct snd_soc_pcm_runtime {
unsigned int fe_compr:1; /* for Dynamic PCM */
int num_components;
struct snd_soc_component *components[0]; /* CPU/Codec/Platform */
struct snd_soc_component *components[]; /* CPU/Codec/Platform */
};
/* 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 for_each_rtd_components(rtd, i, component) \
for ((i) = 0; \
for ((i) = 0, component = NULL; \
((i) < rtd->num_components) && ((component) = rtd->components[i]);\
(i)++)
#define for_each_rtd_cpu_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < rtd->num_cpus) && ((dai) = rtd->cpu_dais[i]); \
((i) < rtd->num_cpus) && ((dai) = asoc_rtd_to_cpu(rtd, i)); \
(i)++)
#define for_each_rtd_cpu_dais_rollback(rtd, i, dai) \
for (; (--(i) >= 0) && ((dai) = rtd->cpu_dais[i]);)
for (; (--(i) >= 0) && ((dai) = asoc_rtd_to_cpu(rtd, i));)
#define for_each_rtd_codec_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \
((i) < rtd->num_codecs) && ((dai) = asoc_rtd_to_codec(rtd, i)); \
(i)++)
#define for_each_rtd_codec_dais_rollback(rtd, i, dai) \
for (; (--(i) >= 0) && ((dai) = rtd->codec_dais[i]);)
for (; (--(i) >= 0) && ((dai) = asoc_rtd_to_codec(rtd, i));)
#define for_each_rtd_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \
......@@ -1252,29 +1256,16 @@ struct soc_enum {
#endif
};
/* device driver data */
static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
void *data)
{
card->drvdata = data;
}
static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card)
{
return card->drvdata;
}
static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
{
if (mc->reg == mc->rreg && mc->shift == mc->rshift)
return 0;
return false;
/*
* mc->reg == mc->rreg && mc->shift != mc->rshift, or
* mc->reg != mc->rreg means that the control is
* stereo (bits in one register or in two registers)
*/
return 1;
return true;
}
static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e,
......@@ -1377,20 +1368,6 @@ struct snd_soc_dai *snd_soc_find_dai(
#include <sound/soc-dai.h>
static inline
struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card,
const char *dai_name)
{
struct snd_soc_pcm_runtime *rtd;
list_for_each_entry(rtd, &card->rtd_list, list) {
if (!strcmp(rtd->codec_dai->name, dai_name))
return rtd->codec_dai;
}
return NULL;
}
static inline
int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card,
const char *platform_name)
......@@ -1436,5 +1413,6 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm)
}
#include <sound/soc-component.h>
#include <sound/soc-card.h>
#endif
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......@@ -27,6 +27,9 @@ struct snd_sof_pdata {
struct device *dev;
/* indicate how many first bytes shouldn't be loaded into DSP memory. */
size_t fw_offset;
/*
* notification callback used if the hardware initialization
* can take time or is handled in a workqueue. This callback
......
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* Copyright 2019 NXP
*
......
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......@@ -49,6 +49,9 @@
/* bclk idle */
#define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH BIT(5)
/* DMIC max. four controllers for eight microphone channels */
#define SOF_DAI_INTEL_DMIC_NUM_CTRL 4
/* SSP Configuration Request - SOF_IPC_DAI_SSP_CONFIG */
struct sof_ipc_dai_ssp_params {
struct sof_ipc_hdr hdr;
......@@ -85,15 +88,19 @@ struct sof_ipc_dai_ssp_params {
struct sof_ipc_dai_hda_params {
struct sof_ipc_hdr hdr;
uint32_t link_dma_ch;
uint32_t rate;
uint32_t channels;
} __packed;
/* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */
struct sof_ipc_dai_alh_params {
struct sof_ipc_hdr hdr;
uint32_t stream_id;
uint32_t rate;
uint32_t channels;
/* reserved for future use */
uint32_t reserved[15];
uint32_t reserved[13];
} __packed;
/* DMIC Configuration Request - SOF_IPC_DAI_DMIC_CONFIG */
......@@ -135,7 +142,7 @@ struct sof_ipc_dai_dmic_pdm_ctrl {
* version number used in configuration data is checked vs. version used by
* device driver src/drivers/dmic.c need to match. It is incremented from
* initial value 1 if updates done for the to driver would alter the operation
* of the microhone.
* of the microphone.
*
* Note: The microphone clock (pdmclk_min, pdmclk_max, duty_min, duty_max)
* parameters need to be set as defined in microphone data sheet. E.g. clock
......@@ -170,12 +177,13 @@ struct sof_ipc_dai_dmic_params {
uint32_t fifo_fs; /**< FIFO sample rate in Hz (8000..96000) */
uint32_t reserved_1; /**< Reserved */
uint16_t fifo_bits; /**< FIFO word length (16 or 32) */
uint16_t reserved_2; /**< Reserved */
uint16_t fifo_bits_b; /**< Deprecated since firmware ABI 3.0.1 */
uint16_t duty_min; /**< Min. mic clock duty cycle in % (20..80) */
uint16_t duty_max; /**< Max. mic clock duty cycle in % (min..80) */
uint32_t num_pdm_active; /**< Number of active pdm controllers */
uint32_t num_pdm_active; /**< Number of active pdm controllers. */
/**< Range is 1..SOF_DAI_INTEL_DMIC_NUM_CTRL */
uint32_t wake_up_time; /**< Time from clock start to data (us) */
uint32_t min_clock_on_time; /**< Min. time that clk is kept on (us) */
......@@ -184,8 +192,8 @@ struct sof_ipc_dai_dmic_params {
/* reserved for future use */
uint32_t reserved[5];
/**< variable number of pdm controller config */
struct sof_ipc_dai_dmic_pdm_ctrl pdm[0];
/**< PDM controllers configuration */
struct sof_ipc_dai_dmic_pdm_ctrl pdm[SOF_DAI_INTEL_DMIC_NUM_CTRL];
} __packed;
#endif
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2020 Intel Corporation. All rights reserved.
*/
/*
* Extended manifest is a place to store metadata about firmware, known during
* compilation time - for example firmware version or used compiler.
* Given information are read on host side before firmware startup.
* This part of output binary is not signed.
*/
#ifndef __SOF_FIRMWARE_EXT_MANIFEST_H__
#define __SOF_FIRMWARE_EXT_MANIFEST_H__
#include <linux/bits.h>
#include <linux/compiler.h>
#include <linux/types.h>
#include <sound/sof/info.h>
/* In ASCII `XMan` */
#define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58
/* Build u32 number in format MMmmmppp */
#define SOF_EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ((uint32_t)( \
((MAJOR) << 24) | \
((MINOR) << 12) | \
(PATH)))
/* check extended manifest version consistency */
#define SOF_EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \
((host_ver) & GENMASK(31, 24)) != \
((cli_ver) & GENMASK(31, 24)))
/* used extended manifest header version */
#define SOF_EXT_MAN_VERSION SOF_EXT_MAN_BUILD_VERSION(1, 0, 0)
/* extended manifest header, deleting any field breaks backward compatibility */
struct sof_ext_man_header {
uint32_t magic; /*< identification number, */
/*< EXT_MAN_MAGIC_NUMBER */
uint32_t full_size; /*< [bytes] full size of ext_man, */
/*< (header + content + padding) */
uint32_t header_size; /*< [bytes] makes header extensionable, */
/*< after append new field to ext_man header */
/*< then backward compatible won't be lost */
uint32_t header_version; /*< value of EXT_MAN_VERSION */
/*< not related with following content */
/* just after this header should be list of ext_man_elem_* elements */
} __packed;
/* Now define extended manifest elements */
/* Extended manifest elements types */
enum sof_ext_man_elem_type {
SOF_EXT_MAN_ELEM_FW_VERSION = 0,
SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW,
SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO,
};
/* extended manifest element header */
struct sof_ext_man_elem_header {
uint32_t type; /*< SOF_EXT_MAN_ELEM_ */
uint32_t size; /*< in bytes, including header size */
/* just after this header should be type dependent content */
} __packed;
/* FW version */
struct sof_ext_man_fw_version {
struct sof_ext_man_elem_header hdr;
/* use sof_ipc struct because of code re-use */
struct sof_ipc_fw_version version;
uint32_t flags;
} __packed;
/* extended data memory windows for IPC, trace and debug */
struct sof_ext_man_window {
struct sof_ext_man_elem_header hdr;
/* use sof_ipc struct because of code re-use */
struct sof_ipc_window ipc_window;
} __packed;
/* Used C compiler description */
struct sof_ext_man_cc_version {
struct sof_ext_man_elem_header hdr;
/* use sof_ipc struct because of code re-use */
struct sof_ipc_cc_version cc_version;
} __packed;
#endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......@@ -31,6 +31,8 @@ enum sof_ipc_ext_data {
SOF_IPC_EXT_UNUSED = 0,
SOF_IPC_EXT_WINDOW = 1,
SOF_IPC_EXT_CC_INFO = 2,
SOF_IPC_EXT_PROBE_INFO = 3,
SOF_IPC_EXT_USER_ABI_INFO = 4,
};
/* FW version - SOF_IPC_GLB_VERSION */
......@@ -109,9 +111,27 @@ struct sof_ipc_cc_version {
/* reserved for future use */
uint32_t reserved[4];
char name[16]; /* null terminated compiler name */
char optim[4]; /* null terminated compiler -O flag value */
char desc[]; /* null terminated compiler description */
uint8_t name[16]; /* null terminated compiler name */
uint8_t optim[4]; /* null terminated compiler -O flag value */
uint8_t desc[32]; /* null terminated compiler description */
} __packed;
/* extended data: Probe setup */
struct sof_ipc_probe_support {
struct sof_ipc_ext_data_hdr ext_hdr;
uint32_t probe_points_max;
uint32_t injection_dmas_max;
/* reserved for future use */
uint32_t reserved[2];
} __packed;
/* extended data: user abi version(s) */
struct sof_ipc_user_abi_version {
struct sof_ipc_ext_data_hdr ext_hdr;
uint32_t abi_dbg_version;
} __packed;
#endif
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......@@ -37,6 +37,8 @@ enum sof_comp_type {
SOF_COMP_SELECTOR, /**< channel selector component */
SOF_COMP_DEMUX,
SOF_COMP_ASRC, /**< Asynchronous sample rate converter */
SOF_COMP_DCBLOCK,
SOF_COMP_SMART_AMP, /**< smart amplifier component */
/* keep FILEREAD/FILEWRITE as the last ones */
SOF_COMP_FILEREAD = 10000, /**< host test based file IO */
SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */
......@@ -75,11 +77,23 @@ struct sof_ipc_comp {
#define SOF_MEM_CAPS_CACHE (1 << 6) /**< cacheable */
#define SOF_MEM_CAPS_EXEC (1 << 7) /**< executable */
/*
* overrun will cause ring buffer overwrite, instead of XRUN.
*/
#define SOF_BUF_OVERRUN_PERMITTED BIT(0)
/*
* underrun will cause readback of 0s, instead of XRUN.
*/
#define SOF_BUF_UNDERRUN_PERMITTED BIT(1)
/* create new component buffer - SOF_IPC_TPLG_BUFFER_NEW */
struct sof_ipc_buffer {
struct sof_ipc_comp comp;
uint32_t size; /**< buffer size in bytes */
uint32_t caps; /**< SOF_MEM_CAPS_ */
uint32_t flags; /**< SOF_BUF_ flags defined above */
uint32_t reserved; /**< reserved for future use */
} __packed;
/* generic component config data - must always be after struct sof_ipc_comp */
......@@ -206,6 +220,8 @@ enum sof_ipc_process_type {
SOF_PROCESS_CHAN_SELECTOR, /**< Channel Selector */
SOF_PROCESS_MUX,
SOF_PROCESS_DEMUX,
SOF_PROCESS_DCBLOCK,
SOF_PROCESS_SMART_AMP, /**< Smart Amplifier */
};
/* generic "effect", "codec" or proprietary processing component */
......@@ -218,7 +234,7 @@ struct sof_ipc_comp_process {
/* reserved for future use */
uint32_t reserved[7];
unsigned char data[0];
uint8_t data[0];
} __packed;
/* frees components, buffers and pipelines
......
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......@@ -72,7 +72,7 @@ struct sof_ipc_dma_trace_posn {
struct sof_ipc_panic_info {
struct sof_ipc_hdr hdr;
uint32_t code; /* SOF_IPC_PANIC_ */
char filename[SOF_TRACE_FILENAME_SIZE];
uint8_t filename[SOF_TRACE_FILENAME_SIZE];
uint32_t linenum;
} __packed;
......
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
......
......@@ -18,6 +18,8 @@
*/
#define SKL_CONTROL_TYPE_BYTE_TLV 0x100
#define SKL_CONTROL_TYPE_MIC_SELECT 0x102
#define SKL_CONTROL_TYPE_MULTI_IO_SELECT 0x103
#define SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC 0x104
#define HDA_SST_CFG_MAX 900 /* size of copier cfg*/
#define MAX_IN_QUEUE 8
......
......@@ -26,7 +26,7 @@
/* SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3
#define SOF_ABI_MINOR 13
#define SOF_ABI_MINOR 16
#define SOF_ABI_PATCH 0
/* SOF ABI version number. Format within 32bit word is MMmmmppp */
......
......@@ -126,4 +126,12 @@
#define SOF_TKN_MUTE_LED_USE 1300
#define SOF_TKN_MUTE_LED_DIRECTION 1301
/* ALH */
#define SOF_TKN_INTEL_ALH_RATE 1400
#define SOF_TKN_INTEL_ALH_CH 1401
/* HDA */
#define SOF_TKN_INTEL_HDA_RATE 1500
#define SOF_TKN_INTEL_HDA_CH 1501
#endif
......@@ -64,7 +64,7 @@ struct snd_pcm_plugin {
char *buf;
snd_pcm_uframes_t buf_frames;
struct snd_pcm_plugin_channel *buf_channels;
char extra_data[0];
char extra_data[];
};
int snd_pcm_plugin_build(struct snd_pcm_substream *handle,
......
......@@ -44,14 +44,4 @@ snd_seq_oss_timer_cur_tick(struct seq_oss_timer *timer)
return timer->cur_tick;
}
/*
* is realtime event?
*/
static inline int
snd_seq_oss_timer_is_realtime(struct seq_oss_timer *timer)
{
return timer->realtime;
}
#endif
......@@ -457,7 +457,7 @@ static int portman_probe(struct parport *p)
/* Set for RXDATA0 where no damage will be done. */
/* 5 */
parport_write_control(p, RXDATA0 + STROBE); /* Write Strobe=1 to command reg. */
parport_write_control(p, RXDATA0 | STROBE); /* Write Strobe=1 to command reg. */
/* 6 */
if ((parport_read_status(p) & ESTB) != ESTB)
......
......@@ -150,8 +150,12 @@ config SND_FIREWIRE_MOTU
Say Y here to enable support for FireWire devices which MOTU produced:
* 828mk2
* Traveler
* 828mk3
* Ultralite
* 8pre
* 828mk3 (FireWire only)
* 828mk3 (Hybrid)
* Audio Express
* 4pre
To compile this driver as a module, choose M here: the module
will be called snd-firewire-motu.
......@@ -164,6 +168,8 @@ config SND_FIREFACE
Say Y here to include support for RME fireface series.
* Fireface 400
* Fireface 800
* Fireface UFX
* Fireface UCX
* Fireface 802
endif # SND_FIREWIRE
......@@ -82,6 +82,7 @@ int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate,
if (err < 0)
return err;
if (s->direction == AMDTP_OUT_STREAM)
s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc;
p->pcm_channels = pcm_channels;
......
This diff is collapsed.
......@@ -108,6 +108,8 @@ typedef unsigned int (*amdtp_stream_process_ctx_payloads_t)(
const struct pkt_desc *desc,
unsigned int packets,
struct snd_pcm_substream *pcm);
struct amdtp_domain;
struct amdtp_stream {
struct fw_unit *unit;
enum cip_flags flags;
......@@ -136,9 +138,7 @@ struct amdtp_stream {
struct {
// To calculate CIP data blocks and tstamp.
unsigned int transfer_delay;
unsigned int data_block_state;
unsigned int last_syt_offset;
unsigned int syt_offset_state;
unsigned int seq_index;
// To generate CIP header.
unsigned int fdf;
......@@ -180,6 +180,7 @@ struct amdtp_stream {
int channel;
int speed;
struct list_head list;
struct amdtp_domain *domain;
};
int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
......@@ -273,6 +274,11 @@ static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s,
msecs_to_jiffies(timeout)) > 0;
}
struct seq_desc {
unsigned int syt_offset;
unsigned int data_blocks;
};
struct amdtp_domain {
struct list_head streams;
......@@ -280,6 +286,14 @@ struct amdtp_domain {
unsigned int events_per_buffer;
struct amdtp_stream *irq_target;
struct seq_desc *seq_descs;
unsigned int seq_size;
unsigned int seq_tail;
unsigned int data_block_state;
unsigned int syt_offset_state;
unsigned int last_syt_offset;
};
int amdtp_domain_init(struct amdtp_domain *d);
......
......@@ -16,7 +16,8 @@
#define LATTER_SYNC_STATUS 0x0000801c0000ULL
static int parse_clock_bits(u32 data, unsigned int *rate,
enum snd_ff_clock_src *src)
enum snd_ff_clock_src *src,
enum snd_ff_unit_version unit_version)
{
static const struct {
unsigned int rate;
......@@ -43,6 +44,11 @@ static int parse_clock_bits(u32 data, unsigned int *rate,
};
int i;
if (unit_version != SND_FF_UNIT_VERSION_UCX) {
// e.g. 0x00fe0f20 but expected 0x00eff002.
data = ((data & 0xf0f0f0f0) >> 4) | ((data & 0x0f0f0f0f) << 4);
}
for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {
rate_entry = rate_entries + i;
if ((data & 0x0f000000) == rate_entry->flag) {
......@@ -79,7 +85,7 @@ static int latter_get_clock(struct snd_ff *ff, unsigned int *rate,
return err;
data = le32_to_cpu(reg);
return parse_clock_bits(data, rate, src);
return parse_clock_bits(data, rate, src, ff->unit_version);
}
static int latter_switch_fetching_mode(struct snd_ff *ff, bool enable)
......@@ -107,18 +113,18 @@ static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate)
int err;
// Set the number of data blocks transferred in a second.
if (rate % 32000 == 0)
code = 0x00;
if (rate % 48000 == 0)
code = 0x04;
else if (rate % 44100 == 0)
code = 0x02;
else if (rate % 48000 == 0)
code = 0x04;
else if (rate % 32000 == 0)
code = 0x00;
else
return -EINVAL;
if (rate >= 64000 && rate < 128000)
code |= 0x08;
else if (rate >= 128000 && rate < 192000)
else if (rate >= 128000)
code |= 0x10;
reg = cpu_to_le32(code);
......@@ -140,7 +146,7 @@ static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate)
if (curr_rate == rate)
break;
}
if (count == 10)
if (count > 10)
return -ETIMEDOUT;
for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); ++i) {
......@@ -181,6 +187,9 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
__le32 reg;
int err;
if (ff->unit_version == SND_FF_UNIT_VERSION_UCX) {
// For Fireface UCX. Always use the maximum number of data
// channels in data block of packet.
if (rate >= 32000 && rate <= 48000)
flag = 0x92;
else if (rate >= 64000 && rate <= 96000)
......@@ -189,6 +198,19 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
flag = 0x8c;
else
return -EINVAL;
} else {
// For Fireface UFX and 802. Due to bandwidth limitation on
// IEEE 1394a (400 Mbps), Analog 1-12 and AES are available
// without any ADAT at quadruple speed.
if (rate >= 32000 && rate <= 48000)
flag = 0x9e;
else if (rate >= 64000 && rate <= 96000)
flag = 0x96;
else if (rate >= 128000 && rate <= 192000)
flag = 0x8e;
else
return -EINVAL;
}
if (generation != fw_parent_device(ff->unit)->card->generation) {
err = fw_iso_resources_update(&ff->tx_resources);
......@@ -207,8 +229,6 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
if (err < 0)
return err;
// Always use the maximum number of data channels in data block of
// packet.
reg = cpu_to_le32(flag);
return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
LATTER_ISOC_START, &reg, sizeof(reg), 0);
......@@ -263,7 +283,7 @@ static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer
}
}
err = parse_clock_bits(data, &rate, &src);
err = parse_clock_bits(data, &rate, &src, ff->unit_version);
if (err < 0)
return;
label = snd_ff_proc_get_clk_label(src);
......
......@@ -184,7 +184,6 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
*/
if (!amdtp_stream_running(&ff->rx_stream)) {
int spd = fw_parent_device(ff->unit)->max_speed;
unsigned int ir_delay_cycle;
err = ff->spec->protocol->begin_session(ff, rate);
if (err < 0)
......@@ -200,14 +199,7 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
if (err < 0)
goto error;
// The device postpones start of transmission mostly for several
// cycles after receiving packets firstly.
if (ff->spec->protocol == &snd_ff_protocol_ff800)
ir_delay_cycle = 800; // = 100 msec
else
ir_delay_cycle = 16; // = 2 msec
err = amdtp_domain_start(&ff->domain, ir_delay_cycle);
err = amdtp_domain_start(&ff->domain, 0);
if (err < 0)
goto error;
......
......@@ -16,12 +16,22 @@ MODULE_LICENSE("GPL v2");
static void name_card(struct snd_ff *ff)
{
struct fw_device *fw_dev = fw_parent_device(ff->unit);
const char *const names[] = {
[SND_FF_UNIT_VERSION_FF800] = "Fireface800",
[SND_FF_UNIT_VERSION_FF400] = "Fireface400",
[SND_FF_UNIT_VERSION_UFX] = "FirefaceUFX",
[SND_FF_UNIT_VERSION_UCX] = "FirefaceUCX",
[SND_FF_UNIT_VERSION_802] = "Fireface802",
};
const char *name;
name = names[ff->unit_version];
strcpy(ff->card->driver, "Fireface");
strcpy(ff->card->shortname, ff->spec->name);
strcpy(ff->card->mixername, ff->spec->name);
strcpy(ff->card->shortname, name);
strcpy(ff->card->mixername, name);
snprintf(ff->card->longname, sizeof(ff->card->longname),
"RME %s, GUID %08x%08x at %s, S%d", ff->spec->name,
"RME %s, GUID %08x%08x at %s, S%d", name,
fw_dev->config_rom[3], fw_dev->config_rom[4],
dev_name(&ff->unit->device), 100 << fw_dev->max_speed);
}
......@@ -101,6 +111,7 @@ static int snd_ff_probe(struct fw_unit *unit,
spin_lock_init(&ff->lock);
init_waitqueue_head(&ff->hwdep_wait);
ff->unit_version = entry->version;
ff->spec = (const struct snd_ff_spec *)entry->driver_data;
/* Register this sound card later. */
......@@ -145,7 +156,6 @@ static void snd_ff_remove(struct fw_unit *unit)
}
static const struct snd_ff_spec spec_ff800 = {
.name = "Fireface800",
.pcm_capture_channels = {28, 20, 12},
.pcm_playback_channels = {28, 20, 12},
.midi_in_ports = 1,
......@@ -157,7 +167,6 @@ static const struct snd_ff_spec spec_ff800 = {
};
static const struct snd_ff_spec spec_ff400 = {
.name = "Fireface400",
.pcm_capture_channels = {18, 14, 10},
.pcm_playback_channels = {18, 14, 10},
.midi_in_ports = 2,
......@@ -169,7 +178,6 @@ static const struct snd_ff_spec spec_ff400 = {
};
static const struct snd_ff_spec spec_ucx = {
.name = "FirefaceUCX",
.pcm_capture_channels = {18, 14, 12},
.pcm_playback_channels = {18, 14, 12},
.midi_in_ports = 2,
......@@ -180,6 +188,17 @@ static const struct snd_ff_spec spec_ucx = {
.midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull},
};
static const struct snd_ff_spec spec_ufx_802 = {
.pcm_capture_channels = {30, 22, 14},
.pcm_playback_channels = {30, 22, 14},
.midi_in_ports = 1,
.midi_out_ports = 1,
.protocol = &snd_ff_protocol_latter,
.midi_high_addr = 0xffff00000034ull,
.midi_addr_range = 0x80,
.midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull},
};
static const struct ieee1394_device_id snd_ff_id_table[] = {
/* Fireface 800 */
{
......@@ -189,7 +208,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_RME,
.specifier_id = OUI_RME,
.version = 0x000001,
.version = SND_FF_UNIT_VERSION_FF800,
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ff800,
},
......@@ -201,10 +220,22 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_RME,
.specifier_id = OUI_RME,
.version = 0x000002,
.version = SND_FF_UNIT_VERSION_FF400,
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ff400,
},
// Fireface UFX.
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_SPECIFIER_ID |
IEEE1394_MATCH_VERSION |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_RME,
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_UFX,
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ufx_802,
},
// Fireface UCX.
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
......@@ -213,10 +244,22 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_RME,
.specifier_id = OUI_RME,
.version = 0x000004,
.version = SND_FF_UNIT_VERSION_UCX,
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ucx,
},
// Fireface 802.
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_SPECIFIER_ID |
IEEE1394_MATCH_VERSION |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_RME,
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_802,
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ufx_802,
},
{}
};
MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table);
......
......@@ -34,6 +34,14 @@
#define SND_FF_IN_MIDI_PORTS 2
#define SND_FF_OUT_MIDI_PORTS 2
enum snd_ff_unit_version {
SND_FF_UNIT_VERSION_FF800 = 0x000001,
SND_FF_UNIT_VERSION_FF400 = 0x000002,
SND_FF_UNIT_VERSION_UFX = 0x000003,
SND_FF_UNIT_VERSION_UCX = 0x000004,
SND_FF_UNIT_VERSION_802 = 0x000005,
};
enum snd_ff_stream_mode {
SND_FF_STREAM_MODE_LOW = 0,
SND_FF_STREAM_MODE_MID,
......@@ -43,8 +51,6 @@ enum snd_ff_stream_mode {
struct snd_ff_protocol;
struct snd_ff_spec {
const char *const name;
const unsigned int pcm_capture_channels[SND_FF_STREAM_MODE_COUNT];
const unsigned int pcm_playback_channels[SND_FF_STREAM_MODE_COUNT];
......@@ -66,6 +72,7 @@ struct snd_ff {
bool registered;
struct delayed_work dwork;
enum snd_ff_unit_version unit_version;
const struct snd_ff_spec *spec;
/* To handle MIDI tx. */
......
......@@ -177,7 +177,7 @@ struct snd_efw_phys_meters {
u32 in_meters;
u32 reserved4;
u32 reserved5;
u32 values[0];
u32 values[];
} __packed;
enum snd_efw_clock_source {
SND_EFW_CLOCK_SOURCE_INTERNAL = 0,
......
......@@ -76,15 +76,11 @@ int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate,
if (i == ARRAY_SIZE(snd_motu_clock_rates))
return -EINVAL;
pcm_chunks = formats->fixed_part_pcm_chunks[mode] +
formats->differed_part_pcm_chunks[mode];
// Each data block includes SPH in its head. Data chunks follow with
// 3 byte alignment. Padding follows with zero to conform to quadlet
// alignment.
pcm_chunks = formats->pcm_chunks[mode];
data_chunks = formats->msg_chunks + pcm_chunks;
/*
* Each data block includes SPH in its head. Data chunks follow with
* 3 byte alignment. Padding follows with zero to conform to quadlet
* alignment.
*/
data_block_quadlets = 1 + DIV_ROUND_UP(data_chunks * 3, 4);
err = amdtp_stream_set_parameters(s, rate, data_block_quadlets);
......@@ -440,7 +436,7 @@ static unsigned int process_it_ctx_payloads(struct amdtp_stream *s,
int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
enum amdtp_stream_direction dir,
const struct snd_motu_protocol *const protocol)
const struct snd_motu_spec *spec)
{
amdtp_stream_process_ctx_payloads_t process_ctx_payloads;
int fmt = CIP_FMT_MOTU;
......@@ -454,14 +450,15 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
* Units of version 3 transmits packets with invalid CIP header
* against IEC 61883-1.
*/
if (protocol == &snd_motu_protocol_v3) {
if (spec->protocol_version == SND_MOTU_PROTOCOL_V3) {
flags |= CIP_WRONG_DBS |
CIP_SKIP_DBC_ZERO_CHECK |
CIP_HEADER_WITHOUT_EOH;
fmt = CIP_FMT_MOTU_TX_V3;
}
if (protocol == &snd_motu_protocol_v2) {
if (spec == &snd_motu_spec_8pre ||
spec == &snd_motu_spec_ultralite) {
// 8pre has some quirks.
flags |= CIP_WRONG_DBS |
CIP_SKIP_DBC_ZERO_CHECK;
......
......@@ -26,8 +26,7 @@ static int motu_rate_constraint(struct snd_pcm_hw_params *params,
rate = snd_motu_clock_rates[i];
mode = i / 2;
pcm_channels = formats->fixed_part_pcm_chunks[mode] +
formats->differed_part_pcm_chunks[mode];
pcm_channels = formats->pcm_chunks[mode];
if (!snd_interval_test(c, pcm_channels))
continue;
......@@ -59,8 +58,7 @@ static int motu_channels_constraint(struct snd_pcm_hw_params *params,
if (!snd_interval_test(r, rate))
continue;
pcm_channels = formats->fixed_part_pcm_chunks[mode] +
formats->differed_part_pcm_chunks[mode];
pcm_channels = formats->pcm_chunks[mode];
channels.min = min(channels.min, pcm_channels);
channels.max = max(channels.max, pcm_channels);
}
......@@ -82,8 +80,7 @@ static void limit_channels_and_rates(struct snd_motu *motu,
rate = snd_motu_clock_rates[i];
mode = i / 2;
pcm_channels = formats->fixed_part_pcm_chunks[mode] +
formats->differed_part_pcm_chunks[mode];
pcm_channels = formats->pcm_chunks[mode];
if (pcm_channels == 0)
continue;
......@@ -133,7 +130,6 @@ static int init_hw_info(struct snd_motu *motu,
static int pcm_open(struct snd_pcm_substream *substream)
{
struct snd_motu *motu = substream->private_data;
const struct snd_motu_protocol *const protocol = motu->spec->protocol;
struct amdtp_domain *d = &motu->domain;
enum snd_motu_clock_source src;
int err;
......@@ -152,7 +148,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
if (err < 0)
goto err_locked;
err = protocol->get_clock_source(motu, &src);
err = snd_motu_protocol_get_clock_source(motu, &src);
if (err < 0)
goto err_locked;
......@@ -166,7 +162,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
unsigned int frames_per_buffer = d->events_per_buffer;
unsigned int rate;
err = protocol->get_clock_rate(motu, &rate);
err = snd_motu_protocol_get_clock_rate(motu, &rate);
if (err < 0)
goto err_locked;
......
......@@ -28,13 +28,12 @@ static void proc_read_clock(struct snd_info_entry *entry,
{
struct snd_motu *motu = entry->private_data;
const struct snd_motu_protocol *const protocol = motu->spec->protocol;
unsigned int rate;
enum snd_motu_clock_source source;
if (protocol->get_clock_rate(motu, &rate) < 0)
if (snd_motu_protocol_get_clock_rate(motu, &rate) < 0)
return;
if (protocol->get_clock_source(motu, &source) < 0)
if (snd_motu_protocol_get_clock_source(motu, &source) < 0)
return;
snd_iprintf(buffer, "Rate:\t%d\n", rate);
......@@ -45,15 +44,14 @@ static void proc_read_format(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_motu *motu = entry->private_data;
const struct snd_motu_protocol *const protocol = motu->spec->protocol;
unsigned int mode;
struct snd_motu_packet_format *formats;
int i;
if (protocol->cache_packet_formats(motu) < 0)
if (snd_motu_protocol_cache_packet_formats(motu) < 0)
return;
snd_iprintf(buffer, "tx:\tmsg\tfixed\tdiffered\n");
snd_iprintf(buffer, "tx:\tmsg\tfixed\ttotal\n");
for (i = 0; i < SND_MOTU_CLOCK_RATE_COUNT; ++i) {
mode = i >> 1;
......@@ -62,11 +60,11 @@ static void proc_read_format(struct snd_info_entry *entry,
"%u:\t%u\t%u\t%u\n",
snd_motu_clock_rates[i],
formats->msg_chunks,
formats->fixed_part_pcm_chunks[mode],
formats->differed_part_pcm_chunks[mode]);
motu->spec->tx_fixed_pcm_chunks[mode],
formats->pcm_chunks[mode]);
}
snd_iprintf(buffer, "rx:\tmsg\tfixed\tdiffered\n");
snd_iprintf(buffer, "rx:\tmsg\tfixed\ttotal\n");
for (i = 0; i < SND_MOTU_CLOCK_RATE_COUNT; ++i) {
mode = i >> 1;
......@@ -75,8 +73,8 @@ static void proc_read_format(struct snd_info_entry *entry,
"%u:\t%u\t%u\t%u\n",
snd_motu_clock_rates[i],
formats->msg_chunks,
formats->fixed_part_pcm_chunks[mode],
formats->differed_part_pcm_chunks[mode]);
motu->spec->rx_fixed_pcm_chunks[mode],
formats->pcm_chunks[mode]);
}
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -88,7 +88,7 @@ static void finish_session(struct snd_motu *motu)
u32 data;
int err;
err = motu->spec->protocol->switch_fetching_mode(motu, false);
err = snd_motu_protocol_switch_fetching_mode(motu, false);
if (err < 0)
return;
......@@ -110,7 +110,7 @@ int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
{
int err;
err = motu->spec->protocol->cache_packet_formats(motu);
err = snd_motu_protocol_cache_packet_formats(motu);
if (err < 0)
return err;
......@@ -140,7 +140,7 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
unsigned int curr_rate;
int err;
err = motu->spec->protocol->get_clock_rate(motu, &curr_rate);
err = snd_motu_protocol_get_clock_rate(motu, &curr_rate);
if (err < 0)
return err;
if (rate == 0)
......@@ -153,7 +153,7 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
fw_iso_resources_free(&motu->tx_resources);
fw_iso_resources_free(&motu->rx_resources);
err = motu->spec->protocol->set_clock_rate(motu, rate);
err = snd_motu_protocol_set_clock_rate(motu, rate);
if (err < 0) {
dev_err(&motu->unit->device,
"fail to set sampling rate: %d\n", err);
......@@ -201,9 +201,9 @@ static int ensure_packet_formats(struct snd_motu *motu)
data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS |
RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS|
TX_PACKET_TRANSMISSION_SPEED_MASK);
if (motu->tx_packet_formats.differed_part_pcm_chunks[0] == 0)
if (motu->spec->tx_fixed_pcm_chunks[0] == motu->tx_packet_formats.pcm_chunks[0])
data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
if (motu->rx_packet_formats.differed_part_pcm_chunks[0] == 0)
if (motu->spec->rx_fixed_pcm_chunks[0] == motu->rx_packet_formats.pcm_chunks[0])
data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
data |= fw_parent_device(motu->unit)->max_speed;
......@@ -272,7 +272,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu)
goto stop_streams;
}
err = motu->spec->protocol->switch_fetching_mode(motu, true);
err = snd_motu_protocol_switch_fetching_mode(motu, true);
if (err < 0) {
dev_err(&motu->unit->device,
"fail to enable frame fetching: %d\n", err);
......@@ -317,7 +317,7 @@ static int init_stream(struct snd_motu *motu, struct amdtp_stream *s)
if (err < 0)
return err;
err = amdtp_motu_init(s, motu->unit, dir, motu->spec->protocol);
err = amdtp_motu_init(s, motu->unit, dir, motu->spec);
if (err < 0)
fw_iso_resources_destroy(resources);
......
......@@ -172,105 +172,6 @@ static void motu_bus_update(struct fw_unit *unit)
snd_motu_transaction_reregister(motu);
}
const struct snd_motu_spec snd_motu_spec_828mk2 = {
.name = "828mk2",
.protocol = &snd_motu_protocol_v2,
.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
SND_MOTU_SPEC_TX_MICINST_CHUNK |
SND_MOTU_SPEC_TX_RETURN_CHUNK |
SND_MOTU_SPEC_RX_SEPARATED_MAIN |
SND_MOTU_SPEC_HAS_OPT_IFACE_A |
SND_MOTU_SPEC_RX_MIDI_2ND_Q |
SND_MOTU_SPEC_TX_MIDI_2ND_Q,
.analog_in_ports = 8,
.analog_out_ports = 8,
};
static const struct snd_motu_spec motu_traveler = {
.name = "Traveler",
.protocol = &snd_motu_protocol_v2,
.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
SND_MOTU_SPEC_SUPPORT_CLOCK_X4 |
SND_MOTU_SPEC_TX_RETURN_CHUNK |
SND_MOTU_SPEC_HAS_AESEBU_IFACE |
SND_MOTU_SPEC_HAS_OPT_IFACE_A |
SND_MOTU_SPEC_RX_MIDI_2ND_Q |
SND_MOTU_SPEC_TX_MIDI_2ND_Q,
.analog_in_ports = 8,
.analog_out_ports = 8,
};
static const struct snd_motu_spec motu_ultralite = {
.name = "UltraLite",
.protocol = &snd_motu_protocol_v2,
.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
SND_MOTU_SPEC_TX_MICINST_CHUNK | // padding.
SND_MOTU_SPEC_TX_RETURN_CHUNK |
SND_MOTU_SPEC_RX_MIDI_2ND_Q |
SND_MOTU_SPEC_TX_MIDI_2ND_Q |
SND_MOTU_SPEC_RX_SEPARATED_MAIN,
.analog_in_ports = 8,
.analog_out_ports = 8,
};
static const struct snd_motu_spec motu_8pre = {
.name = "8pre",
.protocol = &snd_motu_protocol_v2,
// In tx, use coax chunks for mix-return 1/2. In rx, use coax chunks for
// dummy 1/2.
.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
SND_MOTU_SPEC_HAS_OPT_IFACE_A |
SND_MOTU_SPEC_HAS_OPT_IFACE_B |
SND_MOTU_SPEC_RX_MIDI_2ND_Q |
SND_MOTU_SPEC_TX_MIDI_2ND_Q,
.analog_in_ports = 8,
.analog_out_ports = 2,
};
static const struct snd_motu_spec motu_828mk3 = {
.name = "828mk3",
.protocol = &snd_motu_protocol_v3,
.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
SND_MOTU_SPEC_SUPPORT_CLOCK_X4 |
SND_MOTU_SPEC_TX_MICINST_CHUNK |
SND_MOTU_SPEC_TX_RETURN_CHUNK |
SND_MOTU_SPEC_TX_REVERB_CHUNK |
SND_MOTU_SPEC_RX_SEPARATED_MAIN |
SND_MOTU_SPEC_HAS_OPT_IFACE_A |
SND_MOTU_SPEC_HAS_OPT_IFACE_B |
SND_MOTU_SPEC_RX_MIDI_3RD_Q |
SND_MOTU_SPEC_TX_MIDI_3RD_Q,
.analog_in_ports = 8,
.analog_out_ports = 8,
};
static const struct snd_motu_spec motu_audio_express = {
.name = "AudioExpress",
.protocol = &snd_motu_protocol_v3,
.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
SND_MOTU_SPEC_TX_MICINST_CHUNK |
SND_MOTU_SPEC_TX_RETURN_CHUNK |
SND_MOTU_SPEC_RX_SEPARATED_MAIN |
SND_MOTU_SPEC_RX_MIDI_2ND_Q |
SND_MOTU_SPEC_TX_MIDI_3RD_Q,
.analog_in_ports = 2,
.analog_out_ports = 4,
};
static const struct snd_motu_spec motu_4pre = {
.name = "4pre",
.protocol = &snd_motu_protocol_v3,
.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
SND_MOTU_SPEC_TX_MICINST_CHUNK |
SND_MOTU_SPEC_TX_RETURN_CHUNK |
SND_MOTU_SPEC_RX_SEPARATED_MAIN,
.analog_in_ports = 2,
.analog_out_ports = 2,
};
#define SND_MOTU_DEV_ENTRY(model, data) \
{ \
.match_flags = IEEE1394_MATCH_VENDOR_ID | \
......@@ -284,13 +185,14 @@ static const struct snd_motu_spec motu_4pre = {
static const struct ieee1394_device_id motu_id_table[] = {
SND_MOTU_DEV_ENTRY(0x000003, &snd_motu_spec_828mk2),
SND_MOTU_DEV_ENTRY(0x000009, &motu_traveler),
SND_MOTU_DEV_ENTRY(0x00000d, &motu_ultralite),
SND_MOTU_DEV_ENTRY(0x00000f, &motu_8pre),
SND_MOTU_DEV_ENTRY(0x000015, &motu_828mk3), /* FireWire only. */
SND_MOTU_DEV_ENTRY(0x000035, &motu_828mk3), /* Hybrid. */
SND_MOTU_DEV_ENTRY(0x000033, &motu_audio_express),
SND_MOTU_DEV_ENTRY(0x000045, &motu_4pre),
SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler),
SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite),
SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre),
SND_MOTU_DEV_ENTRY(0x000015, &snd_motu_spec_828mk3), // FireWire only.
SND_MOTU_DEV_ENTRY(0x000019, &snd_motu_spec_ultralite_mk3), // FireWire only.
SND_MOTU_DEV_ENTRY(0x000035, &snd_motu_spec_828mk3), // Hybrid.
SND_MOTU_DEV_ENTRY(0x000033, &snd_motu_spec_audio_express),
SND_MOTU_DEV_ENTRY(0x000045, &snd_motu_spec_4pre),
{ }
};
MODULE_DEVICE_TABLE(ieee1394, motu_id_table);
......
......@@ -36,8 +36,7 @@ struct snd_motu_packet_format {
unsigned char pcm_byte_offset;
unsigned char msg_chunks;
unsigned char fixed_part_pcm_chunks[3];
unsigned char differed_part_pcm_chunks[3];
unsigned char pcm_chunks[3];
};
struct snd_motu {
......@@ -74,19 +73,10 @@ struct snd_motu {
};
enum snd_motu_spec_flags {
SND_MOTU_SPEC_SUPPORT_CLOCK_X2 = 0x0001,
SND_MOTU_SPEC_SUPPORT_CLOCK_X4 = 0x0002,
SND_MOTU_SPEC_TX_MICINST_CHUNK = 0x0004,
SND_MOTU_SPEC_TX_RETURN_CHUNK = 0x0008,
SND_MOTU_SPEC_TX_REVERB_CHUNK = 0x0010,
SND_MOTU_SPEC_HAS_AESEBU_IFACE = 0x0020,
SND_MOTU_SPEC_HAS_OPT_IFACE_A = 0x0040,
SND_MOTU_SPEC_HAS_OPT_IFACE_B = 0x0080,
SND_MOTU_SPEC_RX_MIDI_2ND_Q = 0x0100,
SND_MOTU_SPEC_RX_MIDI_3RD_Q = 0x0200,
SND_MOTU_SPEC_TX_MIDI_2ND_Q = 0x0400,
SND_MOTU_SPEC_TX_MIDI_3RD_Q = 0x0800,
SND_MOTU_SPEC_RX_SEPARATED_MAIN = 0x1000,
SND_MOTU_SPEC_RX_MIDI_2ND_Q = 0x0001,
SND_MOTU_SPEC_RX_MIDI_3RD_Q = 0x0002,
SND_MOTU_SPEC_TX_MIDI_2ND_Q = 0x0004,
SND_MOTU_SPEC_TX_MIDI_3RD_Q = 0x0008,
};
#define SND_MOTU_CLOCK_RATE_COUNT 6
......@@ -108,33 +98,33 @@ enum snd_motu_clock_source {
SND_MOTU_CLOCK_SOURCE_UNKNOWN,
};
struct snd_motu_protocol {
int (*get_clock_rate)(struct snd_motu *motu, unsigned int *rate);
int (*set_clock_rate)(struct snd_motu *motu, unsigned int rate);
int (*get_clock_source)(struct snd_motu *motu,
enum snd_motu_clock_source *source);
int (*switch_fetching_mode)(struct snd_motu *motu, bool enable);
int (*cache_packet_formats)(struct snd_motu *motu);
enum snd_motu_protocol_version {
SND_MOTU_PROTOCOL_V2,
SND_MOTU_PROTOCOL_V3,
};
struct snd_motu_spec {
const char *const name;
enum snd_motu_protocol_version protocol_version;
enum snd_motu_spec_flags flags;
unsigned char analog_in_ports;
unsigned char analog_out_ports;
const struct snd_motu_protocol *const protocol;
unsigned char tx_fixed_pcm_chunks[3];
unsigned char rx_fixed_pcm_chunks[3];
};
extern const struct snd_motu_protocol snd_motu_protocol_v2;
extern const struct snd_motu_protocol snd_motu_protocol_v3;
extern const struct snd_motu_spec snd_motu_spec_828mk2;
extern const struct snd_motu_spec snd_motu_spec_traveler;
extern const struct snd_motu_spec snd_motu_spec_ultralite;
extern const struct snd_motu_spec snd_motu_spec_8pre;
extern const struct snd_motu_spec snd_motu_spec_828mk3;
extern const struct snd_motu_spec snd_motu_spec_ultralite_mk3;
extern const struct snd_motu_spec snd_motu_spec_audio_express;
extern const struct snd_motu_spec snd_motu_spec_4pre;
int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
enum amdtp_stream_direction dir,
const struct snd_motu_protocol *const protocol);
const struct snd_motu_spec *spec);
int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate,
unsigned int midi_ports,
struct snd_motu_packet_format *formats);
......@@ -169,4 +159,79 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu);
int snd_motu_create_midi_devices(struct snd_motu *motu);
int snd_motu_create_hwdep_device(struct snd_motu *motu);
int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu,
unsigned int *rate);
int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu,
unsigned int rate);
int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
enum snd_motu_clock_source *src);
int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
bool enable);
int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu);
int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu,
unsigned int *rate);
int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu,
unsigned int rate);
int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu,
enum snd_motu_clock_source *src);
int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu,
bool enable);
int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu);
static inline int snd_motu_protocol_get_clock_rate(struct snd_motu *motu,
unsigned int *rate)
{
if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
return snd_motu_protocol_v2_get_clock_rate(motu, rate);
else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
return snd_motu_protocol_v3_get_clock_rate(motu, rate);
else
return -ENXIO;
}
static inline int snd_motu_protocol_set_clock_rate(struct snd_motu *motu,
unsigned int rate)
{
if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
return snd_motu_protocol_v2_set_clock_rate(motu, rate);
else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
return snd_motu_protocol_v3_set_clock_rate(motu, rate);
else
return -ENXIO;
}
static inline int snd_motu_protocol_get_clock_source(struct snd_motu *motu,
enum snd_motu_clock_source *source)
{
if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
return snd_motu_protocol_v2_get_clock_source(motu, source);
else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
return snd_motu_protocol_v3_get_clock_source(motu, source);
else
return -ENXIO;
}
static inline int snd_motu_protocol_switch_fetching_mode(struct snd_motu *motu,
bool enable)
{
if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
return snd_motu_protocol_v2_switch_fetching_mode(motu, enable);
else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
return snd_motu_protocol_v3_switch_fetching_mode(motu, enable);
else
return -ENXIO;
}
static inline int snd_motu_protocol_cache_packet_formats(struct snd_motu *motu)
{
if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
return snd_motu_protocol_v2_cache_packet_formats(motu);
else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
return snd_motu_protocol_v3_cache_packet_formats(motu);
else
return -ENXIO;
}
#endif
......@@ -62,7 +62,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit);
static void default_release(struct device *dev)
{
snd_hdac_ext_bus_device_exit(container_of(dev, struct hdac_device, dev));
snd_hdac_ext_bus_device_exit(dev_to_hdac_dev(dev));
}
/**
......
......@@ -81,7 +81,6 @@ int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr,
mutex_unlock(&bus->cmd_mutex);
return err;
}
EXPORT_SYMBOL_GPL(snd_hdac_bus_exec_verb);
/**
* snd_hdac_bus_exec_verb_unlocked - unlocked version
......@@ -150,7 +149,6 @@ void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex)
schedule_work(&bus->unsol_work);
}
EXPORT_SYMBOL_GPL(snd_hdac_bus_queue_event);
/*
* process queued unsolicited events
......@@ -162,6 +160,7 @@ static void snd_hdac_bus_process_unsol_events(struct work_struct *work)
struct hdac_driver *drv;
unsigned int rp, caddr, res;
spin_lock_irq(&bus->reg_lock);
while (bus->unsol_rp != bus->unsol_wp) {
rp = (bus->unsol_rp + 1) % HDA_UNSOL_QUEUE_SIZE;
bus->unsol_rp = rp;
......@@ -173,10 +172,13 @@ static void snd_hdac_bus_process_unsol_events(struct work_struct *work)
codec = bus->caddr_tbl[caddr & 0x0f];
if (!codec || !codec->dev.driver)
continue;
spin_unlock_irq(&bus->reg_lock);
drv = drv_to_hdac_driver(codec->dev.driver);
if (drv->unsol_event)
drv->unsol_event(codec, res);
spin_lock_irq(&bus->reg_lock);
}
spin_unlock_irq(&bus->reg_lock);
}
/**
......
......@@ -9,6 +9,7 @@
#include <sound/core.h>
#include <sound/hdaudio.h>
#include <sound/hda_register.h>
#include "local.h"
/* clear CORB read pointer properly */
static void azx_clear_corbrp(struct hdac_bus *bus)
......@@ -527,6 +528,18 @@ bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset)
}
bus->chip_init = true;
/*
* Default value of '8' is as per the HD audio specification (Rev 1.0a).
* Following relation is used to derive STRIPE control value.
* For sample rate <= 48K:
* { ((num_channels * bits_per_sample) / number of SDOs) >= 8 }
* For sample rate > 48K:
* { ((num_channels * bits_per_sample * rate/48000) /
* number of SDOs) >= 8 }
*/
bus->sdo_limit = 8;
return true;
}
EXPORT_SYMBOL_GPL(snd_hdac_bus_init_chip);
......
......@@ -20,7 +20,7 @@ static int get_codec_vendor_name(struct hdac_device *codec);
static void default_release(struct device *dev)
{
snd_hdac_device_exit(container_of(dev, struct hdac_device, dev));
snd_hdac_device_exit(dev_to_hdac_dev(dev));
}
/**
......
......@@ -38,7 +38,7 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
else
value = (channels * bits_per_sample) / sdo_line;
if (value >= 8)
if (value >= bus->sdo_limit)
break;
}
......
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 Jaroslav Kysela <perex@perex.cz>
#include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/dmi.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_intel.h>
#include <sound/core.h>
#include <sound/intel-dsp-config.h>
#include <sound/intel-nhlt.h>
......@@ -16,7 +19,12 @@ MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=lega
#define FLAG_SST BIT(0)
#define FLAG_SOF BIT(1)
#define FLAG_SST_ONLY_IF_DMIC BIT(15)
#define FLAG_SOF_ONLY_IF_DMIC BIT(16)
#define FLAG_SOF_ONLY_IF_SOUNDWIRE BIT(17)
#define FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE (FLAG_SOF_ONLY_IF_DMIC | \
FLAG_SOF_ONLY_IF_SOUNDWIRE)
struct config_entry {
u32 flags;
......@@ -100,6 +108,10 @@ static const struct config_entry config_table[] = {
{}
}
},
{
.flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC,
.device = 0x9d70,
},
#endif
/* Kabylake-LP */
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL)
......@@ -116,6 +128,10 @@ static const struct config_entry config_table[] = {
{}
}
},
{
.flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC,
.device = 0x9d71,
},
#endif
/*
......@@ -166,7 +182,7 @@ static const struct config_entry config_table[] = {
}
},
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x9dc8,
},
#endif
......@@ -187,7 +203,7 @@ static const struct config_entry config_table[] = {
}
},
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0xa348,
},
#endif
......@@ -204,18 +220,50 @@ static const struct config_entry config_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
}
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
},
},
{
/* early version of SKU 09C6 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
},
},
{}
}
},
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x02c8,
},
#endif
/* Cometlake-H */
#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
.flags = FLAG_SOF,
.device = 0x06c8,
.dmi_table = (const struct dmi_system_id []) {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
},
},
{}
}
},
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x06c8,
},
#endif
......@@ -236,7 +284,7 @@ static const struct config_entry config_table[] = {
}
},
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x34c8,
},
#endif
......@@ -256,9 +304,8 @@ static const struct config_entry config_table[] = {
{}
}
},
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0xa0c8,
},
#endif
......@@ -303,6 +350,28 @@ static int snd_intel_dsp_check_dmic(struct pci_dev *pci)
return ret;
}
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
{
struct sdw_intel_acpi_info info;
acpi_handle handle;
int ret;
handle = ACPI_HANDLE(&pci->dev);
ret = sdw_intel_acpi_scan(handle, &info);
if (ret < 0)
return ret;
return info.link_mask;
}
#else
static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
{
return 0;
}
#endif
int snd_intel_dsp_driver_probe(struct pci_dev *pci)
{
const struct config_entry *cfg;
......@@ -336,18 +405,31 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci)
return SND_INTEL_DSP_DRIVER_ANY;
if (cfg->flags & FLAG_SOF) {
if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC) {
if (snd_intel_dsp_check_dmic(pci)) {
dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n");
if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE &&
snd_intel_dsp_check_soundwire(pci) > 0) {
dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n");
return SND_INTEL_DSP_DRIVER_SOF;
}
} else {
if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC &&
snd_intel_dsp_check_dmic(pci)) {
dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n");
return SND_INTEL_DSP_DRIVER_SOF;
}
if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE))
return SND_INTEL_DSP_DRIVER_SOF;
}
if (cfg->flags & FLAG_SST)
if (cfg->flags & FLAG_SST) {
if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) {
if (snd_intel_dsp_check_dmic(pci)) {
dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n");
return SND_INTEL_DSP_DRIVER_SST;
}
} else {
return SND_INTEL_DSP_DRIVER_SST;
}
}
return SND_INTEL_DSP_DRIVER_LEGACY;
}
......@@ -355,3 +437,4 @@ EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel DSP config driver");
MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT);
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2015-2019 Intel Corporation
#include <linux/acpi.h>
#include <sound/intel-nhlt.h>
#define NHLT_ACPI_HEADER_SIG "NHLT"
/* Unique identification for getting NHLT blobs */
static const guid_t osc_guid =
GUID_INIT(0xA69F886E, 0x6CEB, 0x4594,
0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53);
struct nhlt_acpi_table *intel_nhlt_init(struct device *dev)
{
acpi_handle handle;
union acpi_object *obj;
struct nhlt_resource_desc *nhlt_ptr;
struct nhlt_acpi_table *nhlt_table = NULL;
handle = ACPI_HANDLE(dev);
if (!handle) {
dev_err(dev, "Didn't find ACPI_HANDLE\n");
return NULL;
}
struct nhlt_acpi_table *nhlt;
acpi_status status;
obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL);
if (!obj)
return NULL;
if (obj->type != ACPI_TYPE_BUFFER) {
dev_dbg(dev, "No NHLT table found\n");
ACPI_FREE(obj);
status = acpi_get_table(ACPI_SIG_NHLT, 0,
(struct acpi_table_header **)&nhlt);
if (ACPI_FAILURE(status)) {
dev_warn(dev, "NHLT table not found\n");
return NULL;
}
nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer;
if (nhlt_ptr->length)
nhlt_table = (struct nhlt_acpi_table *)
memremap(nhlt_ptr->min_addr, nhlt_ptr->length,
MEMREMAP_WB);
ACPI_FREE(obj);
if (nhlt_table &&
(strncmp(nhlt_table->header.signature,
NHLT_ACPI_HEADER_SIG,
strlen(NHLT_ACPI_HEADER_SIG)) != 0)) {
memunmap(nhlt_table);
dev_err(dev, "NHLT ACPI header signature incorrect\n");
return NULL;
}
return nhlt_table;
return nhlt;
}
EXPORT_SYMBOL_GPL(intel_nhlt_init);
void intel_nhlt_free(struct nhlt_acpi_table *nhlt)
{
memunmap((void *)nhlt);
acpi_put_table((struct acpi_table_header *)nhlt);
}
EXPORT_SYMBOL_GPL(intel_nhlt_free);
......
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.
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