mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
sound updates for 5.7-rc1
This became again a busy development cycle. There are a few ALSA core updates (merely API cleanups and sparse fixes), while majority of other changes are found in ASoC scene. Here are some highlights: * ALSA core: - More helper macros for sparse warning fixes (e.g. bitwise types) - Slight optimization of PCM OSS locks - Make common handling for PCM / compress buffers (for SOF) * ASoC: - Lots of code refactoring and modernization for (still ongoing) componentization works - Conversion of SND_SOC_ALL_CODECS to use imply - Continued refactoring and fixing of the Intel SOF/SST support, including the initial (but still incomplete) SoundWire support - SoundWire and more advanced clocking support for Realtek RT5682 - Support for amlogic GX, Meson 8, Meson 8B and T9015 DAC, Broadcom DSL/PON, Ingenic JZ4760 and JZ4770, Realtek RL6231, and TI TAS2563 and TLV320ADCX140 * HD-audio: - Optimizations in HDMI jack handling - A few new quirks and fixups for Realtek codecs * USB-audio: - Delayed registration support - New quirks for Motu, Kingston, Presonus -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAl6Fr0oOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE+MFA//XZD6a6sVDCp1JvcT4yLn+xcpXPgT/HC/pUJb fH4T629gGUG2OGmEQXWf86c8UkrKjNsdkK5ZNjg6PlYagGZEO5RlQA35EV0/6QTK hQuRu8ALuVUnQBrB+knQRnlfa8hzXIaXWkriNi0s6V04iAlLJB1XqZ8/ckq3kWs2 UqQ7vkTRODRAivdH0a4KcN2hENSvPfBkNTjhTn+Gp86FC3PIGbN6XqcZWM0rpXQ7 qi9H9jVbavRCpHTPiV5DSZ6JyqqL/pT3LQ4GZIAf+i+frMGTIurB/7VUVIIuCFGT hf1MRrEFo47ox+7RyhJpgPPJxHhNdY+z7uUQDc/hoN1tDlLhGeS2Wjmy3soLZ172 yVbun2z6jfVgm5lyHMqDnY71nCUVAgSWZwFbBtKMroLkw06X3P8ahTmad7Pnnut0 XbrYt29aKOkuf+ejeMaUAtuyW0nKUg68DqlX8wP1RvO1bvY4kGrEkVj3K3ktNZEr GeZFLDDSMumxxXduX8vv/O5Z6MOGhq/toGjnYwnIOyzKR8uLEbUI4DIptUMoelgK b7zIMbLjeoZ4ckeUKNdbmEuhbrWZ3oM6owKCPt4D9EBunK9nu//cq2nsfGuJGBbT Swa+POYH89Au/22pYS0q3/fMAbEHctove/hvFiWoMRa3fNA2My2rMWwyaIAeW1Gl CAwOXk8= =fAMQ -----END PGP SIGNATURE----- Merge tag 'sound-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "This became again a busy development cycle. There are few ALSA core updates (merely API cleanups and sparse fixes), with the majority of other changes are found in ASoC scene. Here are some highlights: ALSA core: - More helper macros for sparse warning fixes (e.g. bitwise types) - Slight optimization of PCM OSS locks - Make common handling for PCM / compress buffers (for SOF) ASoC: - Lots of code refactoring and modernization for (still ongoing) componentization works - Conversion of SND_SOC_ALL_CODECS to use imply - Continued refactoring and fixing of the Intel SOF/SST support, including the initial (but still incomplete) SoundWire support - SoundWire and more advanced clocking support for Realtek RT5682 - Support for amlogic GX, Meson 8, Meson 8B and T9015 DAC, Broadcom DSL/PON, Ingenic JZ4760 and JZ4770, Realtek RL6231, and TI TAS2563 and TLV320ADCX140 HD-audio: - Optimizations in HDMI jack handling - A few new quirks and fixups for Realtek codecs USB-audio: - Delayed registration support - New quirks for Motu, Kingston, Presonus" * tag 'sound-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (415 commits) ALSA: usb-audio: Fix case when USB MIDI interface has more than one extra endpoint descriptor Revert "ALSA: uapi: Drop asound.h inclusion from asoc.h" ALSA: hda/realtek - Remove now-unnecessary XPS 13 headphone noise fixups ALSA: hda/realtek - Set principled PC Beep configuration for ALC256 ALSA: doc: Document PC Beep Hidden Register on Realtek ALC256 ALSA: hda/realtek - a fake key event is triggered by running shutup ALSA: hda: default enable CA0132 DSP support ASoC: amd: acp3x-pcm-dma: clean up two indentation issues ASoC: tlv320adcx140: Remove undocumented property ASoC: Intel: sof_sdw: Add Volteer support with RT5682 SNDW helper function ASoC: Intel: common: add match table for TGL RT5682 SoundWire driver ASoC: Intel: boards: add sof_sdw machine driver ASoC: Intel: soc-acpi: update topology and driver name for SoundWire platforms ASoC: rt5682: move DAI clock registry to I2S mode ASoC: pxa: magician: convert to use i2c_new_client_device() ASoC: SOF: Intel: hda-ctrl: add reset cycle before parsing capabilities Asoc: SOF: Intel: hda: check SoundWire wakeen interrupt in irq thread ASoC: SOF: Intel: hda: add WAKEEN interrupt support for SoundWire ASoC: SOF: Intel: hda: add parameter to control SoundWire clock stop quirks ASoC: SOF: Intel: hda: merge IPC, stream and SoundWire interrupt handlers ...
This commit is contained in:
commit
848960e576
113
Documentation/devicetree/bindings/sound/amlogic,aiu.yaml
Normal file
113
Documentation/devicetree/bindings/sound/amlogic,aiu.yaml
Normal file
@ -0,0 +1,113 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/amlogic,aiu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic AIU audio output controller
|
||||
|
||||
maintainers:
|
||||
- Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^audio-controller@.*"
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 2
|
||||
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- amlogic,aiu-gxbb
|
||||
- amlogic,aiu-gxl
|
||||
- amlogic,aiu-meson8
|
||||
- amlogic,aiu-meson8b
|
||||
- const:
|
||||
amlogic,aiu
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: AIU peripheral clock
|
||||
- description: I2S peripheral clock
|
||||
- description: I2S output clock
|
||||
- description: I2S master clock
|
||||
- description: I2S mixer clock
|
||||
- description: SPDIF peripheral clock
|
||||
- description: SPDIF output clock
|
||||
- description: SPDIF master clock
|
||||
- description: SPDIF master clock multiplexer
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: i2s_pclk
|
||||
- const: i2s_aoclk
|
||||
- const: i2s_mclk
|
||||
- const: i2s_mixer
|
||||
- const: spdif_pclk
|
||||
- const: spdif_aoclk
|
||||
- const: spdif_mclk
|
||||
- const: spdif_mclk_sel
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: I2S interrupt line
|
||||
- description: SPDIF interrupt line
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: i2s
|
||||
- const: spdif
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- "#sound-dai-cells"
|
||||
- compatible
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- reg
|
||||
- resets
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
|
||||
|
||||
aiu: audio-controller@5400 {
|
||||
compatible = "amlogic,aiu-gxl", "amlogic,aiu";
|
||||
#sound-dai-cells = <2>;
|
||||
reg = <0x0 0x5400 0x0 0x2ac>;
|
||||
interrupts = <GIC_SPI 48 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 50 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "i2s", "spdif";
|
||||
clocks = <&clkc CLKID_AIU_GLUE>,
|
||||
<&clkc CLKID_I2S_OUT>,
|
||||
<&clkc CLKID_AOCLK_GATE>,
|
||||
<&clkc CLKID_CTS_AMCLK>,
|
||||
<&clkc CLKID_MIXER_IFACE>,
|
||||
<&clkc CLKID_IEC958>,
|
||||
<&clkc CLKID_IEC958_GATE>,
|
||||
<&clkc CLKID_CTS_MCLK_I958>,
|
||||
<&clkc CLKID_CTS_I958>;
|
||||
clock-names = "pclk",
|
||||
"i2s_pclk",
|
||||
"i2s_aoclk",
|
||||
"i2s_mclk",
|
||||
"i2s_mixer",
|
||||
"spdif_pclk",
|
||||
"spdif_aoclk",
|
||||
"spdif_mclk",
|
||||
"spdif_mclk_sel";
|
||||
resets = <&reset RESET_AIU>;
|
||||
};
|
||||
|
@ -0,0 +1,51 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/amlogic,g12a-toacodec.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic G12a Internal DAC Control Glue
|
||||
|
||||
maintainers:
|
||||
- Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^audio-controller@.*"
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 1
|
||||
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- const:
|
||||
amlogic,g12a-toacodec
|
||||
- items:
|
||||
- enum:
|
||||
- amlogic,sm1-toacodec
|
||||
- const:
|
||||
amlogic,g12a-toacodec
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- "#sound-dai-cells"
|
||||
- compatible
|
||||
- reg
|
||||
- resets
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h>
|
||||
|
||||
toacodec: audio-controller@740 {
|
||||
compatible = "amlogic,g12a-toacodec";
|
||||
reg = <0x0 0x740 0x0 0x4>;
|
||||
#sound-dai-cells = <1>;
|
||||
resets = <&clkc_audio AUD_RESET_TOACODEC>;
|
||||
};
|
@ -0,0 +1,113 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/amlogic,gx-sound-card.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic GX sound card
|
||||
|
||||
maintainers:
|
||||
- Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: amlogic,gx-sound-card
|
||||
|
||||
audio-aux-devs:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description: list of auxiliary devices
|
||||
|
||||
audio-routing:
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
minItems: 2
|
||||
description: |-
|
||||
A list of the connections between audio components. Each entry is a
|
||||
pair of strings, the first being the connection's sink, the second
|
||||
being the connection's source.
|
||||
|
||||
audio-widgets:
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
minItems: 2
|
||||
description: |-
|
||||
A list off component DAPM widget. Each entry is a pair of strings,
|
||||
the first being the widget type, the second being the widget name
|
||||
|
||||
model:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: User specified audio sound card name
|
||||
|
||||
patternProperties:
|
||||
"^dai-link-[0-9]+$":
|
||||
type: object
|
||||
description: |-
|
||||
dai-link child nodes:
|
||||
Container for dai-link level properties and the CODEC sub-nodes.
|
||||
There should be at least one (and probably more) subnode of this type
|
||||
|
||||
properties:
|
||||
dai-format:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum: [ i2s, left-j, dsp_a ]
|
||||
|
||||
mclk-fs:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |-
|
||||
Multiplication factor between the frame rate and master clock
|
||||
rate
|
||||
|
||||
sound-dai:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: phandle of the CPU DAI
|
||||
|
||||
patternProperties:
|
||||
"^codec-[0-9]+$":
|
||||
type: object
|
||||
description: |-
|
||||
Codecs:
|
||||
dai-link representing backend links should have at least one subnode.
|
||||
One subnode for each codec of the dai-link. dai-link representing
|
||||
frontend links have no codec, therefore have no subnodes
|
||||
|
||||
properties:
|
||||
sound-dai:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: phandle of the codec DAI
|
||||
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
required:
|
||||
- model
|
||||
- dai-link-0
|
||||
|
||||
examples:
|
||||
- |
|
||||
sound {
|
||||
compatible = "amlogic,gx-sound-card";
|
||||
model = "GXL-ACME-S905X-FOO";
|
||||
audio-aux-devs = <&>;
|
||||
audio-routing = "I2S ENCODER I2S IN", "I2S FIFO Playback";
|
||||
|
||||
dai-link-0 {
|
||||
sound-dai = <&i2s_fifo>;
|
||||
};
|
||||
|
||||
dai-link-1 {
|
||||
sound-dai = <&i2s_encoder>;
|
||||
dai-format = "i2s";
|
||||
mclk-fs = <256>;
|
||||
|
||||
codec-0 {
|
||||
sound-dai = <&codec0>;
|
||||
};
|
||||
|
||||
codec-1 {
|
||||
sound-dai = <&codec1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
58
Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
Normal file
58
Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
Normal file
@ -0,0 +1,58 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/amlogic,t9015.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic T9015 Internal Audio DAC
|
||||
|
||||
maintainers:
|
||||
- Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^audio-controller@.*"
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
compatible:
|
||||
items:
|
||||
- const: amlogic,t9015
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Peripheral clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- "#sound-dai-cells"
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/g12a-clkc.h>
|
||||
#include <dt-bindings/reset/amlogic,meson-g12a-reset.h>
|
||||
|
||||
acodec: audio-controller@32000 {
|
||||
compatible = "amlogic,t9015";
|
||||
reg = <0x0 0x32000 0x0 0x14>;
|
||||
#sound-dai-cells = <0>;
|
||||
clocks = <&clkc CLKID_AUDIO_CODEC>;
|
||||
clock-names = "pclk";
|
||||
resets = <&reset RESET_AUDIO_CODEC>;
|
||||
};
|
||||
|
@ -0,0 +1,29 @@
|
||||
Broadcom DSL/PON BCM63xx Audio I2S controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "brcm,bcm63xx-i2s".
|
||||
- #address-cells: 32bit valued, 1 cell.
|
||||
- #size-cells: 32bit valued, 0 cell.
|
||||
- reg: Should contain audio registers location and length
|
||||
- interrupts: Should contain the interrupt for the controller.
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
Please refer to clock-bindings.txt.
|
||||
- clock-names: One of each entry matching the clocks phandles list:
|
||||
- "i2sclk" (generated clock) Required.
|
||||
- "i2sosc" (fixed 200MHz clock) Required.
|
||||
|
||||
(1) : The generated clock is required only when any of TX and RX
|
||||
works on Master Mode.
|
||||
(2) : The fixed 200MHz clock is from internal chip and always on
|
||||
|
||||
Example:
|
||||
|
||||
i2s: bcm63xx-i2s {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "brcm,bcm63xx-i2s";
|
||||
reg = <0xFF802080 0xFF>;
|
||||
interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&i2sclk>, <&osc>;
|
||||
clock-names = "i2sclk","i2sosc";
|
||||
};
|
69
Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml
Normal file
69
Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml
Normal file
@ -0,0 +1,69 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/cirrus,cs42l51.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: CS42L51 audio codec DT bindings
|
||||
|
||||
maintainers:
|
||||
- Olivier Moysan <olivier.moysan@st.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: cirrus,cs42l51
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: MCLK
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
VL-supply:
|
||||
description: phandle to voltage regulator of digital interface section
|
||||
|
||||
VD-supply:
|
||||
description: phandle to voltage regulator of digital internal section
|
||||
|
||||
VA-supply:
|
||||
description: phandle to voltage regulator of analog internal section
|
||||
|
||||
VAHP-supply:
|
||||
description: phandle to voltage regulator of headphone
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#sound-dai-cells"
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cs42l51@4a {
|
||||
compatible = "cirrus,cs42l51";
|
||||
reg = <0x4a>;
|
||||
#sound-dai-cells = <0>;
|
||||
clocks = <&mclk_prov>;
|
||||
clock-names = "MCLK";
|
||||
VL-supply = <®_audio>;
|
||||
VD-supply = <®_audio>;
|
||||
VA-supply = <®_audio>;
|
||||
VAHP-supply = <®_audio>;
|
||||
reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
...
|
@ -1,33 +0,0 @@
|
||||
CS42L51 audio CODEC
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "cirrus,cs42l51"
|
||||
|
||||
- reg : the I2C address of the device for I2C.
|
||||
|
||||
Optional properties:
|
||||
- VL-supply, VD-supply, VA-supply, VAHP-supply: power supplies for the device,
|
||||
as covered in Documentation/devicetree/bindings/regulator/regulator.txt.
|
||||
|
||||
- reset-gpios : GPIO specification for the reset pin. If specified, it will be
|
||||
deasserted before starting the communication with the codec.
|
||||
|
||||
- clocks : a list of phandles + clock-specifiers, one for each entry in
|
||||
clock-names
|
||||
|
||||
- clock-names : must contain "MCLK"
|
||||
|
||||
Example:
|
||||
|
||||
cs42l51: cs42l51@4a {
|
||||
compatible = "cirrus,cs42l51";
|
||||
reg = <0x4a>;
|
||||
clocks = <&mclk_prov>;
|
||||
clock-names = "MCLK";
|
||||
VL-supply = <®_audio>;
|
||||
VD-supply = <®_audio>;
|
||||
VA-supply = <®_audio>;
|
||||
VAHP-supply = <®_audio>;
|
||||
reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>;
|
||||
};
|
@ -1,44 +0,0 @@
|
||||
Audio codec controlled by ChromeOS EC
|
||||
|
||||
Google's ChromeOS EC codec is a digital mic codec provided by the
|
||||
Embedded Controller (EC) and is controlled via a host-command interface.
|
||||
|
||||
An EC codec node should only be found as a sub-node of the EC node (see
|
||||
Documentation/devicetree/bindings/mfd/cros-ec.txt).
|
||||
|
||||
Required properties:
|
||||
- compatible: Must contain "google,cros-ec-codec"
|
||||
- #sound-dai-cells: Should be 1. The cell specifies number of DAIs.
|
||||
|
||||
Optional properties:
|
||||
- reg: Pysical base address and length of shared memory region from EC.
|
||||
It contains 3 unsigned 32-bit integer. The first 2 integers
|
||||
combine to become an unsigned 64-bit physical address. The last
|
||||
one integer is length of the shared memory.
|
||||
- memory-region: Shared memory region to EC. A "shared-dma-pool". See
|
||||
../reserved-memory/reserved-memory.txt for details.
|
||||
|
||||
Example:
|
||||
|
||||
{
|
||||
...
|
||||
|
||||
reserved_mem: reserved_mem {
|
||||
compatible = "shared-dma-pool";
|
||||
reg = <0 0x52800000 0 0x100000>;
|
||||
no-map;
|
||||
};
|
||||
}
|
||||
|
||||
cros-ec@0 {
|
||||
compatible = "google,cros-ec-spi";
|
||||
|
||||
...
|
||||
|
||||
cros_ec_codec: ec-codec {
|
||||
compatible = "google,cros-ec-codec";
|
||||
#sound-dai-cells = <1>;
|
||||
reg = <0x0 0x10500000 0x80000>;
|
||||
memory-region = <&reserved_mem>;
|
||||
};
|
||||
};
|
@ -0,0 +1,67 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/google,cros-ec-codec.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Audio codec controlled by ChromeOS EC
|
||||
|
||||
maintainers:
|
||||
- Cheng-Yi Chiang <cychiang@chromium.org>
|
||||
|
||||
description: |
|
||||
Google's ChromeOS EC codec is a digital mic codec provided by the
|
||||
Embedded Controller (EC) and is controlled via a host-command interface.
|
||||
An EC codec node should only be found as a sub-node of the EC node (see
|
||||
Documentation/devicetree/bindings/mfd/cros-ec.txt).
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: google,cros-ec-codec
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 1
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: |
|
||||
Physical base address and length of shared memory region from EC.
|
||||
It contains 3 unsigned 32-bit integer. The first 2 integers
|
||||
combine to become an unsigned 64-bit physical address.
|
||||
The last one integer is the length of the shared memory.
|
||||
|
||||
memory-region:
|
||||
$ref: '/schemas/types.yaml#/definitions/phandle'
|
||||
description: |
|
||||
Shared memory region to EC. A "shared-dma-pool".
|
||||
See ../reserved-memory/reserved-memory.txt for details.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- '#sound-dai-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
reserved_mem: reserved-mem@52800000 {
|
||||
compatible = "shared-dma-pool";
|
||||
reg = <0x52800000 0x100000>;
|
||||
no-map;
|
||||
};
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cros-ec@0 {
|
||||
compatible = "google,cros-ec-spi";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
reg = <0>;
|
||||
cros_ec_codec: ec-codec@10500000 {
|
||||
compatible = "google,cros-ec-codec";
|
||||
#sound-dai-cells = <1>;
|
||||
reg = <0x0 0x10500000 0x80000>;
|
||||
memory-region = <&reserved_mem>;
|
||||
};
|
||||
};
|
||||
};
|
92
Documentation/devicetree/bindings/sound/ingenic,aic.yaml
Normal file
92
Documentation/devicetree/bindings/sound/ingenic,aic.yaml
Normal file
@ -0,0 +1,92 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/ingenic,aic.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Ingenic SoCs AC97 / I2S Controller (AIC) DT bindings
|
||||
|
||||
maintainers:
|
||||
- Paul Cercueil <paul@crapouillou.net>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: '^audio-controller@'
|
||||
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- ingenic,jz4740-i2s
|
||||
- ingenic,jz4760-i2s
|
||||
- ingenic,jz4770-i2s
|
||||
- ingenic,jz4780-i2s
|
||||
- items:
|
||||
- const: ingenic,jz4725b-i2s
|
||||
- const: ingenic,jz4740-i2s
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: AIC clock
|
||||
- description: I2S clock
|
||||
- description: EXT clock
|
||||
- description: PLL/2 clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: aic
|
||||
- const: i2s
|
||||
- const: ext
|
||||
- const: pll half
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: DMA controller phandle and request line for I2S RX
|
||||
- description: DMA controller phandle and request line for I2S TX
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- dmas
|
||||
- dma-names
|
||||
- '#sound-dai-cells'
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/jz4740-cgu.h>
|
||||
aic: audio-controller@10020000 {
|
||||
compatible = "ingenic,jz4740-i2s";
|
||||
reg = <0x10020000 0x38>;
|
||||
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <18>;
|
||||
|
||||
clocks = <&cgu JZ4740_CLK_AIC>,
|
||||
<&cgu JZ4740_CLK_I2S>,
|
||||
<&cgu JZ4740_CLK_EXT>,
|
||||
<&cgu JZ4740_CLK_PLL_HALF>;
|
||||
clock-names = "aic", "i2s", "ext", "pll half";
|
||||
|
||||
dmas = <&dmac 25 0xffffffff>, <&dmac 24 0xffffffff>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
Ingenic JZ4740 I2S controller
|
||||
|
||||
Required properties:
|
||||
- compatible : "ingenic,jz4740-i2s" or "ingenic,jz4780-i2s"
|
||||
- reg : I2S registers location and length
|
||||
- clocks : AIC and I2S PLL clock specifiers.
|
||||
- clock-names: "aic" and "i2s"
|
||||
- dmas: DMA controller phandle and DMA request line for I2S Tx and Rx channels
|
||||
- dma-names: Must be "tx" and "rx"
|
||||
|
||||
Example:
|
||||
|
||||
i2s: i2s@10020000 {
|
||||
compatible = "ingenic,jz4740-i2s";
|
||||
reg = <0x10020000 0x94>;
|
||||
|
||||
clocks = <&cgu JZ4740_CLK_AIC>, <&cgu JZ4740_CLK_I2SPLL>;
|
||||
clock-names = "aic", "i2s";
|
||||
|
||||
dmas = <&dma 2>, <&dma 3>;
|
||||
dma-names = "tx", "rx";
|
||||
|
||||
};
|
@ -18,6 +18,7 @@ Required properties:
|
||||
* Headphone Jack
|
||||
* Int Spk
|
||||
* Mic Jack
|
||||
* Int Mic
|
||||
|
||||
- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
|
||||
- nvidia,audio-codec : The phandle of the WM8903 audio codec
|
||||
|
@ -10,6 +10,11 @@ Required properties:
|
||||
- clock-names: should be "pclk".
|
||||
- spk-depop-time-ms: speak depop time msec.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- mute-gpios: GPIO specifier for external line driver control (typically the
|
||||
dedicated GPIO_MUTE pin)
|
||||
|
||||
Example for rk3328 internal codec:
|
||||
|
||||
codec: codec@ff410000 {
|
||||
@ -18,6 +23,6 @@ codec: codec@ff410000 {
|
||||
rockchip,grf = <&grf>;
|
||||
clocks = <&cru PCLK_ACODEC>;
|
||||
clock-names = "pclk";
|
||||
mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>;
|
||||
spk-depop-time-ms = 100;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -1,49 +0,0 @@
|
||||
* Rockchip I2S controller
|
||||
|
||||
The I2S bus (Inter-IC sound bus) is a serial link for digital
|
||||
audio data transfer between devices in the system.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be one of the following:
|
||||
- "rockchip,rk3066-i2s": for rk3066
|
||||
- "rockchip,px30-i2s", "rockchip,rk3066-i2s": for px30
|
||||
- "rockchip,rk3036-i2s", "rockchip,rk3066-i2s": for rk3036
|
||||
- "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
|
||||
- "rockchip,rk3228-i2s", "rockchip,rk3066-i2s": for rk3228
|
||||
- "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
|
||||
- "rockchip,rk3328-i2s", "rockchip,rk3066-i2s": for rk3328
|
||||
- "rockchip,rk3366-i2s", "rockchip,rk3066-i2s": for rk3366
|
||||
- "rockchip,rk3368-i2s", "rockchip,rk3066-i2s": for rk3368
|
||||
- "rockchip,rk3399-i2s", "rockchip,rk3066-i2s": for rk3399
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: should contain the I2S interrupt.
|
||||
- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
|
||||
Documentation/devicetree/bindings/dma/dma.txt
|
||||
- dma-names: should include "tx" and "rx".
|
||||
- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
|
||||
- clock-names: should contain the following:
|
||||
- "i2s_hclk": clock for I2S BUS
|
||||
- "i2s_clk" : clock for I2S controller
|
||||
- rockchip,playback-channels: max playback channels, if not set, 8 channels default.
|
||||
- rockchip,capture-channels: max capture channels, if not set, 2 channels default.
|
||||
|
||||
Required properties for controller which support multi channels
|
||||
playback/capture:
|
||||
|
||||
- rockchip,grf: the phandle of the syscon node for GRF register.
|
||||
|
||||
Example for rk3288 I2S controller:
|
||||
|
||||
i2s@ff890000 {
|
||||
compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
|
||||
reg = <0xff890000 0x10000>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&pdma1 0>, <&pdma1 1>;
|
||||
dma-names = "tx", "rx";
|
||||
clock-names = "i2s_hclk", "i2s_clk";
|
||||
clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
|
||||
rockchip,playback-channels = <8>;
|
||||
rockchip,capture-channels = <2>;
|
||||
};
|
111
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
Normal file
111
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
Normal file
@ -0,0 +1,111 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/rockchip-i2s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip I2S controller
|
||||
|
||||
description:
|
||||
The I2S bus (Inter-IC sound bus) is a serial link for digital
|
||||
audio data transfer between devices in the system.
|
||||
|
||||
maintainers:
|
||||
- Heiko Stuebner <heiko@sntech.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: rockchip,rk3066-i2s
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,px30-i2s
|
||||
- rockchip,rk3036-i2s
|
||||
- rockchip,rk3188-i2s
|
||||
- rockchip,rk3228-i2s
|
||||
- rockchip,rk3288-i2s
|
||||
- rockchip,rk3328-i2s
|
||||
- rockchip,rk3366-i2s
|
||||
- rockchip,rk3368-i2s
|
||||
- rockchip,rk3399-i2s
|
||||
- const: rockchip,rk3066-i2s
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: clock for I2S controller
|
||||
- description: clock for I2S BUS
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: i2s_clk
|
||||
- const: i2s_hclk
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: TX DMA Channel
|
||||
- description: RX DMA Channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
rockchip,capture-channels:
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 2
|
||||
description:
|
||||
Max capture channels, if not set, 2 channels default.
|
||||
|
||||
rockchip,playback-channels:
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 8
|
||||
description:
|
||||
Max playback channels, if not set, 8 channels default.
|
||||
|
||||
rockchip,grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
The phandle of the syscon node for the GRF register.
|
||||
Required property for controllers which support multi channel
|
||||
playback/capture.
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- dmas
|
||||
- dma-names
|
||||
- "#sound-dai-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/rk3288-cru.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2s@ff890000 {
|
||||
compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
|
||||
reg = <0xff890000 0x10000>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru SCLK_I2S0>, <&cru HCLK_I2S0>;
|
||||
clock-names = "i2s_clk", "i2s_hclk";
|
||||
dmas = <&pdma1 0>, <&pdma1 1>;
|
||||
dma-names = "tx", "rx";
|
||||
rockchip,capture-channels = <2>;
|
||||
rockchip,playback-channels = <8>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
@ -32,6 +32,18 @@ Optional properties:
|
||||
The delay time is realtek,btndet-delay value multiple of 8.192 ms.
|
||||
If absent, the default is 16.
|
||||
|
||||
- #clock-cells : Should be set to '<1>', wclk and bclk sources provided.
|
||||
- clock-output-names : Name given for DAI clocks output.
|
||||
|
||||
- clocks : phandle and clock specifier for codec MCLK.
|
||||
- clock-names : Clock name string for 'clocks' attribute, should be "mclk".
|
||||
|
||||
- realtek,dmic-clk-rate-hz : Set the clock rate (hz) for the requirement of
|
||||
the particular DMIC.
|
||||
|
||||
- realtek,dmic-delay-ms : Set the delay time (ms) for the requirement of
|
||||
the particular DMIC.
|
||||
|
||||
Pins on the device (for linking into audio routes) for RT5682:
|
||||
|
||||
* DMIC L1
|
||||
@ -53,4 +65,10 @@ rt5682 {
|
||||
realtek,dmic1-clk-pin = <1>;
|
||||
realtek,jd-src = <1>;
|
||||
realtek,btndet-delay = <16>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
clock-output-names = "rt5682-dai-wclk", "rt5682-dai-bclk";
|
||||
|
||||
clocks = <&osc>;
|
||||
clock-names = "mclk";
|
||||
};
|
||||
|
@ -1,62 +0,0 @@
|
||||
STMicroelectronics STM32 SPI/I2S Controller
|
||||
|
||||
The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode.
|
||||
Only some SPI instances support I2S.
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "st,stm32h7-i2s"
|
||||
- reg: Offset and length of the device's register set.
|
||||
- interrupts: Must contain the interrupt line id.
|
||||
- clocks: Must contain phandle and clock specifier pairs for each entry
|
||||
in clock-names.
|
||||
- clock-names: Must contain "i2sclk", "pclk", "x8k" and "x11k".
|
||||
"i2sclk": clock which feeds the internal clock generator
|
||||
"pclk": clock which feeds the peripheral bus interface
|
||||
"x8k": I2S parent clock for sampling rates multiple of 8kHz.
|
||||
"x11k": I2S parent clock for sampling rates multiple of 11.025kHz.
|
||||
- dmas: DMA specifiers for tx and rx dma.
|
||||
See Documentation/devicetree/bindings/dma/stm32-dma.txt.
|
||||
- dma-names: Identifier for each DMA request line. Must be "tx" and "rx".
|
||||
- pinctrl-names: should contain only value "default"
|
||||
- pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
|
||||
|
||||
Optional properties:
|
||||
- resets: Reference to a reset controller asserting the reset controller
|
||||
|
||||
The device node should contain one 'port' child node with one child 'endpoint'
|
||||
node, according to the bindings defined in Documentation/devicetree/bindings/
|
||||
graph.txt.
|
||||
|
||||
Example:
|
||||
sound_card {
|
||||
compatible = "audio-graph-card";
|
||||
dais = <&i2s2_port>;
|
||||
};
|
||||
|
||||
i2s2: audio-controller@40003800 {
|
||||
compatible = "st,stm32h7-i2s";
|
||||
reg = <0x40003800 0x400>;
|
||||
interrupts = <36>;
|
||||
clocks = <&rcc PCLK1>, <&rcc SPI2_CK>, <&rcc PLL1_Q>, <&rcc PLL2_P>;
|
||||
clock-names = "pclk", "i2sclk", "x8k", "x11k";
|
||||
dmas = <&dmamux2 2 39 0x400 0x1>,
|
||||
<&dmamux2 3 40 0x400 0x1>;
|
||||
dma-names = "rx", "tx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_i2s2>;
|
||||
|
||||
i2s2_port: port@0 {
|
||||
cpu_endpoint: endpoint {
|
||||
remote-endpoint = <&codec_endpoint>;
|
||||
format = "i2s";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
audio-codec {
|
||||
codec_port: port@0 {
|
||||
codec_endpoint: endpoint {
|
||||
remote-endpoint = <&cpu_endpoint>;
|
||||
};
|
||||
};
|
||||
};
|
87
Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
Normal file
87
Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
Normal file
@ -0,0 +1,87 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/st,stm32-i2s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: STMicroelectronics STM32 SPI/I2S Controller
|
||||
|
||||
maintainers:
|
||||
- Olivier Moysan <olivier.moysan@st.com>
|
||||
|
||||
description:
|
||||
The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode.
|
||||
Only some SPI instances support I2S.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- st,stm32h7-i2s
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: clock feeding the peripheral bus interface.
|
||||
- description: clock feeding the internal clock generator.
|
||||
- description: I2S parent clock for sampling rates multiple of 8kHz.
|
||||
- description: I2S parent clock for sampling rates multiple of 11.025kHz.
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: i2sclk
|
||||
- const: x8k
|
||||
- const: x11k
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: audio capture DMA.
|
||||
- description: audio playback DMA.
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#sound-dai-cells"
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
i2s2: audio-controller@4000b000 {
|
||||
compatible = "st,stm32h7-i2s";
|
||||
#sound-dai-cells = <0>;
|
||||
reg = <0x4000b000 0x400>;
|
||||
clocks = <&rcc SPI2>, <&rcc SPI2_K>, <&rcc PLL3_Q>, <&rcc PLL3_R>;
|
||||
clock-names = "pclk", "i2sclk", "x8k", "x11k";
|
||||
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmamux1 39 0x400 0x01>,
|
||||
<&dmamux1 40 0x400 0x01>;
|
||||
dma-names = "rx", "tx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s2_pins_a>;
|
||||
};
|
||||
|
||||
...
|
@ -1,56 +0,0 @@
|
||||
STMicroelectronics STM32 S/PDIF receiver (SPDIFRX).
|
||||
|
||||
The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with
|
||||
IEC-60958 and IEC-61937.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "st,stm32h7-spdifrx"
|
||||
- reg: cpu DAI IP base address and size
|
||||
- clocks: must contain an entry for kclk (used as S/PDIF signal reference)
|
||||
- clock-names: must contain "kclk"
|
||||
- interrupts: cpu DAI interrupt line
|
||||
- dmas: DMA specifiers for audio data DMA and iec control flow DMA
|
||||
See STM32 DMA bindings, Documentation/devicetree/bindings/dma/st,stm32-dma.yaml
|
||||
- dma-names: two dmas have to be defined, "rx" and "rx-ctrl"
|
||||
|
||||
Optional properties:
|
||||
- resets: Reference to a reset controller asserting the SPDIFRX
|
||||
|
||||
The device node should contain one 'port' child node with one child 'endpoint'
|
||||
node, according to the bindings defined in Documentation/devicetree/bindings/
|
||||
graph.txt.
|
||||
|
||||
Example:
|
||||
spdifrx: spdifrx@40004000 {
|
||||
compatible = "st,stm32h7-spdifrx";
|
||||
reg = <0x40004000 0x400>;
|
||||
clocks = <&rcc SPDIFRX_CK>;
|
||||
clock-names = "kclk";
|
||||
interrupts = <97>;
|
||||
dmas = <&dmamux1 2 93 0x400 0x0>,
|
||||
<&dmamux1 3 94 0x400 0x0>;
|
||||
dma-names = "rx", "rx-ctrl";
|
||||
pinctrl-0 = <&spdifrx_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
spdifrx_port: port {
|
||||
cpu_endpoint: endpoint {
|
||||
remote-endpoint = <&codec_endpoint>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
spdif_in: spdif-in {
|
||||
compatible = "linux,spdif-dir";
|
||||
|
||||
codec_port: port {
|
||||
codec_endpoint: endpoint {
|
||||
remote-endpoint = <&cpu_endpoint>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soundcard {
|
||||
compatible = "audio-graph-card";
|
||||
dais = <&spdifrx_port>;
|
||||
};
|
@ -0,0 +1,80 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/st,stm32-spdifrx.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: STMicroelectronics STM32 S/PDIF receiver (SPDIFRX)
|
||||
|
||||
maintainers:
|
||||
- Olivier Moysan <olivier.moysan@st.com>
|
||||
|
||||
description: |
|
||||
The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with
|
||||
IEC-60958 and IEC-61937.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- st,stm32h7-spdifrx
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: kclk
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: audio data capture DMA
|
||||
- description: IEC status bits capture DMA
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: rx-ctrl
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#sound-dai-cells"
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
spdifrx: spdifrx@40004000 {
|
||||
compatible = "st,stm32h7-spdifrx";
|
||||
#sound-dai-cells = <0>;
|
||||
reg = <0x40004000 0x400>;
|
||||
clocks = <&rcc SPDIF_K>;
|
||||
clock-names = "kclk";
|
||||
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmamux1 2 93 0x400 0x0>,
|
||||
<&dmamux1 3 94 0x400 0x0>;
|
||||
dma-names = "rx", "rx-ctrl";
|
||||
pinctrl-0 = <&spdifrx_pins>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
...
|
@ -8,7 +8,7 @@ real time monitoring of loudspeaker behavior.
|
||||
Required properties:
|
||||
- #address-cells - Should be <1>.
|
||||
- #size-cells - Should be <0>.
|
||||
- compatible: - Should contain "ti,tas2562".
|
||||
- compatible: - Should contain "ti,tas2562", "ti,tas2563".
|
||||
- reg: - The i2c address. Should be 0x4c, 0x4d, 0x4e or 0x4f.
|
||||
- ti,imon-slot-no:- TDM TX current sense time slot.
|
||||
|
||||
|
82
Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
Normal file
82
Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
Normal file
@ -0,0 +1,82 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause)
|
||||
# Copyright (C) 2019 Texas Instruments Incorporated
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/tlv320adcx140.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments TLV320ADCX140 Quad Channel Analog-to-Digital Converter
|
||||
|
||||
maintainers:
|
||||
- Dan Murphy <dmurphy@ti.com>
|
||||
|
||||
description: |
|
||||
The TLV320ADCX140 are multichannel (4-ch analog recording or 8-ch digital
|
||||
PDM microphones recording), high-performance audio, analog-to-digital
|
||||
converter (ADC) with analog inputs supporting up to 2V RMS. The TLV320ADCX140
|
||||
family supports line and microphone Inputs, and offers a programmable
|
||||
microphone bias or supply voltage generation.
|
||||
|
||||
Specifications can be found at:
|
||||
http://www.ti.com/lit/ds/symlink/tlv320adc3140.pdf
|
||||
http://www.ti.com/lit/ds/symlink/tlv320adc5140.pdf
|
||||
http://www.ti.com/lit/ds/symlink/tlv320adc6140.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: ti,tlv320adc3140
|
||||
- const: ti,tlv320adc5140
|
||||
- const: ti,tlv320adc6140
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: |
|
||||
I2C addresss of the device can be one of these 0x4c, 0x4d, 0x4e or 0x4f
|
||||
|
||||
reset-gpios:
|
||||
description: |
|
||||
GPIO used for hardware reset.
|
||||
|
||||
areg-supply:
|
||||
description: |
|
||||
Regulator with AVDD at 3.3V. If not defined then the internal regulator
|
||||
is enabled.
|
||||
|
||||
ti,mic-bias-source:
|
||||
description: |
|
||||
Indicates the source for MIC Bias.
|
||||
0 - Mic bias is set to VREF
|
||||
1 - Mic bias is set to VREF × 1.096
|
||||
6 - Mic bias is set to AVDD
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- enum: [0, 1, 6]
|
||||
|
||||
ti,vref-source:
|
||||
description: |
|
||||
Indicates the source for MIC Bias.
|
||||
0 - Set VREF to 2.75V
|
||||
1 - Set VREF to 2.5V
|
||||
2 - Set VREF to 1.375V
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- enum: [0, 1, 2]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
codec: codec@4c {
|
||||
compatible = "ti,tlv320adc5140";
|
||||
reg = <0x4c>;
|
||||
ti,mic-bias-source = <6>;
|
||||
reset-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
@ -2234,6 +2234,19 @@ use_vmalloc
|
||||
buffers. If mmap is used on such architectures, turn off this
|
||||
option, so that the DMA-coherent buffers are allocated and used
|
||||
instead.
|
||||
delayed_register
|
||||
The option is needed for devices that have multiple streams
|
||||
defined in multiple USB interfaces. The driver may invoke
|
||||
registrations multiple times (once per interface) and this may
|
||||
lead to the insufficient device enumeration.
|
||||
This option receives an array of strings, and you can pass
|
||||
ID:INTERFACE like ``0123abcd:4`` for performing the delayed
|
||||
registration to the given device. In this example, when a USB
|
||||
device 0123:abcd is probed, the driver waits the registration
|
||||
until the USB interface 4 gets probed.
|
||||
The driver prints a message like "Found post-registration device
|
||||
assignment: 1234abcd:04" for such a device, so that user can
|
||||
notice the need.
|
||||
|
||||
This module supports multiple devices, autoprobe and hotplugging.
|
||||
|
||||
|
@ -8,3 +8,4 @@ HD-Audio
|
||||
models
|
||||
controls
|
||||
dp-mst
|
||||
realtek-pc-beep
|
||||
|
@ -216,8 +216,6 @@ alc298-dell-aio
|
||||
ALC298 fixups on Dell AIO machines
|
||||
alc275-dell-xps
|
||||
ALC275 fixups on Dell XPS models
|
||||
alc256-dell-xps13
|
||||
ALC256 fixups on Dell XPS13
|
||||
lenovo-spk-noise
|
||||
Workaround for speaker noise on Lenovo machines
|
||||
lenovo-hotkey
|
||||
|
129
Documentation/sound/hd-audio/realtek-pc-beep.rst
Normal file
129
Documentation/sound/hd-audio/realtek-pc-beep.rst
Normal file
@ -0,0 +1,129 @@
|
||||
===============================
|
||||
Realtek PC Beep Hidden Register
|
||||
===============================
|
||||
|
||||
This file documents the "PC Beep Hidden Register", which is present in certain
|
||||
Realtek HDA codecs and controls a muxer and pair of passthrough mixers that can
|
||||
route audio between pins but aren't themselves exposed as HDA widgets. As far
|
||||
as I can tell, these hidden routes are designed to allow flexible PC Beep output
|
||||
for codecs that don't have mixer widgets in their output paths. Why it's easier
|
||||
to hide a mixer behind an undocumented vendor register than to just expose it
|
||||
as a widget, I have no idea.
|
||||
|
||||
Register Description
|
||||
====================
|
||||
|
||||
The register is accessed via processing coefficient 0x36 on NID 20h. Bits not
|
||||
identified below have no discernible effect on my machine, a Dell XPS 13 9350::
|
||||
|
||||
MSB LSB
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |h|S|L| | B |R| | Known bits
|
||||
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
|0|0|1|1| 0x7 |0|0x0|1| 0x7 | Reset value
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
1Ah input select (B): 2 bits
|
||||
When zero, expose the PC Beep line (from the internal beep generator, when
|
||||
enabled with the Set Beep Generation verb on NID 01h, or else from the
|
||||
external PCBEEP pin) on the 1Ah pin node. When nonzero, expose the headphone
|
||||
jack (or possibly Line In on some machines) input instead. If PC Beep is
|
||||
selected, the 1Ah boost control has no effect.
|
||||
|
||||
Amplify 1Ah loopback, left (L): 1 bit
|
||||
Amplify the left channel of 1Ah before mixing it into outputs as specified
|
||||
by h and S bits. Does not affect the level of 1Ah exposed to other widgets.
|
||||
|
||||
Amplify 1Ah loopback, right (R): 1 bit
|
||||
Amplify the right channel of 1Ah before mixing it into outputs as specified
|
||||
by h and S bits. Does not affect the level of 1Ah exposed to other widgets.
|
||||
|
||||
Loopback 1Ah to 21h [active low] (h): 1 bit
|
||||
When zero, mix 1Ah (possibly with amplification, depending on L and R bits)
|
||||
into 21h (headphone jack on my machine). Mixed signal respects the mute
|
||||
setting on 21h.
|
||||
|
||||
Loopback 1Ah to 14h (S): 1 bit
|
||||
When one, mix 1Ah (possibly with amplification, depending on L and R bits)
|
||||
into 14h (internal speaker on my machine). Mixed signal **ignores** the mute
|
||||
setting on 14h and is present whenever 14h is configured as an output.
|
||||
|
||||
Path diagrams
|
||||
=============
|
||||
|
||||
1Ah input selection (DIV is the PC Beep divider set on NID 01h)::
|
||||
|
||||
<Beep generator> <PCBEEP pin> <Headphone jack>
|
||||
| | |
|
||||
+--DIV--+--!DIV--+ {1Ah boost control}
|
||||
| |
|
||||
+--(b == 0)--+--(b != 0)--+
|
||||
|
|
||||
>1Ah (Beep/Headphone Mic/Line In)<
|
||||
|
||||
Loopback of 1Ah to 21h/14h::
|
||||
|
||||
<1Ah (Beep/Headphone Mic/Line In)>
|
||||
|
|
||||
{amplify if L/R}
|
||||
|
|
||||
+-----!h-----+-----S-----+
|
||||
| |
|
||||
{21h mute control} |
|
||||
| |
|
||||
>21h (Headphone)< >14h (Internal Speaker)<
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
All Realtek HDA codecs have a vendor-defined widget with node ID 20h which
|
||||
provides access to a bank of registers that control various codec functions.
|
||||
Registers are read and written via the standard HDA processing coefficient
|
||||
verbs (Set/Get Coefficient Index, Set/Get Processing Coefficient). The node is
|
||||
named "Realtek Vendor Registers" in public datasheets' verb listings and,
|
||||
apart from that, is entirely undocumented.
|
||||
|
||||
This particular register, exposed at coefficient 0x36 and named in commits from
|
||||
Realtek, is of note: unlike most registers, which seem to control detailed
|
||||
amplifier parameters not in scope of the HDA specification, it controls audio
|
||||
routing which could just as easily have been defined using standard HDA mixer
|
||||
and selector widgets.
|
||||
|
||||
Specifically, it selects between two sources for the input pin widget with Node
|
||||
ID (NID) 1Ah: the widget's signal can come either from an audio jack (on my
|
||||
laptop, a Dell XPS 13 9350, it's the headphone jack, but comments in Realtek
|
||||
commits indicate that it might be a Line In on some machines) or from the PC
|
||||
Beep line (which is itself multiplexed between the codec's internal beep
|
||||
generator and external PCBEEP pin, depending on if the beep generator is
|
||||
enabled via verbs on NID 01h). Additionally, it can mix (with optional
|
||||
amplification) that signal onto the 21h and/or 14h output pins.
|
||||
|
||||
The register's reset value is 0x3717, corresponding to PC Beep on 1Ah that is
|
||||
then amplified and mixed into both the headphones and the speakers. Not only
|
||||
does this violate the HDA specification, which says that "[a vendor defined
|
||||
beep input pin] connection may be maintained *only* while the Link reset
|
||||
(**RST#**) is asserted", it means that we cannot ignore the register if we care
|
||||
about the input that 1Ah would otherwise expose or if the PCBEEP trace is
|
||||
poorly shielded and picks up chassis noise (both of which are the case on my
|
||||
machine).
|
||||
|
||||
Unfortunately, there are lots of ways to get this register configuration wrong.
|
||||
Linux, it seems, has gone through most of them. For one, the register resets
|
||||
after S3 suspend: judging by existing code, this isn't the case for all vendor
|
||||
registers, and it's led to some fixes that improve behavior on cold boot but
|
||||
don't last after suspend. Other fixes have successfully switched the 1Ah input
|
||||
away from PC Beep but have failed to disable both loopback paths. On my
|
||||
machine, this means that the headphone input is amplified and looped back to
|
||||
the headphone output, which uses the exact same pins! As you might expect, this
|
||||
causes terrible headphone noise, the character of which is controlled by the
|
||||
1Ah boost control. (If you've seen instructions online to fix XPS 13 headphone
|
||||
noise by changing "Headphone Mic Boost" in ALSA, now you know why.)
|
||||
|
||||
The information here has been obtained through black-box reverse engineering of
|
||||
the ALC256 codec's behavior and is not guaranteed to be correct. It likely
|
||||
also applies for the ALC255, ALC257, ALC235, and ALC236, since those codecs
|
||||
seem to be close relatives of the ALC256. (They all share one initialization
|
||||
function.) Additionally, other codecs like the ALC225 and ALC285 also have this
|
||||
register, judging by existing fixups in ``patch_realtek.c``, but specific
|
||||
data (e.g. node IDs, bit positions, pin mappings) for those codecs may differ
|
||||
from what I've described here.
|
@ -104,5 +104,10 @@ Make sure to name your corresponding cpu and codec playback and capture
|
||||
dai names ending with "Playback" and "Capture" respectively as dapm core
|
||||
will link and power those dais based on the name.
|
||||
|
||||
Note that in current device tree there is no way to mark a dai_link
|
||||
as codec to codec. However, it may change in future.
|
||||
A dai_link in a "simple-audio-card" will automatically be detected as
|
||||
codec to codec when all DAIs on the link belong to codec components.
|
||||
The dai_link will be initialized with the subset of stream parameters
|
||||
(channels, format, sample rate) supported by all DAIs on the link. Since
|
||||
there is no way to provide these parameters in the device tree, this is
|
||||
mostly useful for communication with simple fixed-function codecs, such
|
||||
as a Bluetooth controller or cellular modem.
|
||||
|
15
MAINTAINERS
15
MAINTAINERS
@ -4055,8 +4055,8 @@ F: Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
|
||||
F: sound/soc/codecs/cros_ec_codec.*
|
||||
|
||||
CIRRUS LOGIC AUDIO CODEC DRIVERS
|
||||
M: Brian Austin <brian.austin@cirrus.com>
|
||||
M: Paul Handrigan <Paul.Handrigan@cirrus.com>
|
||||
M: James Schulman <james.schulman@cirrus.com>
|
||||
M: David Rhodes <david.rhodes@cirrus.com>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: sound/soc/codecs/cs*
|
||||
@ -15750,6 +15750,17 @@ F: sound/soc/
|
||||
F: include/dt-bindings/sound/
|
||||
F: include/sound/soc*
|
||||
|
||||
SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS
|
||||
M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
M: Liam Girdwood <lgirdwood@gmail.com>
|
||||
M: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
|
||||
M: Kai Vehmanen <kai.vehmanen@linux.intel.com>
|
||||
M: Daniel Baluta <daniel.baluta@nxp.com>
|
||||
L: sound-open-firmware@alsa-project.org (moderated for non-subscribers)
|
||||
W: https://github.com/thesofproject/linux/
|
||||
S: Supported
|
||||
F: sound/soc/sof/
|
||||
|
||||
SOUNDWIRE SUBSYSTEM
|
||||
M: Vinod Koul <vkoul@kernel.org>
|
||||
M: Sanyog Kale <sanyog.r.kale@intel.com>
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
@ -169,6 +170,9 @@ struct mtk_hdmi {
|
||||
bool audio_enable;
|
||||
bool powered;
|
||||
bool enabled;
|
||||
hdmi_codec_plugged_cb plugged_cb;
|
||||
struct device *codec_dev;
|
||||
struct mutex update_plugged_status_lock;
|
||||
};
|
||||
|
||||
static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b)
|
||||
@ -1194,13 +1198,26 @@ static void mtk_hdmi_clk_disable_audio(struct mtk_hdmi *hdmi)
|
||||
clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_AUD_SPDIF]);
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi)
|
||||
{
|
||||
bool connected;
|
||||
|
||||
mutex_lock(&hdmi->update_plugged_status_lock);
|
||||
connected = mtk_cec_hpd_high(hdmi->cec_dev);
|
||||
if (hdmi->plugged_cb && hdmi->codec_dev)
|
||||
hdmi->plugged_cb(hdmi->codec_dev, connected);
|
||||
mutex_unlock(&hdmi->update_plugged_status_lock);
|
||||
|
||||
return connected ?
|
||||
connector_status_connected : connector_status_disconnected;
|
||||
}
|
||||
|
||||
static enum drm_connector_status hdmi_conn_detect(struct drm_connector *conn,
|
||||
bool force)
|
||||
{
|
||||
struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
|
||||
|
||||
return mtk_cec_hpd_high(hdmi->cec_dev) ?
|
||||
connector_status_connected : connector_status_disconnected;
|
||||
return mtk_hdmi_update_plugged_status(hdmi);
|
||||
}
|
||||
|
||||
static void hdmi_conn_destroy(struct drm_connector *conn)
|
||||
@ -1657,20 +1674,39 @@ static int mtk_hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_hdmi_audio_hook_plugged_cb(struct device *dev, void *data,
|
||||
hdmi_codec_plugged_cb fn,
|
||||
struct device *codec_dev)
|
||||
{
|
||||
struct mtk_hdmi *hdmi = data;
|
||||
|
||||
mutex_lock(&hdmi->update_plugged_status_lock);
|
||||
hdmi->plugged_cb = fn;
|
||||
hdmi->codec_dev = codec_dev;
|
||||
mutex_unlock(&hdmi->update_plugged_status_lock);
|
||||
|
||||
mtk_hdmi_update_plugged_status(hdmi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hdmi_codec_ops mtk_hdmi_audio_codec_ops = {
|
||||
.hw_params = mtk_hdmi_audio_hw_params,
|
||||
.audio_startup = mtk_hdmi_audio_startup,
|
||||
.audio_shutdown = mtk_hdmi_audio_shutdown,
|
||||
.digital_mute = mtk_hdmi_audio_digital_mute,
|
||||
.get_eld = mtk_hdmi_audio_get_eld,
|
||||
.hook_plugged_cb = mtk_hdmi_audio_hook_plugged_cb,
|
||||
};
|
||||
|
||||
static void mtk_hdmi_register_audio_driver(struct device *dev)
|
||||
static int mtk_hdmi_register_audio_driver(struct device *dev)
|
||||
{
|
||||
struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
struct hdmi_codec_pdata codec_data = {
|
||||
.ops = &mtk_hdmi_audio_codec_ops,
|
||||
.max_i2s_channels = 2,
|
||||
.i2s = 1,
|
||||
.data = hdmi,
|
||||
};
|
||||
struct platform_device *pdev;
|
||||
|
||||
@ -1678,9 +1714,10 @@ static void mtk_hdmi_register_audio_driver(struct device *dev)
|
||||
PLATFORM_DEVID_AUTO, &codec_data,
|
||||
sizeof(codec_data));
|
||||
if (IS_ERR(pdev))
|
||||
return;
|
||||
return PTR_ERR(pdev);
|
||||
|
||||
DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_drm_hdmi_probe(struct platform_device *pdev)
|
||||
@ -1706,6 +1743,7 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_init(&hdmi->update_plugged_status_lock);
|
||||
platform_set_drvdata(pdev, hdmi);
|
||||
|
||||
ret = mtk_hdmi_output_init(hdmi);
|
||||
@ -1714,7 +1752,11 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
mtk_hdmi_register_audio_driver(dev);
|
||||
ret = mtk_hdmi_register_audio_driver(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register audio driver: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
|
||||
hdmi->bridge.of_node = pdev->dev.of_node;
|
||||
|
@ -594,6 +594,7 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream,
|
||||
struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev);
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct sdw_stream_runtime *sruntime;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
int ret, i;
|
||||
|
||||
sruntime = sdw_alloc_stream(dai->name);
|
||||
@ -602,12 +603,12 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream,
|
||||
|
||||
ctrl->sruntime[dai->id] = sruntime;
|
||||
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
ret = snd_soc_dai_set_sdw_stream(rtd->codec_dais[i], sruntime,
|
||||
for_each_rtd_codec_dais(rtd, i, codec_dai) {
|
||||
ret = snd_soc_dai_set_sdw_stream(codec_dai, sruntime,
|
||||
substream->stream);
|
||||
if (ret < 0 && ret != -ENOTSUPP) {
|
||||
dev_err(dai->dev, "Failed to set sdw stream on %s",
|
||||
rtd->codec_dais[i]->name);
|
||||
codec_dai->name);
|
||||
sdw_release_stream(sruntime);
|
||||
return ret;
|
||||
}
|
||||
|
@ -167,13 +167,15 @@ static int sdw_program_slave_port_params(struct sdw_bus *bus,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Program DPN_BlockCtrl1 register */
|
||||
ret = sdw_write(s_rt->slave, addr2, (p_params->bps - 1));
|
||||
if (ret < 0) {
|
||||
dev_err(&s_rt->slave->dev,
|
||||
"DPN_BlockCtrl1 register write failed for port %d\n",
|
||||
t_params->port_num);
|
||||
return ret;
|
||||
if (!dpn_prop->read_only_wordlength) {
|
||||
/* Program DPN_BlockCtrl1 register */
|
||||
ret = sdw_write(s_rt->slave, addr2, (p_params->bps - 1));
|
||||
if (ret < 0) {
|
||||
dev_err(&s_rt->slave->dev,
|
||||
"DPN_BlockCtrl1 register write failed for port %d\n",
|
||||
t_params->port_num);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Program DPN_SampleCtrl1 register */
|
||||
|
@ -575,7 +575,7 @@ config SPI_PPC4xx
|
||||
|
||||
config SPI_PXA2XX
|
||||
tristate "PXA2xx SSP SPI master"
|
||||
depends on (ARCH_PXA || ARCH_MMP || PCI || ACPI)
|
||||
depends on ARCH_PXA || ARCH_MMP || PCI || ACPI || COMPILE_TEST
|
||||
select PXA_SSP if ARCH_PXA || ARCH_MMP
|
||||
help
|
||||
This enables using a PXA2xx or Sodaville SSP port as a SPI master
|
||||
|
18
include/dt-bindings/sound/meson-aiu.h
Normal file
18
include/dt-bindings/sound/meson-aiu.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __DT_MESON_AIU_H
|
||||
#define __DT_MESON_AIU_H
|
||||
|
||||
#define AIU_CPU 0
|
||||
#define AIU_HDMI 1
|
||||
#define AIU_ACODEC 2
|
||||
|
||||
#define CPU_I2S_FIFO 0
|
||||
#define CPU_SPDIF_FIFO 1
|
||||
#define CPU_I2S_ENCODER 2
|
||||
#define CPU_SPDIF_ENCODER 3
|
||||
|
||||
#define CTRL_I2S 0
|
||||
#define CTRL_PCM 1
|
||||
#define CTRL_OUT 2
|
||||
|
||||
#endif /* __DT_MESON_AIU_H */
|
10
include/dt-bindings/sound/meson-g12a-toacodec.h
Normal file
10
include/dt-bindings/sound/meson-g12a-toacodec.h
Normal file
@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __DT_MESON_G12A_TOACODEC_H
|
||||
#define __DT_MESON_G12A_TOACODEC_H
|
||||
|
||||
#define TOACODEC_IN_A 0
|
||||
#define TOACODEC_IN_B 1
|
||||
#define TOACODEC_IN_C 2
|
||||
#define TOACODEC_OUT 3
|
||||
|
||||
#endif /* __DT_MESON_G12A_TOACODEC_H */
|
@ -284,6 +284,7 @@ struct sdw_dpn_audio_mode {
|
||||
* @max_async_buffer: Number of samples that this port can buffer in
|
||||
* asynchronous modes
|
||||
* @block_pack_mode: Type of block port mode supported
|
||||
* @read_only_wordlength: Read Only wordlength field in DPN_BlockCtrl1 register
|
||||
* @port_encoding: Payload Channel Sample encoding schemes supported
|
||||
* @audio_modes: Audio modes supported
|
||||
*/
|
||||
@ -307,6 +308,7 @@ struct sdw_dpn_prop {
|
||||
u32 modes;
|
||||
u32 max_async_buffer;
|
||||
bool block_pack_mode;
|
||||
bool read_only_wordlength;
|
||||
u32 port_encoding;
|
||||
struct sdw_dpn_audio_mode *audio_modes;
|
||||
};
|
||||
|
@ -156,6 +156,18 @@ struct uac2_feature_unit_descriptor {
|
||||
__u8 bmaControls[]; /* variable length */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* 4.7.2.10 Effect Unit Descriptor */
|
||||
|
||||
struct uac2_effect_unit_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubtype;
|
||||
__u8 bUnitID;
|
||||
__le16 wEffectType;
|
||||
__u8 bSourceID;
|
||||
__u8 bmaControls[]; /* variable length */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* 4.9.2 Class-Specific AS Interface Descriptor */
|
||||
|
||||
struct uac2_as_header_descriptor {
|
||||
|
@ -23,7 +23,6 @@ struct snd_compr_ops;
|
||||
* struct snd_compr_runtime: runtime stream description
|
||||
* @state: stream state
|
||||
* @ops: pointer to DSP callbacks
|
||||
* @dma_buffer_p: runtime dma buffer pointer
|
||||
* @buffer: pointer to kernel buffer, valid only when not in mmap mode or
|
||||
* DSP doesn't implement copy
|
||||
* @buffer_size: size of the above buffer
|
||||
@ -34,11 +33,14 @@ struct snd_compr_ops;
|
||||
* @total_bytes_transferred: cumulative bytes transferred by offload DSP
|
||||
* @sleep: poll sleep
|
||||
* @private_data: driver private data pointer
|
||||
* @dma_area: virtual buffer address
|
||||
* @dma_addr: physical buffer address (not accessible from main CPU)
|
||||
* @dma_bytes: size of DMA area
|
||||
* @dma_buffer_p: runtime dma buffer pointer
|
||||
*/
|
||||
struct snd_compr_runtime {
|
||||
snd_pcm_state_t state;
|
||||
struct snd_compr_ops *ops;
|
||||
struct snd_dma_buffer *dma_buffer_p;
|
||||
void *buffer;
|
||||
u64 buffer_size;
|
||||
u32 fragment_size;
|
||||
@ -47,6 +49,11 @@ struct snd_compr_runtime {
|
||||
u64 total_bytes_transferred;
|
||||
wait_queue_head_t sleep;
|
||||
void *private_data;
|
||||
|
||||
unsigned char *dma_area;
|
||||
dma_addr_t dma_addr;
|
||||
size_t dma_bytes;
|
||||
struct snd_dma_buffer *dma_buffer_p;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -60,6 +67,7 @@ struct snd_compr_runtime {
|
||||
* @metadata_set: metadata set flag, true when set
|
||||
* @next_track: has userspace signal next track transition, true when set
|
||||
* @private_data: pointer to DSP private data
|
||||
* @dma_buffer: allocated buffer if any
|
||||
*/
|
||||
struct snd_compr_stream {
|
||||
const char *name;
|
||||
@ -71,6 +79,7 @@ struct snd_compr_stream {
|
||||
bool metadata_set;
|
||||
bool next_track;
|
||||
void *private_data;
|
||||
struct snd_dma_buffer dma_buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -180,21 +189,34 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
|
||||
|
||||
/**
|
||||
* snd_compr_set_runtime_buffer - Set the Compress runtime buffer
|
||||
* @substream: compress substream to set
|
||||
* @stream: compress stream to set
|
||||
* @bufp: the buffer information, NULL to clear
|
||||
*
|
||||
* Copy the buffer information to runtime buffer when @bufp is non-NULL.
|
||||
* Otherwise it clears the current buffer information.
|
||||
*/
|
||||
static inline void snd_compr_set_runtime_buffer(
|
||||
struct snd_compr_stream *substream,
|
||||
struct snd_dma_buffer *bufp)
|
||||
static inline void
|
||||
snd_compr_set_runtime_buffer(struct snd_compr_stream *stream,
|
||||
struct snd_dma_buffer *bufp)
|
||||
{
|
||||
struct snd_compr_runtime *runtime = substream->runtime;
|
||||
struct snd_compr_runtime *runtime = stream->runtime;
|
||||
|
||||
runtime->dma_buffer_p = bufp;
|
||||
if (bufp) {
|
||||
runtime->dma_buffer_p = bufp;
|
||||
runtime->dma_area = bufp->area;
|
||||
runtime->dma_addr = bufp->addr;
|
||||
runtime->dma_bytes = bufp->bytes;
|
||||
} else {
|
||||
runtime->dma_buffer_p = NULL;
|
||||
runtime->dma_area = NULL;
|
||||
runtime->dma_addr = 0;
|
||||
runtime->dma_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size);
|
||||
int snd_compr_free_pages(struct snd_compr_stream *stream);
|
||||
|
||||
int snd_compr_stop_error(struct snd_compr_stream *stream,
|
||||
snd_pcm_state_t state);
|
||||
|
||||
|
@ -266,6 +266,7 @@ void snd_device_disconnect(struct snd_card *card, void *device_data);
|
||||
void snd_device_disconnect_all(struct snd_card *card);
|
||||
void snd_device_free(struct snd_card *card, void *device_data);
|
||||
void snd_device_free_all(struct snd_card *card);
|
||||
int snd_device_get_state(struct snd_card *card, void *device_data);
|
||||
|
||||
/* isadma.c */
|
||||
|
||||
|
@ -513,6 +513,7 @@ struct hdac_stream {
|
||||
struct snd_pcm_substream *substream; /* assigned substream,
|
||||
* set in PCM open
|
||||
*/
|
||||
struct snd_compr_stream *cstream;
|
||||
unsigned int format_val; /* format value to be set in the
|
||||
* controller and the codec
|
||||
*/
|
||||
@ -527,6 +528,7 @@ struct hdac_stream {
|
||||
bool locked:1;
|
||||
bool stripe:1; /* apply stripe control */
|
||||
|
||||
u64 curr_pos;
|
||||
/* timestamp */
|
||||
unsigned long start_wallclk; /* start + minimum wallclk */
|
||||
unsigned long period_wallclk; /* wallclk for period */
|
||||
|
@ -644,6 +644,11 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
|
||||
#define snd_pcm_group_for_each_entry(s, substream) \
|
||||
list_for_each_entry(s, &substream->group->substreams, link_list)
|
||||
|
||||
#define for_each_pcm_streams(stream) \
|
||||
for (stream = SNDRV_PCM_STREAM_PLAYBACK; \
|
||||
stream <= SNDRV_PCM_STREAM_LAST; \
|
||||
stream++)
|
||||
|
||||
/**
|
||||
* snd_pcm_running - Check whether the substream is in a running state
|
||||
* @substream: substream to check
|
||||
@ -1122,7 +1127,14 @@ snd_pcm_kernel_readv(struct snd_pcm_substream *substream,
|
||||
return __snd_pcm_lib_xfer(substream, bufs, false, frames, true);
|
||||
}
|
||||
|
||||
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
|
||||
int snd_pcm_hw_limit_rates(struct snd_pcm_hardware *hw);
|
||||
|
||||
static inline int
|
||||
snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
|
||||
{
|
||||
return snd_pcm_hw_limit_rates(&runtime->hw);
|
||||
}
|
||||
|
||||
unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
|
||||
unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit);
|
||||
unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
|
||||
@ -1415,6 +1427,15 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format)
|
||||
return 1ULL << (__force int) pcm_format;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcm_for_each_format - helper to iterate for each format type
|
||||
* @f: the iterator variable in snd_pcm_format_t type
|
||||
*/
|
||||
#define pcm_for_each_format(f) \
|
||||
for ((f) = SNDRV_PCM_FORMAT_FIRST; \
|
||||
(__force int)(f) <= (__force int)SNDRV_PCM_FORMAT_LAST; \
|
||||
(f) = (__force snd_pcm_format_t)((__force int)(f) + 1))
|
||||
|
||||
/* printk helpers */
|
||||
#define pcm_err(pcm, fmt, args...) \
|
||||
dev_err((pcm)->card->dev, fmt, ##args)
|
||||
|
@ -133,6 +133,13 @@ static inline int snd_mask_test(const struct snd_mask *mask, unsigned int val)
|
||||
return mask->bits[MASK_OFS(val)] & MASK_BIT(val);
|
||||
}
|
||||
|
||||
/* Most of drivers need only this one */
|
||||
static inline int snd_mask_test_format(const struct snd_mask *mask,
|
||||
snd_pcm_format_t format)
|
||||
{
|
||||
return snd_mask_test(mask, (__force unsigned int)format);
|
||||
}
|
||||
|
||||
static inline int snd_mask_single(const struct snd_mask *mask)
|
||||
{
|
||||
int i, c = 0;
|
||||
|
@ -24,6 +24,12 @@ enum rt5682_jd_src {
|
||||
RT5682_JD1,
|
||||
};
|
||||
|
||||
enum rt5682_dai_clks {
|
||||
RT5682_DAI_WCLK_IDX,
|
||||
RT5682_DAI_BCLK_IDX,
|
||||
RT5682_DAI_NUM_CLKS,
|
||||
};
|
||||
|
||||
struct rt5682_platform_data {
|
||||
|
||||
int ldo1_en; /* GPIO for LDO1_EN */
|
||||
@ -32,6 +38,10 @@ struct rt5682_platform_data {
|
||||
enum rt5682_dmic1_clk_pin dmic1_clk_pin;
|
||||
enum rt5682_jd_src jd_src;
|
||||
unsigned int btndet_delay;
|
||||
unsigned int dmic_clk_rate;
|
||||
unsigned int dmic_delay;
|
||||
|
||||
const char *dai_clk_names[RT5682_DAI_NUM_CLKS];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -75,18 +75,45 @@ struct snd_soc_acpi_mach_params {
|
||||
};
|
||||
|
||||
/**
|
||||
* snd_soc_acpi_link_adr: ACPI-based list of _ADR, with a variable
|
||||
* number of devices per link
|
||||
*
|
||||
* snd_soc_acpi_endpoint - endpoint descriptor
|
||||
* @num: endpoint number (mandatory, unique per device)
|
||||
* @aggregated: 0 (independent) or 1 (logically grouped)
|
||||
* @group_position: zero-based order (only when @aggregated is 1)
|
||||
* @group_id: platform-unique group identifier (only when @aggregrated is 1)
|
||||
*/
|
||||
struct snd_soc_acpi_endpoint {
|
||||
u8 num;
|
||||
u8 aggregated;
|
||||
u8 group_position;
|
||||
u8 group_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* snd_soc_acpi_adr_device - descriptor for _ADR-enumerated device
|
||||
* @adr: 64 bit ACPI _ADR value
|
||||
* @num_endpoints: number of endpoints for this device
|
||||
* @endpoints: array of endpoints
|
||||
*/
|
||||
struct snd_soc_acpi_adr_device {
|
||||
const u64 adr;
|
||||
const u8 num_endpoints;
|
||||
const struct snd_soc_acpi_endpoint *endpoints;
|
||||
};
|
||||
|
||||
/**
|
||||
* snd_soc_acpi_link_adr - ACPI-based list of _ADR enumerated devices
|
||||
* @mask: one bit set indicates the link this list applies to
|
||||
* @num_adr: ARRAY_SIZE of adr
|
||||
* @adr: array of _ADR (represented as u64).
|
||||
* @num_adr: ARRAY_SIZE of devices
|
||||
* @adr_d: array of devices
|
||||
*
|
||||
* The number of devices per link can be more than 1, e.g. in SoundWire
|
||||
* multi-drop configurations.
|
||||
*/
|
||||
|
||||
struct snd_soc_acpi_link_adr {
|
||||
const u32 mask;
|
||||
const u32 num_adr;
|
||||
const u64 *adr;
|
||||
const struct snd_soc_acpi_adr_device *adr_d;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -202,6 +202,8 @@ struct snd_soc_dai_ops {
|
||||
|
||||
int (*set_sdw_stream)(struct snd_soc_dai *dai,
|
||||
void *stream, int direction);
|
||||
void *(*get_sdw_stream)(struct snd_soc_dai *dai, int direction);
|
||||
|
||||
/*
|
||||
* DAI digital mute - optional.
|
||||
* Called by soc-core to minimise any pops.
|
||||
@ -322,9 +324,7 @@ struct snd_soc_dai {
|
||||
struct snd_soc_dai_driver *driver;
|
||||
|
||||
/* DAI runtime info */
|
||||
unsigned int capture_active; /* stream usage count */
|
||||
unsigned int playback_active; /* stream usage count */
|
||||
unsigned int probed:1;
|
||||
unsigned int stream_active[SNDRV_PCM_STREAM_LAST + 1]; /* usage count */
|
||||
|
||||
unsigned int active;
|
||||
|
||||
@ -348,8 +348,27 @@ struct snd_soc_dai {
|
||||
unsigned int rx_mask;
|
||||
|
||||
struct list_head list;
|
||||
|
||||
/* bit field */
|
||||
unsigned int probed:1;
|
||||
unsigned int started:1;
|
||||
};
|
||||
|
||||
static inline struct snd_soc_pcm_stream *
|
||||
snd_soc_dai_get_pcm_stream(const struct snd_soc_dai *dai, int stream)
|
||||
{
|
||||
return (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||
&dai->driver->playback : &dai->driver->capture;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct snd_soc_dapm_widget *snd_soc_dai_get_widget(
|
||||
struct snd_soc_dai *dai, int stream)
|
||||
{
|
||||
return (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||
dai->playback_widget : dai->capture_widget;
|
||||
}
|
||||
|
||||
static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
|
||||
const struct snd_pcm_substream *ss)
|
||||
{
|
||||
@ -406,4 +425,23 @@ static inline int snd_soc_dai_set_sdw_stream(struct snd_soc_dai *dai,
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dai_get_sdw_stream() - Retrieves SDW stream from DAI
|
||||
* @dai: DAI
|
||||
* @direction: Stream direction(Playback/Capture)
|
||||
*
|
||||
* This routine only retrieves that was previously configured
|
||||
* with snd_soc_dai_get_sdw_stream()
|
||||
*
|
||||
* Returns pointer to stream or -ENOTSUPP if callback is not supported;
|
||||
*/
|
||||
static inline void *snd_soc_dai_get_sdw_stream(struct snd_soc_dai *dai,
|
||||
int direction)
|
||||
{
|
||||
if (dai->driver->ops->get_sdw_stream)
|
||||
return dai->driver->ops->get_sdw_stream(dai, direction);
|
||||
else
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -482,6 +482,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
|
||||
struct snd_soc_dapm_widget_list **list,
|
||||
bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,
|
||||
enum snd_soc_dapm_direction));
|
||||
void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list);
|
||||
|
||||
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
|
||||
struct snd_kcontrol *kcontrol);
|
||||
@ -691,6 +692,11 @@ struct snd_soc_dapm_widget_list {
|
||||
struct snd_soc_dapm_widget *widgets[0];
|
||||
};
|
||||
|
||||
#define for_each_dapm_widgets(list, i, widget) \
|
||||
for ((i) = 0; \
|
||||
(i) < list->num_widgets && (widget = list->widgets[i]); \
|
||||
(i)++)
|
||||
|
||||
struct snd_soc_dapm_stats {
|
||||
int power_checks;
|
||||
int path_checks;
|
||||
|
@ -132,17 +132,8 @@ int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
|
||||
struct snd_pcm_substream *
|
||||
snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream);
|
||||
|
||||
/* get the BE runtime state */
|
||||
enum snd_soc_dpcm_state
|
||||
snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream);
|
||||
|
||||
/* set the BE runtime state */
|
||||
void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
|
||||
enum snd_soc_dpcm_state state);
|
||||
|
||||
/* internal use only */
|
||||
int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
|
||||
int soc_dpcm_runtime_update(struct snd_soc_card *);
|
||||
/* update audio routing between PCMs and any DAI links */
|
||||
int snd_soc_dpcm_runtime_update(struct snd_soc_card *card);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
|
||||
@ -154,6 +145,7 @@ static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
|
||||
|
||||
int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
|
||||
int stream, struct snd_soc_dapm_widget_list **list_);
|
||||
void dpcm_path_put(struct snd_soc_dapm_widget_list **list);
|
||||
int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
|
||||
int stream, struct snd_soc_dapm_widget_list **list, int new);
|
||||
int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
@ -167,10 +159,4 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
|
||||
int event);
|
||||
|
||||
static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
|
||||
{
|
||||
kfree(*list);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -471,6 +471,9 @@ 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);
|
||||
|
||||
int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hardware *hw, int stream);
|
||||
|
||||
int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
|
||||
unsigned int dai_fmt);
|
||||
|
||||
@ -855,6 +858,11 @@ struct snd_soc_dai_link {
|
||||
((platform) = &link->platforms[i]); \
|
||||
(i)++)
|
||||
|
||||
#define for_each_link_cpus(link, i, cpu) \
|
||||
for ((i) = 0; \
|
||||
((i) < link->num_cpus) && ((cpu) = &link->cpus[i]); \
|
||||
(i)++)
|
||||
|
||||
/*
|
||||
* Sample 1 : Single CPU/Codec/Platform
|
||||
*
|
||||
@ -1058,6 +1066,7 @@ struct snd_soc_card {
|
||||
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;
|
||||
@ -1109,6 +1118,14 @@ struct snd_soc_card {
|
||||
#define for_each_card_components(card, component) \
|
||||
list_for_each_entry(component, &(card)->component_dev_list, card_list)
|
||||
|
||||
#define for_each_card_dapms(card, dapm) \
|
||||
list_for_each_entry(dapm, &card->dapm_list, list)
|
||||
|
||||
#define for_each_card_widgets(card, w)\
|
||||
list_for_each_entry(w, &card->widgets, list)
|
||||
#define for_each_card_widgets_safe(card, w, _w) \
|
||||
list_for_each_entry_safe(w, _w, &card->widgets, list)
|
||||
|
||||
/* SoC machine DAI configuration, glues a codec and cpu DAI together */
|
||||
struct snd_soc_pcm_runtime {
|
||||
struct device *dev;
|
||||
@ -1128,10 +1145,14 @@ struct snd_soc_pcm_runtime {
|
||||
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;
|
||||
unsigned int num_codecs;
|
||||
|
||||
struct snd_soc_dai **cpu_dais;
|
||||
unsigned int num_cpus;
|
||||
|
||||
struct delayed_work delayed_work;
|
||||
void (*close_delayed_work_func)(struct snd_soc_pcm_runtime *rtd);
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
@ -1148,16 +1169,31 @@ struct snd_soc_pcm_runtime {
|
||||
int num_components;
|
||||
struct snd_soc_component *components[0]; /* 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; \
|
||||
((i) < rtd->num_components) && ((component) = rtd->components[i]);\
|
||||
(i)++)
|
||||
#define for_each_rtd_codec_dai(rtd, i, dai)\
|
||||
for ((i) = 0; \
|
||||
((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \
|
||||
#define for_each_rtd_cpu_dais(rtd, i, dai) \
|
||||
for ((i) = 0; \
|
||||
((i) < rtd->num_cpus) && ((dai) = rtd->cpu_dais[i]); \
|
||||
(i)++)
|
||||
#define for_each_rtd_codec_dai_rollback(rtd, i, dai) \
|
||||
#define for_each_rtd_cpu_dais_rollback(rtd, i, dai) \
|
||||
for (; (--(i) >= 0) && ((dai) = rtd->cpu_dais[i]);)
|
||||
#define for_each_rtd_codec_dais(rtd, i, dai) \
|
||||
for ((i) = 0; \
|
||||
((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \
|
||||
(i)++)
|
||||
#define for_each_rtd_codec_dais_rollback(rtd, i, dai) \
|
||||
for (; (--(i) >= 0) && ((dai) = rtd->codec_dais[i]);)
|
||||
#define for_each_rtd_dais(rtd, i, dai) \
|
||||
for ((i) = 0; \
|
||||
((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \
|
||||
((dai) = (rtd)->dais[i]); \
|
||||
(i)++)
|
||||
|
||||
void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
|
@ -87,6 +87,15 @@ struct sof_ipc_dai_hda_params {
|
||||
uint32_t link_dma_ch;
|
||||
} __packed;
|
||||
|
||||
/* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */
|
||||
struct sof_ipc_dai_alh_params {
|
||||
struct sof_ipc_hdr hdr;
|
||||
uint32_t stream_id;
|
||||
|
||||
/* reserved for future use */
|
||||
uint32_t reserved[15];
|
||||
} __packed;
|
||||
|
||||
/* DMIC Configuration Request - SOF_IPC_DAI_DMIC_CONFIG */
|
||||
|
||||
/* This struct is defined per 2ch PDM controller available in the platform.
|
||||
@ -179,13 +188,4 @@ struct sof_ipc_dai_dmic_params {
|
||||
struct sof_ipc_dai_dmic_pdm_ctrl pdm[0];
|
||||
} __packed;
|
||||
|
||||
/* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */
|
||||
struct sof_ipc_dai_alh_params {
|
||||
struct sof_ipc_hdr hdr;
|
||||
uint32_t stream_id;
|
||||
|
||||
/* reserved for future use */
|
||||
uint32_t reserved[15];
|
||||
} __packed;
|
||||
|
||||
#endif
|
||||
|
@ -51,6 +51,7 @@
|
||||
#define SOF_IPC_GLB_TRACE_MSG SOF_GLB_TYPE(0x9U)
|
||||
#define SOF_IPC_GLB_GDB_DEBUG SOF_GLB_TYPE(0xAU)
|
||||
#define SOF_IPC_GLB_TEST_MSG SOF_GLB_TYPE(0xBU)
|
||||
#define SOF_IPC_GLB_PROBE SOF_GLB_TYPE(0xCU)
|
||||
|
||||
/*
|
||||
* DSP Command Message Types
|
||||
@ -102,6 +103,16 @@
|
||||
#define SOF_IPC_STREAM_VORBIS_PARAMS SOF_CMD_TYPE(0x010)
|
||||
#define SOF_IPC_STREAM_VORBIS_FREE SOF_CMD_TYPE(0x011)
|
||||
|
||||
/* probe */
|
||||
#define SOF_IPC_PROBE_INIT SOF_CMD_TYPE(0x001)
|
||||
#define SOF_IPC_PROBE_DEINIT SOF_CMD_TYPE(0x002)
|
||||
#define SOF_IPC_PROBE_DMA_ADD SOF_CMD_TYPE(0x003)
|
||||
#define SOF_IPC_PROBE_DMA_INFO SOF_CMD_TYPE(0x004)
|
||||
#define SOF_IPC_PROBE_DMA_REMOVE SOF_CMD_TYPE(0x005)
|
||||
#define SOF_IPC_PROBE_POINT_ADD SOF_CMD_TYPE(0x006)
|
||||
#define SOF_IPC_PROBE_POINT_INFO SOF_CMD_TYPE(0x007)
|
||||
#define SOF_IPC_PROBE_POINT_REMOVE SOF_CMD_TYPE(0x008)
|
||||
|
||||
/* trace */
|
||||
#define SOF_IPC_TRACE_DMA_PARAMS SOF_CMD_TYPE(0x001)
|
||||
#define SOF_IPC_TRACE_DMA_POSITION SOF_CMD_TYPE(0x002)
|
||||
|
@ -28,9 +28,9 @@
|
||||
|
||||
/* extended data types that can be appended onto end of sof_ipc_fw_ready */
|
||||
enum sof_ipc_ext_data {
|
||||
SOF_IPC_EXT_DMA_BUFFER = 0,
|
||||
SOF_IPC_EXT_WINDOW,
|
||||
SOF_IPC_EXT_CC_INFO,
|
||||
SOF_IPC_EXT_UNUSED = 0,
|
||||
SOF_IPC_EXT_WINDOW = 1,
|
||||
SOF_IPC_EXT_CC_INFO = 2,
|
||||
};
|
||||
|
||||
/* FW version - SOF_IPC_GLB_VERSION */
|
||||
@ -83,22 +83,6 @@ struct sof_ipc_ext_data_hdr {
|
||||
uint32_t type; /**< SOF_IPC_EXT_ */
|
||||
} __packed;
|
||||
|
||||
struct sof_ipc_dma_buffer_elem {
|
||||
struct sof_ipc_hdr hdr;
|
||||
uint32_t type; /**< SOF_IPC_REGION_ */
|
||||
uint32_t id; /**< platform specific - used to map to host memory */
|
||||
struct sof_ipc_host_buffer buffer;
|
||||
} __packed;
|
||||
|
||||
/* extended data DMA buffers for IPC, trace and debug */
|
||||
struct sof_ipc_dma_buffer_data {
|
||||
struct sof_ipc_ext_data_hdr ext_hdr;
|
||||
uint32_t num_buffers;
|
||||
|
||||
/* host files in buffer[n].buffer */
|
||||
struct sof_ipc_dma_buffer_elem buffer[];
|
||||
} __packed;
|
||||
|
||||
struct sof_ipc_window_elem {
|
||||
struct sof_ipc_hdr hdr;
|
||||
uint32_t type; /**< SOF_IPC_REGION_ */
|
||||
|
@ -53,9 +53,10 @@ struct sof_ipc_comp {
|
||||
uint32_t id;
|
||||
enum sof_comp_type type;
|
||||
uint32_t pipeline_id;
|
||||
uint32_t core;
|
||||
|
||||
/* reserved for future use */
|
||||
uint32_t reserved[2];
|
||||
uint32_t reserved[1];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define __LINUX_UAPI_SND_ASOC_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <sound/asound.h>
|
||||
|
||||
/*
|
||||
* Maximum number of channels topology kcontrol can represent.
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <sound/compress_params.h>
|
||||
|
||||
|
||||
#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 2)
|
||||
#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 2, 0)
|
||||
/**
|
||||
* struct snd_compressed_buffer - compressed buffer
|
||||
* @fragment_size: size of buffer fragment in bytes
|
||||
|
@ -75,7 +75,9 @@
|
||||
#define SND_AUDIOCODEC_G723_1 ((__u32) 0x0000000C)
|
||||
#define SND_AUDIOCODEC_G729 ((__u32) 0x0000000D)
|
||||
#define SND_AUDIOCODEC_BESPOKE ((__u32) 0x0000000E)
|
||||
#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_BESPOKE
|
||||
#define SND_AUDIOCODEC_ALAC ((__u32) 0x0000000F)
|
||||
#define SND_AUDIOCODEC_APE ((__u32) 0x00000010)
|
||||
#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_APE
|
||||
|
||||
/*
|
||||
* Profile and modes are listed with bit masks. This allows for a
|
||||
@ -142,6 +144,9 @@
|
||||
#define SND_AUDIOPROFILE_WMA8 ((__u32) 0x00000002)
|
||||
#define SND_AUDIOPROFILE_WMA9 ((__u32) 0x00000004)
|
||||
#define SND_AUDIOPROFILE_WMA10 ((__u32) 0x00000008)
|
||||
#define SND_AUDIOPROFILE_WMA9_PRO ((__u32) 0x00000010)
|
||||
#define SND_AUDIOPROFILE_WMA9_LOSSLESS ((__u32) 0x00000020)
|
||||
#define SND_AUDIOPROFILE_WMA10_LOSSLESS ((__u32) 0x00000040)
|
||||
|
||||
#define SND_AUDIOMODE_WMA_LEVEL1 ((__u32) 0x00000001)
|
||||
#define SND_AUDIOMODE_WMA_LEVEL2 ((__u32) 0x00000002)
|
||||
@ -326,6 +331,33 @@ struct snd_dec_flac {
|
||||
__u16 reserved;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct snd_dec_wma {
|
||||
__u32 encoder_option;
|
||||
__u32 adv_encoder_option;
|
||||
__u32 adv_encoder_option2;
|
||||
__u32 reserved;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct snd_dec_alac {
|
||||
__u32 frame_length;
|
||||
__u8 compatible_version;
|
||||
__u8 pb;
|
||||
__u8 mb;
|
||||
__u8 kb;
|
||||
__u32 max_run;
|
||||
__u32 max_frame_bytes;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct snd_dec_ape {
|
||||
__u16 compatible_version;
|
||||
__u16 compression_level;
|
||||
__u32 format_flags;
|
||||
__u32 blocks_per_frame;
|
||||
__u32 final_frame_blocks;
|
||||
__u32 total_frames;
|
||||
__u32 seek_table_present;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
union snd_codec_options {
|
||||
struct snd_enc_wma wma;
|
||||
struct snd_enc_vorbis vorbis;
|
||||
@ -333,6 +365,9 @@ union snd_codec_options {
|
||||
struct snd_enc_flac flac;
|
||||
struct snd_enc_generic generic;
|
||||
struct snd_dec_flac flac_d;
|
||||
struct snd_dec_wma wma_d;
|
||||
struct snd_dec_alac alac_d;
|
||||
struct snd_dec_ape ape_d;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
/** struct snd_codec_desc - description of codec capabilities
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
/* SOF ABI version major, minor and patch numbers */
|
||||
#define SOF_ABI_MAJOR 3
|
||||
#define SOF_ABI_MINOR 12
|
||||
#define SOF_ABI_MINOR 13
|
||||
#define SOF_ABI_PATCH 0
|
||||
|
||||
/* SOF ABI version number. Format within 32bit word is MMmmmppp */
|
||||
|
@ -38,7 +38,7 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct dma_slave_config config;
|
||||
int ret;
|
||||
|
||||
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
dma_params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
|
||||
if (!dma_params)
|
||||
return 0;
|
||||
|
||||
@ -47,7 +47,7 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
return ret;
|
||||
|
||||
snd_dmaengine_pcm_set_config_from_dai_data(substream,
|
||||
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
|
||||
snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream),
|
||||
&config);
|
||||
|
||||
ret = dmaengine_slave_config(chan, &config);
|
||||
@ -95,7 +95,7 @@ int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
|
||||
|
||||
runtime->hw = pxa2xx_pcm_hardware;
|
||||
|
||||
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
dma_params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
|
||||
if (!dma_params)
|
||||
return 0;
|
||||
|
||||
@ -120,7 +120,7 @@ int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
|
||||
return ret;
|
||||
|
||||
return snd_dmaengine_pcm_open(
|
||||
substream, dma_request_slave_channel(rtd->cpu_dai->dev,
|
||||
substream, dma_request_slave_channel(asoc_rtd_to_cpu(rtd, 0)->dev,
|
||||
dma_params->chan_name));
|
||||
}
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_open);
|
||||
|
@ -488,6 +488,48 @@ out:
|
||||
}
|
||||
#endif /* !COMPR_CODEC_CAPS_OVERFLOW */
|
||||
|
||||
int snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size)
|
||||
{
|
||||
struct snd_dma_buffer *dmab;
|
||||
int ret;
|
||||
|
||||
if (snd_BUG_ON(!(stream) || !(stream)->runtime))
|
||||
return -EINVAL;
|
||||
dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
|
||||
if (!dmab)
|
||||
return -ENOMEM;
|
||||
dmab->dev = stream->dma_buffer.dev;
|
||||
ret = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev, size, dmab);
|
||||
if (ret < 0) {
|
||||
kfree(dmab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
snd_compr_set_runtime_buffer(stream, dmab);
|
||||
stream->runtime->dma_bytes = size;
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_compr_malloc_pages);
|
||||
|
||||
int snd_compr_free_pages(struct snd_compr_stream *stream)
|
||||
{
|
||||
struct snd_compr_runtime *runtime = stream->runtime;
|
||||
|
||||
if (snd_BUG_ON(!(stream) || !(stream)->runtime))
|
||||
return -EINVAL;
|
||||
if (runtime->dma_area == NULL)
|
||||
return 0;
|
||||
if (runtime->dma_buffer_p != &stream->dma_buffer) {
|
||||
/* It's a newly allocated buffer. Release it now. */
|
||||
snd_dma_free_pages(runtime->dma_buffer_p);
|
||||
kfree(runtime->dma_buffer_p);
|
||||
}
|
||||
|
||||
snd_compr_set_runtime_buffer(stream, NULL);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_compr_free_pages);
|
||||
|
||||
/* revisit this with snd_pcm_preallocate_xxx */
|
||||
static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
|
||||
struct snd_compr_params *params)
|
||||
|
@ -237,3 +237,24 @@ void snd_device_free_all(struct snd_card *card)
|
||||
list_for_each_entry_safe_reverse(dev, next, &card->devices, list)
|
||||
__snd_device_free(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_device_get_state - Get the current state of the given device
|
||||
* @card: the card instance
|
||||
* @device_data: the data pointer to release
|
||||
*
|
||||
* Returns the current state of the given device object. For the valid
|
||||
* device, either @SNDRV_DEV_BUILD, @SNDRV_DEV_REGISTERED or
|
||||
* @SNDRV_DEV_DISCONNECTED is returned.
|
||||
* Or for a non-existing device, -1 is returned as an error.
|
||||
*/
|
||||
int snd_device_get_state(struct snd_card *card, void *device_data)
|
||||
{
|
||||
struct snd_device *dev;
|
||||
|
||||
dev = look_for_dev(card, device_data);
|
||||
if (dev)
|
||||
return dev->state;
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_device_get_state);
|
||||
|
@ -604,7 +604,7 @@ int snd_info_card_free(struct snd_card *card)
|
||||
*/
|
||||
int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
|
||||
{
|
||||
int c = -1;
|
||||
int c;
|
||||
|
||||
if (snd_BUG_ON(!buffer || !buffer->buffer))
|
||||
return 1;
|
||||
|
@ -884,20 +884,17 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
|
||||
sformat = snd_pcm_plug_slave_format(format, sformat_mask);
|
||||
|
||||
if ((__force int)sformat < 0 ||
|
||||
!snd_mask_test(sformat_mask, (__force int)sformat)) {
|
||||
for (sformat = (__force snd_pcm_format_t)0;
|
||||
(__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST;
|
||||
sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) {
|
||||
if (snd_mask_test(sformat_mask, (__force int)sformat) &&
|
||||
!snd_mask_test_format(sformat_mask, sformat)) {
|
||||
pcm_for_each_format(sformat) {
|
||||
if (snd_mask_test_format(sformat_mask, sformat) &&
|
||||
snd_pcm_oss_format_to(sformat) >= 0)
|
||||
break;
|
||||
}
|
||||
if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) {
|
||||
pcm_dbg(substream->pcm, "Cannot find a format!!!\n");
|
||||
err = -EINVAL;
|
||||
goto failure;
|
||||
goto format_found;
|
||||
}
|
||||
pcm_dbg(substream->pcm, "Cannot find a format!!!\n");
|
||||
err = -EINVAL;
|
||||
goto failure;
|
||||
}
|
||||
format_found:
|
||||
err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0);
|
||||
if (err < 0)
|
||||
goto failure;
|
||||
@ -1220,8 +1217,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&runtime->oss.params_lock);
|
||||
ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
|
||||
frames, in_kernel);
|
||||
mutex_lock(&runtime->oss.params_lock);
|
||||
if (ret != -EPIPE && ret != -ESTRPIPE)
|
||||
break;
|
||||
/* test, if we can't store new data, because the stream */
|
||||
@ -1257,8 +1256,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
|
||||
ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
|
||||
if (ret < 0)
|
||||
break;
|
||||
mutex_unlock(&runtime->oss.params_lock);
|
||||
ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
|
||||
frames, in_kernel);
|
||||
mutex_lock(&runtime->oss.params_lock);
|
||||
if (ret == -EPIPE) {
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
|
||||
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
|
||||
|
@ -196,82 +196,74 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t calc_dst_frames(struct snd_pcm_substream *plug,
|
||||
snd_pcm_sframes_t frames)
|
||||
{
|
||||
struct snd_pcm_plugin *plugin, *plugin_next;
|
||||
|
||||
plugin = snd_pcm_plug_first(plug);
|
||||
while (plugin && frames > 0) {
|
||||
plugin_next = plugin->next;
|
||||
if (plugin->dst_frames) {
|
||||
frames = plugin->dst_frames(plugin, frames);
|
||||
if (frames < 0)
|
||||
return frames;
|
||||
}
|
||||
if (frames > plugin->buf_frames)
|
||||
frames = plugin->buf_frames;
|
||||
plugin = plugin_next;
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t calc_src_frames(struct snd_pcm_substream *plug,
|
||||
snd_pcm_sframes_t frames)
|
||||
{
|
||||
struct snd_pcm_plugin *plugin, *plugin_prev;
|
||||
|
||||
plugin = snd_pcm_plug_last(plug);
|
||||
while (plugin && frames > 0) {
|
||||
if (frames > plugin->buf_frames)
|
||||
frames = plugin->buf_frames;
|
||||
plugin_prev = plugin->prev;
|
||||
if (plugin->src_frames) {
|
||||
frames = plugin->src_frames(plugin, frames);
|
||||
if (frames < 0)
|
||||
return frames;
|
||||
}
|
||||
plugin = plugin_prev;
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames)
|
||||
{
|
||||
struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
|
||||
int stream;
|
||||
|
||||
if (snd_BUG_ON(!plug))
|
||||
return -ENXIO;
|
||||
if (drv_frames == 0)
|
||||
return 0;
|
||||
stream = snd_pcm_plug_stream(plug);
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
plugin = snd_pcm_plug_last(plug);
|
||||
while (plugin && drv_frames > 0) {
|
||||
if (drv_frames > plugin->buf_frames)
|
||||
drv_frames = plugin->buf_frames;
|
||||
plugin_prev = plugin->prev;
|
||||
if (plugin->src_frames)
|
||||
drv_frames = plugin->src_frames(plugin, drv_frames);
|
||||
plugin = plugin_prev;
|
||||
}
|
||||
} else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
plugin = snd_pcm_plug_first(plug);
|
||||
while (plugin && drv_frames > 0) {
|
||||
plugin_next = plugin->next;
|
||||
if (plugin->dst_frames)
|
||||
drv_frames = plugin->dst_frames(plugin, drv_frames);
|
||||
if (drv_frames > plugin->buf_frames)
|
||||
drv_frames = plugin->buf_frames;
|
||||
plugin = plugin_next;
|
||||
}
|
||||
} else
|
||||
switch (snd_pcm_plug_stream(plug)) {
|
||||
case SNDRV_PCM_STREAM_PLAYBACK:
|
||||
return calc_src_frames(plug, drv_frames);
|
||||
case SNDRV_PCM_STREAM_CAPTURE:
|
||||
return calc_dst_frames(plug, drv_frames);
|
||||
default:
|
||||
snd_BUG();
|
||||
return drv_frames;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t clt_frames)
|
||||
{
|
||||
struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
|
||||
snd_pcm_sframes_t frames;
|
||||
int stream;
|
||||
|
||||
if (snd_BUG_ON(!plug))
|
||||
return -ENXIO;
|
||||
if (clt_frames == 0)
|
||||
return 0;
|
||||
frames = clt_frames;
|
||||
stream = snd_pcm_plug_stream(plug);
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
plugin = snd_pcm_plug_first(plug);
|
||||
while (plugin && frames > 0) {
|
||||
plugin_next = plugin->next;
|
||||
if (plugin->dst_frames) {
|
||||
frames = plugin->dst_frames(plugin, frames);
|
||||
if (frames < 0)
|
||||
return frames;
|
||||
}
|
||||
if (frames > plugin->buf_frames)
|
||||
frames = plugin->buf_frames;
|
||||
plugin = plugin_next;
|
||||
}
|
||||
} else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
plugin = snd_pcm_plug_last(plug);
|
||||
while (plugin) {
|
||||
if (frames > plugin->buf_frames)
|
||||
frames = plugin->buf_frames;
|
||||
plugin_prev = plugin->prev;
|
||||
if (plugin->src_frames) {
|
||||
frames = plugin->src_frames(plugin, frames);
|
||||
if (frames < 0)
|
||||
return frames;
|
||||
}
|
||||
plugin = plugin_prev;
|
||||
}
|
||||
} else
|
||||
switch (snd_pcm_plug_stream(plug)) {
|
||||
case SNDRV_PCM_STREAM_PLAYBACK:
|
||||
return calc_dst_frames(plug, clt_frames);
|
||||
case SNDRV_PCM_STREAM_CAPTURE:
|
||||
return calc_src_frames(plug, clt_frames);
|
||||
default:
|
||||
snd_BUG();
|
||||
return frames;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int snd_pcm_plug_formats(const struct snd_mask *mask,
|
||||
|
@ -47,7 +47,7 @@ struct rate_priv {
|
||||
unsigned int pos;
|
||||
rate_f func;
|
||||
snd_pcm_sframes_t old_src_frames, old_dst_frames;
|
||||
struct rate_channel channels[0];
|
||||
struct rate_channel channels[];
|
||||
};
|
||||
|
||||
static void rate_init(struct snd_pcm_plugin *plugin)
|
||||
|
@ -1019,7 +1019,7 @@ static ssize_t show_pcm_class(struct device *dev,
|
||||
str = "none";
|
||||
else
|
||||
str = strs[pcm->dev_class];
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", str);
|
||||
return sprintf(buf, "%s\n", str);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(pcm_class, 0444, show_pcm_class, NULL);
|
||||
|
@ -240,6 +240,7 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue);
|
||||
snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct dma_tx_state state;
|
||||
enum dma_status status;
|
||||
unsigned int buf_size;
|
||||
@ -250,9 +251,12 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
|
||||
buf_size = snd_pcm_lib_buffer_bytes(substream);
|
||||
if (state.residue > 0 && state.residue <= buf_size)
|
||||
pos = buf_size - state.residue;
|
||||
|
||||
runtime->delay = bytes_to_frames(runtime,
|
||||
state.in_flight_bytes);
|
||||
}
|
||||
|
||||
return bytes_to_frames(substream->runtime, pos);
|
||||
return bytes_to_frames(runtime, pos);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
|
||||
|
||||
@ -426,7 +430,7 @@ int snd_dmaengine_pcm_refine_runtime_hwparams(
|
||||
* default assumption is that it supports 1, 2 and 4 bytes
|
||||
* widths.
|
||||
*/
|
||||
for (i = SNDRV_PCM_FORMAT_FIRST; i <= SNDRV_PCM_FORMAT_LAST; i++) {
|
||||
pcm_for_each_format(i) {
|
||||
int bits = snd_pcm_format_physical_width(i);
|
||||
|
||||
/*
|
||||
|
@ -42,6 +42,11 @@ struct pcm_format_data {
|
||||
/* we do lots of calculations on snd_pcm_format_t; shut up sparse */
|
||||
#define INT __force int
|
||||
|
||||
static bool valid_format(snd_pcm_format_t format)
|
||||
{
|
||||
return (INT)format >= 0 && (INT)format <= (INT)SNDRV_PCM_FORMAT_LAST;
|
||||
}
|
||||
|
||||
static const struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
|
||||
[SNDRV_PCM_FORMAT_S8] = {
|
||||
.width = 8, .phys = 8, .le = -1, .signd = 1,
|
||||
@ -259,7 +264,7 @@ static const struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] =
|
||||
int snd_pcm_format_signed(snd_pcm_format_t format)
|
||||
{
|
||||
int val;
|
||||
if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
if ((val = pcm_formats[(INT)format].signd) < 0)
|
||||
return -EINVAL;
|
||||
@ -307,7 +312,7 @@ EXPORT_SYMBOL(snd_pcm_format_linear);
|
||||
int snd_pcm_format_little_endian(snd_pcm_format_t format)
|
||||
{
|
||||
int val;
|
||||
if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
if ((val = pcm_formats[(INT)format].le) < 0)
|
||||
return -EINVAL;
|
||||
@ -343,7 +348,7 @@ EXPORT_SYMBOL(snd_pcm_format_big_endian);
|
||||
int snd_pcm_format_width(snd_pcm_format_t format)
|
||||
{
|
||||
int val;
|
||||
if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
if ((val = pcm_formats[(INT)format].width) == 0)
|
||||
return -EINVAL;
|
||||
@ -361,7 +366,7 @@ EXPORT_SYMBOL(snd_pcm_format_width);
|
||||
int snd_pcm_format_physical_width(snd_pcm_format_t format)
|
||||
{
|
||||
int val;
|
||||
if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
if ((val = pcm_formats[(INT)format].phys) == 0)
|
||||
return -EINVAL;
|
||||
@ -394,7 +399,7 @@ EXPORT_SYMBOL(snd_pcm_format_size);
|
||||
*/
|
||||
const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
|
||||
{
|
||||
if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
|
||||
if (!valid_format(format))
|
||||
return NULL;
|
||||
if (! pcm_formats[(INT)format].phys)
|
||||
return NULL;
|
||||
@ -418,7 +423,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
|
||||
unsigned char *dst;
|
||||
const unsigned char *pat;
|
||||
|
||||
if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
if (samples == 0)
|
||||
return 0;
|
||||
@ -474,32 +479,32 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
|
||||
EXPORT_SYMBOL(snd_pcm_format_set_silence);
|
||||
|
||||
/**
|
||||
* snd_pcm_limit_hw_rates - determine rate_min/rate_max fields
|
||||
* @runtime: the runtime instance
|
||||
* snd_pcm_hw_limit_rates - determine rate_min/rate_max fields
|
||||
* @hw: the pcm hw instance
|
||||
*
|
||||
* Determines the rate_min and rate_max fields from the rates bits of
|
||||
* the given runtime->hw.
|
||||
* the given hw.
|
||||
*
|
||||
* Return: Zero if successful.
|
||||
*/
|
||||
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
|
||||
int snd_pcm_hw_limit_rates(struct snd_pcm_hardware *hw)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (int)snd_pcm_known_rates.count; i++) {
|
||||
if (runtime->hw.rates & (1 << i)) {
|
||||
runtime->hw.rate_min = snd_pcm_known_rates.list[i];
|
||||
if (hw->rates & (1 << i)) {
|
||||
hw->rate_min = snd_pcm_known_rates.list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = (int)snd_pcm_known_rates.count - 1; i >= 0; i--) {
|
||||
if (runtime->hw.rates & (1 << i)) {
|
||||
runtime->hw.rate_max = snd_pcm_known_rates.list[i];
|
||||
if (hw->rates & (1 << i)) {
|
||||
hw->rate_max = snd_pcm_known_rates.list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
|
||||
EXPORT_SYMBOL(snd_pcm_hw_limit_rates);
|
||||
|
||||
/**
|
||||
* snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit
|
||||
|
@ -228,6 +228,9 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* macro for simplified cast */
|
||||
#define PARAM_MASK_BIT(b) (1U << (__force int)(b))
|
||||
|
||||
static bool hw_support_mmap(struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
|
||||
@ -257,7 +260,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
|
||||
return -EINVAL;
|
||||
|
||||
/* This parameter is not requested to change by a caller. */
|
||||
if (!(params->rmask & (1 << k)))
|
||||
if (!(params->rmask & PARAM_MASK_BIT(k)))
|
||||
continue;
|
||||
|
||||
if (trace_hw_mask_param_enabled())
|
||||
@ -271,7 +274,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
|
||||
|
||||
/* Set corresponding flag so that the caller gets it. */
|
||||
trace_hw_mask_param(substream, k, 0, &old_mask, m);
|
||||
params->cmask |= 1 << k;
|
||||
params->cmask |= PARAM_MASK_BIT(k);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -293,7 +296,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
|
||||
return -EINVAL;
|
||||
|
||||
/* This parameter is not requested to change by a caller. */
|
||||
if (!(params->rmask & (1 << k)))
|
||||
if (!(params->rmask & PARAM_MASK_BIT(k)))
|
||||
continue;
|
||||
|
||||
if (trace_hw_interval_param_enabled())
|
||||
@ -307,7 +310,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
|
||||
|
||||
/* Set corresponding flag so that the caller gets it. */
|
||||
trace_hw_interval_param(substream, k, 0, &old_interval, i);
|
||||
params->cmask |= 1 << k;
|
||||
params->cmask |= PARAM_MASK_BIT(k);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -349,7 +352,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
|
||||
* have 0 so that the parameters are never changed anymore.
|
||||
*/
|
||||
for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
|
||||
vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
|
||||
vstamps[k] = (params->rmask & PARAM_MASK_BIT(k)) ? 1 : 0;
|
||||
|
||||
/* Due to the above design, actual sequence number starts at 2. */
|
||||
stamp = 2;
|
||||
@ -417,7 +420,7 @@ retry:
|
||||
hw_param_interval(params, r->var));
|
||||
}
|
||||
|
||||
params->cmask |= (1 << r->var);
|
||||
params->cmask |= PARAM_MASK_BIT(r->var);
|
||||
vstamps[r->var] = stamp;
|
||||
again = true;
|
||||
}
|
||||
@ -486,9 +489,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
|
||||
|
||||
params->info = 0;
|
||||
params->fifo_size = 0;
|
||||
if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
|
||||
if (params->rmask & PARAM_MASK_BIT(SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
|
||||
params->msbits = 0;
|
||||
if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
|
||||
if (params->rmask & PARAM_MASK_BIT(SNDRV_PCM_HW_PARAM_RATE)) {
|
||||
params->rate_num = 0;
|
||||
params->rate_den = 0;
|
||||
}
|
||||
@ -2293,21 +2296,21 @@ static int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params,
|
||||
static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
unsigned int k;
|
||||
snd_pcm_format_t k;
|
||||
const struct snd_interval *i =
|
||||
hw_param_interval_c(params, rule->deps[0]);
|
||||
struct snd_mask m;
|
||||
struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
snd_mask_any(&m);
|
||||
for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
|
||||
pcm_for_each_format(k) {
|
||||
int bits;
|
||||
if (! snd_mask_test(mask, k))
|
||||
if (!snd_mask_test_format(mask, k))
|
||||
continue;
|
||||
bits = snd_pcm_format_physical_width(k);
|
||||
if (bits <= 0)
|
||||
continue; /* ignore invalid formats */
|
||||
if ((unsigned)bits < i->min || (unsigned)bits > i->max)
|
||||
snd_mask_reset(&m, k);
|
||||
snd_mask_reset(&m, (__force unsigned)k);
|
||||
}
|
||||
return snd_mask_refine(mask, &m);
|
||||
}
|
||||
@ -2316,14 +2319,15 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
struct snd_interval t;
|
||||
unsigned int k;
|
||||
snd_pcm_format_t k;
|
||||
|
||||
t.min = UINT_MAX;
|
||||
t.max = 0;
|
||||
t.openmin = 0;
|
||||
t.openmax = 0;
|
||||
for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
|
||||
pcm_for_each_format(k) {
|
||||
int bits;
|
||||
if (! snd_mask_test(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k))
|
||||
if (!snd_mask_test_format(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k))
|
||||
continue;
|
||||
bits = snd_pcm_format_physical_width(k);
|
||||
if (bits <= 0)
|
||||
@ -2505,16 +2509,16 @@ static int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
|
||||
unsigned int mask = 0;
|
||||
|
||||
if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
|
||||
mask |= 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED;
|
||||
mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
|
||||
mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED;
|
||||
mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
|
||||
if (hw_support_mmap(substream)) {
|
||||
if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
|
||||
mask |= 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
|
||||
mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||
if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
|
||||
mask |= 1 << SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED;
|
||||
mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
||||
if (hw->info & SNDRV_PCM_INFO_COMPLEX)
|
||||
mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX;
|
||||
mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_MMAP_COMPLEX);
|
||||
}
|
||||
err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask);
|
||||
if (err < 0)
|
||||
@ -2524,7 +2528,8 @@ static int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD);
|
||||
err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT,
|
||||
PARAM_MASK_BIT(SNDRV_PCM_SUBFORMAT_STD));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -118,7 +118,7 @@ struct loopback_cable {
|
||||
struct loopback_setup {
|
||||
unsigned int notify: 1;
|
||||
unsigned int rate_shift;
|
||||
unsigned int format;
|
||||
snd_pcm_format_t format;
|
||||
unsigned int rate;
|
||||
unsigned int channels;
|
||||
struct snd_ctl_elem_id active_id;
|
||||
@ -1432,7 +1432,7 @@ static int loopback_format_info(struct snd_kcontrol *kcontrol,
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = 1;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = SNDRV_PCM_FORMAT_LAST;
|
||||
uinfo->value.integer.max = (__force int)SNDRV_PCM_FORMAT_LAST;
|
||||
uinfo->value.integer.step = 1;
|
||||
return 0;
|
||||
}
|
||||
@ -1443,7 +1443,7 @@ static int loopback_format_get(struct snd_kcontrol *kcontrol,
|
||||
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
ucontrol->value.integer.value[0] =
|
||||
loopback->setup[kcontrol->id.subdevice]
|
||||
(__force int)loopback->setup[kcontrol->id.subdevice]
|
||||
[kcontrol->id.device].format;
|
||||
return 0;
|
||||
}
|
||||
|
@ -901,10 +901,10 @@ static int snd_card_dummy_new_mixer(struct snd_dummy *dummy)
|
||||
static void print_formats(struct snd_dummy *dummy,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
int i;
|
||||
snd_pcm_format_t i;
|
||||
|
||||
for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
|
||||
if (dummy->pcm_hw.formats & (1ULL << i))
|
||||
pcm_for_each_format(i) {
|
||||
if (dummy->pcm_hw.formats & pcm_format_to_bits(i))
|
||||
snd_iprintf(buffer, " %s", snd_pcm_format_name(i));
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +509,7 @@ MODULE_DEVICE_TABLE(ieee1394, bebob_id_table);
|
||||
static struct fw_driver bebob_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "snd-bebob",
|
||||
.name = KBUILD_MODNAME,
|
||||
.bus = &fw_bus_type,
|
||||
},
|
||||
.probe = bebob_probe,
|
||||
|
@ -192,7 +192,7 @@ MODULE_DEVICE_TABLE(ieee1394, snd_dg00x_id_table);
|
||||
static struct fw_driver dg00x_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "snd-firewire-digi00x",
|
||||
.name = KBUILD_MODNAME,
|
||||
.bus = &fw_bus_type,
|
||||
},
|
||||
.probe = snd_dg00x_probe,
|
||||
|
@ -224,7 +224,7 @@ MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table);
|
||||
static struct fw_driver ff_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "snd-fireface",
|
||||
.name = KBUILD_MODNAME,
|
||||
.bus = &fw_bus_type,
|
||||
},
|
||||
.probe = snd_ff_probe,
|
||||
|
@ -362,7 +362,7 @@ MODULE_DEVICE_TABLE(ieee1394, efw_id_table);
|
||||
static struct fw_driver efw_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "snd-fireworks",
|
||||
.name = KBUILD_MODNAME,
|
||||
.bus = &fw_bus_type,
|
||||
},
|
||||
.probe = efw_probe,
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
static long tscm_hwdep_read_locked(struct snd_tscm *tscm, char __user *buf,
|
||||
long count, loff_t *offset)
|
||||
__releases(&tscm->lock)
|
||||
{
|
||||
struct snd_firewire_event_lock_status event = {
|
||||
.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS,
|
||||
@ -36,6 +37,7 @@ static long tscm_hwdep_read_locked(struct snd_tscm *tscm, char __user *buf,
|
||||
|
||||
static long tscm_hwdep_read_queue(struct snd_tscm *tscm, char __user *buf,
|
||||
long remained, loff_t *offset)
|
||||
__releases(&tscm->lock)
|
||||
{
|
||||
char __user *pos = buf;
|
||||
unsigned int type = SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL;
|
||||
|
@ -224,7 +224,7 @@ MODULE_DEVICE_TABLE(ieee1394, snd_tscm_id_table);
|
||||
static struct fw_driver tscm_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "snd-firewire-tascam",
|
||||
.name = KBUILD_MODNAME,
|
||||
.bus = &fw_bus_type,
|
||||
},
|
||||
.probe = snd_tscm_probe,
|
||||
|
@ -204,7 +204,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_device_set_chip_name);
|
||||
*/
|
||||
int snd_hdac_codec_modalias(struct hdac_device *codec, char *buf, size_t size)
|
||||
{
|
||||
return snprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n",
|
||||
return scnprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n",
|
||||
codec->vendor_id, codec->revision_id, codec->type);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_codec_modalias);
|
||||
|
@ -435,7 +435,7 @@ enum {
|
||||
#define LOOP_WRITE(rec, offset, _buf, count, mode) \
|
||||
do { \
|
||||
struct snd_emu8000 *emu = (rec)->emu; \
|
||||
unsigned short *buf = (unsigned short *)(_buf); \
|
||||
unsigned short *buf = (__force unsigned short *)(_buf); \
|
||||
snd_emu8000_write_wait(emu, 1); \
|
||||
EMU8000_SMALW_WRITE(emu, offset); \
|
||||
while (count > 0) { \
|
||||
@ -492,7 +492,7 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
|
||||
#define LOOP_WRITE(rec, pos, _buf, count, mode) \
|
||||
do { \
|
||||
struct snd_emu8000 *emu = rec->emu; \
|
||||
unsigned short *buf = (unsigned short *)(_buf); \
|
||||
unsigned short *buf = (__force unsigned short *)(_buf); \
|
||||
snd_emu8000_write_wait(emu, 1); \
|
||||
EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); \
|
||||
if (rec->voices > 1) \
|
||||
|
@ -1070,7 +1070,7 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_ali *codec = snd_pcm_substream_chip(substream);
|
||||
struct snd_pcm_substream *s;
|
||||
unsigned int what, whati, capture_flag;
|
||||
unsigned int what, whati;
|
||||
struct snd_ali_voice *pvoice, *evoice;
|
||||
unsigned int val;
|
||||
int do_start;
|
||||
@ -1088,7 +1088,7 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
what = whati = capture_flag = 0;
|
||||
what = whati = 0;
|
||||
snd_pcm_group_for_each_entry(s, substream) {
|
||||
if ((struct snd_ali *) snd_pcm_substream_chip(s) == codec) {
|
||||
pvoice = s->runtime->private_data;
|
||||
@ -1110,8 +1110,6 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream,
|
||||
evoice->running = 0;
|
||||
}
|
||||
snd_pcm_trigger_done(s, substream);
|
||||
if (pvoice->mode)
|
||||
capture_flag = 1;
|
||||
}
|
||||
}
|
||||
spin_lock(&codec->reg_lock);
|
||||
|
@ -1789,6 +1789,7 @@ int snd_emu10k1_create(struct snd_card *card,
|
||||
int idx, err;
|
||||
int is_audigy;
|
||||
size_t page_table_size;
|
||||
__le32 *pgtbl;
|
||||
unsigned int silent_page;
|
||||
const struct snd_emu_chip_details *c;
|
||||
static const struct snd_device_ops ops = {
|
||||
@ -2009,8 +2010,9 @@ int snd_emu10k1_create(struct snd_card *card,
|
||||
/* Clear silent pages and set up pointers */
|
||||
memset(emu->silent_page.area, 0, emu->silent_page.bytes);
|
||||
silent_page = emu->silent_page.addr << emu->address_mode;
|
||||
pgtbl = (__le32 *)emu->ptb_pages.area;
|
||||
for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++)
|
||||
((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
|
||||
pgtbl[idx] = cpu_to_le32(silent_page | idx);
|
||||
|
||||
/* set up voice indices */
|
||||
for (idx = 0; idx < NUM_G; idx++) {
|
||||
|
@ -184,6 +184,7 @@ comment "Set to Y if you want auto-loading the codec driver"
|
||||
config SND_HDA_CODEC_CA0132_DSP
|
||||
bool "Support new DSP code for CA0132 codec"
|
||||
depends on SND_HDA_CODEC_CA0132
|
||||
default y
|
||||
select SND_HDA_DSP_LOADER
|
||||
select FW_LOADER
|
||||
help
|
||||
|
@ -88,7 +88,7 @@ struct hda_conn_list {
|
||||
struct list_head list;
|
||||
int len;
|
||||
hda_nid_t nid;
|
||||
hda_nid_t conns[0];
|
||||
hda_nid_t conns[];
|
||||
};
|
||||
|
||||
/* look up the cached results */
|
||||
|
@ -373,7 +373,7 @@ static int azx_get_sync_time(ktime_t *device,
|
||||
u32 wallclk_ctr, wallclk_cycles;
|
||||
bool direction;
|
||||
u32 dma_select;
|
||||
u32 timeout = 200;
|
||||
u32 timeout;
|
||||
u32 retry_count = 0;
|
||||
|
||||
runtime = substream->runtime;
|
||||
|
@ -1180,6 +1180,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
|
||||
SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI),
|
||||
SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
|
||||
SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI),
|
||||
SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI),
|
||||
SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D),
|
||||
SND_PCI_QUIRK(0x1102, 0x0051, "Sound Blaster AE-5", QUIRK_AE5),
|
||||
{}
|
||||
@ -2698,7 +2699,7 @@ struct dsp_image_seg {
|
||||
u32 magic;
|
||||
u32 chip_addr;
|
||||
u32 count;
|
||||
u32 data[0];
|
||||
u32 data[];
|
||||
};
|
||||
|
||||
static const u32 g_magic_value = 0x4c46584d;
|
||||
|
@ -154,7 +154,6 @@ struct hdmi_spec {
|
||||
struct hda_multi_out multiout;
|
||||
struct hda_pcm_stream pcm_playback;
|
||||
|
||||
bool use_jack_detect; /* jack detection enabled */
|
||||
bool use_acomp_notifier; /* use eld_notify callback for hotplug */
|
||||
bool acomp_registered; /* audio component registered in this driver */
|
||||
struct drm_audio_component_audio_ops drm_audio_ops;
|
||||
@ -753,7 +752,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
|
||||
* Unsolicited events
|
||||
*/
|
||||
|
||||
static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
|
||||
static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
|
||||
|
||||
static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid,
|
||||
int dev_id)
|
||||
@ -764,8 +763,7 @@ static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid,
|
||||
if (pin_idx < 0)
|
||||
return;
|
||||
mutex_lock(&spec->pcm_lock);
|
||||
if (hdmi_present_sense(get_pin(spec, pin_idx), 1))
|
||||
snd_hda_jack_report_sync(codec);
|
||||
hdmi_present_sense(get_pin(spec, pin_idx), 1);
|
||||
mutex_unlock(&spec->pcm_lock);
|
||||
}
|
||||
|
||||
@ -779,21 +777,9 @@ static void jack_callback(struct hda_codec *codec,
|
||||
check_presence_and_report(codec, jack->nid, jack->dev_id);
|
||||
}
|
||||
|
||||
static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
|
||||
static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res,
|
||||
struct hda_jack_tbl *jack)
|
||||
{
|
||||
int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
|
||||
struct hda_jack_tbl *jack;
|
||||
|
||||
if (codec->dp_mst) {
|
||||
int dev_entry =
|
||||
(res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
|
||||
|
||||
jack = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry);
|
||||
} else {
|
||||
jack = snd_hda_jack_tbl_get_from_tag(codec, tag, 0);
|
||||
}
|
||||
if (!jack)
|
||||
return;
|
||||
jack->jack_dirty = 1;
|
||||
|
||||
codec_dbg(codec,
|
||||
@ -853,7 +839,7 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
|
||||
}
|
||||
|
||||
if (subtag == 0)
|
||||
hdmi_intrinsic_event(codec, res);
|
||||
hdmi_intrinsic_event(codec, res, jack);
|
||||
else
|
||||
hdmi_non_intrinsic_event(codec, res);
|
||||
}
|
||||
@ -1480,21 +1466,60 @@ static void hdmi_pcm_reset_pin(struct hdmi_spec *spec,
|
||||
per_pin->channels = 0;
|
||||
}
|
||||
|
||||
static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec,
|
||||
struct hdmi_spec_per_pin *per_pin)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
|
||||
if (per_pin->pcm_idx >= 0)
|
||||
return spec->pcm_rec[per_pin->pcm_idx].jack;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* update per_pin ELD from the given new ELD;
|
||||
* setup info frame and notification accordingly
|
||||
* also notify ELD kctl and report jack status changes
|
||||
*/
|
||||
static bool update_eld(struct hda_codec *codec,
|
||||
static void update_eld(struct hda_codec *codec,
|
||||
struct hdmi_spec_per_pin *per_pin,
|
||||
struct hdmi_eld *eld)
|
||||
struct hdmi_eld *eld,
|
||||
int repoll)
|
||||
{
|
||||
struct hdmi_eld *pin_eld = &per_pin->sink_eld;
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct snd_jack *pcm_jack;
|
||||
bool old_eld_valid = pin_eld->eld_valid;
|
||||
bool eld_changed;
|
||||
int pcm_idx;
|
||||
|
||||
if (eld->eld_valid) {
|
||||
if (eld->eld_size <= 0 ||
|
||||
snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer,
|
||||
eld->eld_size) < 0) {
|
||||
eld->eld_valid = false;
|
||||
if (repoll) {
|
||||
schedule_delayed_work(&per_pin->work,
|
||||
msecs_to_jiffies(300));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!eld->eld_valid || eld->eld_size <= 0) {
|
||||
eld->eld_valid = false;
|
||||
eld->eld_size = 0;
|
||||
}
|
||||
|
||||
/* for monitor disconnection, save pcm_idx firstly */
|
||||
pcm_idx = per_pin->pcm_idx;
|
||||
|
||||
/*
|
||||
* pcm_idx >=0 before update_eld() means it is in monitor
|
||||
* disconnected event. Jack must be fetched before update_eld().
|
||||
*/
|
||||
pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
|
||||
if (spec->dyn_pcm_assign) {
|
||||
if (eld->eld_valid) {
|
||||
hdmi_attach_hda_pcm(spec, per_pin);
|
||||
@ -1509,6 +1534,8 @@ static bool update_eld(struct hda_codec *codec,
|
||||
*/
|
||||
if (pcm_idx == -1)
|
||||
pcm_idx = per_pin->pcm_idx;
|
||||
if (!pcm_jack)
|
||||
pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
|
||||
if (eld->eld_valid)
|
||||
snd_hdmi_show_eld(codec, &eld->info);
|
||||
@ -1547,42 +1574,17 @@ static bool update_eld(struct hda_codec *codec,
|
||||
SNDRV_CTL_EVENT_MASK_VALUE |
|
||||
SNDRV_CTL_EVENT_MASK_INFO,
|
||||
&get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id);
|
||||
return eld_changed;
|
||||
|
||||
if (eld_changed && pcm_jack)
|
||||
snd_jack_report(pcm_jack,
|
||||
(eld->monitor_present && eld->eld_valid) ?
|
||||
SND_JACK_AVOUT : 0);
|
||||
}
|
||||
|
||||
static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec,
|
||||
struct hdmi_spec_per_pin *per_pin)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct snd_jack *jack = NULL;
|
||||
struct hda_jack_tbl *jack_tbl;
|
||||
|
||||
/* if !dyn_pcm_assign, get jack from hda_jack_tbl
|
||||
* in !dyn_pcm_assign case, spec->pcm_rec[].jack is not
|
||||
* NULL even after snd_hda_jack_tbl_clear() is called to
|
||||
* free snd_jack. This may cause access invalid memory
|
||||
* when calling snd_jack_report
|
||||
*/
|
||||
if (per_pin->pcm_idx >= 0 && spec->dyn_pcm_assign) {
|
||||
jack = spec->pcm_rec[per_pin->pcm_idx].jack;
|
||||
} else if (!spec->dyn_pcm_assign) {
|
||||
/*
|
||||
* jack tbl doesn't support DP MST
|
||||
* DP MST will use dyn_pcm_assign,
|
||||
* so DP MST will never come here
|
||||
*/
|
||||
jack_tbl = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid,
|
||||
per_pin->dev_id);
|
||||
if (jack_tbl)
|
||||
jack = jack_tbl->jack;
|
||||
}
|
||||
return jack;
|
||||
}
|
||||
/* update ELD and jack state via HD-audio verbs */
|
||||
static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
|
||||
static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
|
||||
int repoll)
|
||||
{
|
||||
struct hda_jack_tbl *jack;
|
||||
struct hda_codec *codec = per_pin->codec;
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hdmi_eld *eld = &spec->temp_eld;
|
||||
@ -1597,9 +1599,11 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
|
||||
* the unsolicited response to avoid custom WARs.
|
||||
*/
|
||||
int present;
|
||||
bool ret;
|
||||
bool do_repoll = false;
|
||||
struct snd_jack *pcm_jack = NULL;
|
||||
int ret;
|
||||
|
||||
ret = snd_hda_power_up_pm(codec);
|
||||
if (ret < 0 && pm_runtime_suspended(hda_codec_dev(codec)))
|
||||
goto out;
|
||||
|
||||
present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id);
|
||||
|
||||
@ -1618,62 +1622,12 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
|
||||
if (spec->ops.pin_get_eld(codec, pin_nid, dev_id,
|
||||
eld->eld_buffer, &eld->eld_size) < 0)
|
||||
eld->eld_valid = false;
|
||||
else {
|
||||
if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer,
|
||||
eld->eld_size) < 0)
|
||||
eld->eld_valid = false;
|
||||
}
|
||||
if (!eld->eld_valid && repoll)
|
||||
do_repoll = true;
|
||||
}
|
||||
|
||||
if (do_repoll) {
|
||||
schedule_delayed_work(&per_pin->work, msecs_to_jiffies(300));
|
||||
} else {
|
||||
/*
|
||||
* pcm_idx >=0 before update_eld() means it is in monitor
|
||||
* disconnected event. Jack must be fetched before
|
||||
* update_eld().
|
||||
*/
|
||||
pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
update_eld(codec, per_pin, eld);
|
||||
if (!pcm_jack)
|
||||
pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
}
|
||||
|
||||
ret = !repoll || !eld->monitor_present || eld->eld_valid;
|
||||
|
||||
jack = snd_hda_jack_tbl_get_mst(codec, pin_nid, per_pin->dev_id);
|
||||
if (jack) {
|
||||
jack->block_report = !ret;
|
||||
jack->pin_sense = (eld->monitor_present && eld->eld_valid) ?
|
||||
AC_PINSENSE_PRESENCE : 0;
|
||||
|
||||
if (spec->dyn_pcm_assign && pcm_jack && !do_repoll) {
|
||||
int state = 0;
|
||||
|
||||
if (jack->pin_sense & AC_PINSENSE_PRESENCE)
|
||||
state = SND_JACK_AVOUT;
|
||||
snd_jack_report(pcm_jack, state);
|
||||
}
|
||||
|
||||
/*
|
||||
* snd_hda_jack_pin_sense() call at the beginning of this
|
||||
* function, updates jack->pins_sense and clears
|
||||
* jack->jack_dirty, therefore snd_hda_jack_report_sync() will
|
||||
* not override the jack->pin_sense.
|
||||
*
|
||||
* snd_hda_jack_report_sync() is superfluous for dyn_pcm_assign
|
||||
* case. The jack->pin_sense update was already performed, and
|
||||
* hda_jack->jack is NULL for dyn_pcm_assign.
|
||||
*
|
||||
* Don't call snd_hda_jack_report_sync() for
|
||||
* dyn_pcm_assign.
|
||||
*/
|
||||
ret = ret && !spec->dyn_pcm_assign;
|
||||
}
|
||||
update_eld(codec, per_pin, eld, repoll);
|
||||
mutex_unlock(&per_pin->lock);
|
||||
return ret;
|
||||
out:
|
||||
snd_hda_power_down_pm(codec);
|
||||
}
|
||||
|
||||
/* update ELD and jack state via audio component */
|
||||
@ -1682,64 +1636,25 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hdmi_eld *eld = &spec->temp_eld;
|
||||
struct snd_jack *jack = NULL;
|
||||
bool changed;
|
||||
int size;
|
||||
|
||||
mutex_lock(&per_pin->lock);
|
||||
eld->monitor_present = false;
|
||||
size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid,
|
||||
eld->eld_size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid,
|
||||
per_pin->dev_id, &eld->monitor_present,
|
||||
eld->eld_buffer, ELD_MAX_SIZE);
|
||||
if (size > 0) {
|
||||
size = min(size, ELD_MAX_SIZE);
|
||||
if (snd_hdmi_parse_eld(codec, &eld->info,
|
||||
eld->eld_buffer, size) < 0)
|
||||
size = -EINVAL;
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
eld->eld_valid = true;
|
||||
eld->eld_size = size;
|
||||
} else {
|
||||
eld->eld_valid = false;
|
||||
eld->eld_size = 0;
|
||||
}
|
||||
|
||||
/* pcm_idx >=0 before update_eld() means it is in monitor
|
||||
* disconnected event. Jack must be fetched before update_eld()
|
||||
*/
|
||||
jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
changed = update_eld(codec, per_pin, eld);
|
||||
if (jack == NULL)
|
||||
jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
if (changed && jack)
|
||||
snd_jack_report(jack,
|
||||
(eld->monitor_present && eld->eld_valid) ?
|
||||
SND_JACK_AVOUT : 0);
|
||||
eld->eld_valid = (eld->eld_size > 0);
|
||||
update_eld(codec, per_pin, eld, 0);
|
||||
mutex_unlock(&per_pin->lock);
|
||||
}
|
||||
|
||||
static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
|
||||
static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
|
||||
{
|
||||
struct hda_codec *codec = per_pin->codec;
|
||||
int ret;
|
||||
|
||||
/* no temporary power up/down needed for component notifier */
|
||||
if (!codec_has_acomp(codec)) {
|
||||
ret = snd_hda_power_up_pm(codec);
|
||||
if (ret < 0 && pm_runtime_suspended(hda_codec_dev(codec))) {
|
||||
snd_hda_power_down_pm(codec);
|
||||
return false;
|
||||
}
|
||||
ret = hdmi_present_sense_via_verbs(per_pin, repoll);
|
||||
snd_hda_power_down_pm(codec);
|
||||
} else {
|
||||
if (!codec_has_acomp(codec))
|
||||
hdmi_present_sense_via_verbs(per_pin, repoll);
|
||||
else
|
||||
sync_eld_via_acomp(codec, per_pin);
|
||||
ret = false; /* don't call snd_hda_jack_report_sync() */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hdmi_repoll_eld(struct work_struct *work)
|
||||
@ -1759,8 +1674,7 @@ static void hdmi_repoll_eld(struct work_struct *work)
|
||||
per_pin->repoll_count = 0;
|
||||
|
||||
mutex_lock(&spec->pcm_lock);
|
||||
if (hdmi_present_sense(per_pin, per_pin->repoll_count))
|
||||
snd_hda_jack_report_sync(per_pin->codec);
|
||||
hdmi_present_sense(per_pin, per_pin->repoll_count);
|
||||
mutex_unlock(&spec->pcm_lock);
|
||||
}
|
||||
|
||||
@ -2206,15 +2120,23 @@ static void free_hdmi_jack_priv(struct snd_jack *jack)
|
||||
pcm->jack = NULL;
|
||||
}
|
||||
|
||||
static int add_hdmi_jack_kctl(struct hda_codec *codec,
|
||||
struct hdmi_spec *spec,
|
||||
int pcm_idx,
|
||||
const char *name)
|
||||
static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx)
|
||||
{
|
||||
char hdmi_str[32] = "HDMI/DP";
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pcm_idx);
|
||||
struct snd_jack *jack;
|
||||
int pcmdev = get_pcm_rec(spec, pcm_idx)->device;
|
||||
int err;
|
||||
|
||||
err = snd_jack_new(codec->card, name, SND_JACK_AVOUT, &jack,
|
||||
if (pcmdev > 0)
|
||||
sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
|
||||
if (!spec->dyn_pcm_assign &&
|
||||
!is_jack_detectable(codec, per_pin->pin_nid))
|
||||
strncat(hdmi_str, " Phantom",
|
||||
sizeof(hdmi_str) - strlen(hdmi_str) - 1);
|
||||
|
||||
err = snd_jack_new(codec->card, hdmi_str, SND_JACK_AVOUT, &jack,
|
||||
true, false);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -2225,48 +2147,6 @@ static int add_hdmi_jack_kctl(struct hda_codec *codec,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx)
|
||||
{
|
||||
char hdmi_str[32] = "HDMI/DP";
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hdmi_spec_per_pin *per_pin;
|
||||
struct hda_jack_tbl *jack;
|
||||
int pcmdev = get_pcm_rec(spec, pcm_idx)->device;
|
||||
bool phantom_jack;
|
||||
int ret;
|
||||
|
||||
if (pcmdev > 0)
|
||||
sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
|
||||
|
||||
if (spec->dyn_pcm_assign)
|
||||
return add_hdmi_jack_kctl(codec, spec, pcm_idx, hdmi_str);
|
||||
|
||||
/* for !dyn_pcm_assign, we still use hda_jack for compatibility */
|
||||
/* if !dyn_pcm_assign, it must be non-MST mode.
|
||||
* This means pcms and pins are statically mapped.
|
||||
* And pcm_idx is pin_idx.
|
||||
*/
|
||||
per_pin = get_pin(spec, pcm_idx);
|
||||
phantom_jack = !is_jack_detectable(codec, per_pin->pin_nid);
|
||||
if (phantom_jack)
|
||||
strncat(hdmi_str, " Phantom",
|
||||
sizeof(hdmi_str) - strlen(hdmi_str) - 1);
|
||||
ret = snd_hda_jack_add_kctl_mst(codec, per_pin->pin_nid,
|
||||
per_pin->dev_id, hdmi_str, phantom_jack,
|
||||
0, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
jack = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid,
|
||||
per_pin->dev_id);
|
||||
if (jack == NULL)
|
||||
return 0;
|
||||
/* assign jack->jack to pcm_rec[].jack to
|
||||
* align with dyn_pcm_assign mode
|
||||
*/
|
||||
spec->pcm_rec[pcm_idx].jack = jack->jack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int generic_hdmi_build_controls(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
@ -2355,7 +2235,6 @@ static int generic_hdmi_init(struct hda_codec *codec)
|
||||
int pin_idx;
|
||||
|
||||
mutex_lock(&spec->bind_lock);
|
||||
spec->use_jack_detect = !codec->jackpoll_interval;
|
||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
||||
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||
hda_nid_t pin_nid = per_pin->pin_nid;
|
||||
@ -2365,12 +2244,8 @@ static int generic_hdmi_init(struct hda_codec *codec)
|
||||
hdmi_init_pin(codec, pin_nid);
|
||||
if (codec_has_acomp(codec))
|
||||
continue;
|
||||
if (spec->use_jack_detect)
|
||||
snd_hda_jack_detect_enable(codec, pin_nid, dev_id);
|
||||
else
|
||||
snd_hda_jack_detect_enable_callback_mst(codec, pin_nid,
|
||||
dev_id,
|
||||
jack_callback);
|
||||
snd_hda_jack_detect_enable_callback_mst(codec, pin_nid, dev_id,
|
||||
jack_callback);
|
||||
}
|
||||
mutex_unlock(&spec->bind_lock);
|
||||
return 0;
|
||||
@ -2532,12 +2407,6 @@ static void reprogram_jack_detect(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned int val = use_acomp ? 0 : (AC_USRSP_EN | tbl->tag);
|
||||
snd_hda_codec_write_cache(codec, nid, 0,
|
||||
AC_VERB_SET_UNSOLICITED_ENABLE, val);
|
||||
} else {
|
||||
/* if no jack entry was defined beforehand, create a new one
|
||||
* at need (i.e. only when notifier is cleared)
|
||||
*/
|
||||
if (!use_acomp)
|
||||
snd_hda_jack_detect_enable(codec, nid, dev_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2553,13 +2422,11 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
|
||||
spec->use_acomp_notifier = use_acomp;
|
||||
spec->codec->relaxed_resume = use_acomp;
|
||||
/* reprogram each jack detection logic depending on the notifier */
|
||||
if (spec->use_jack_detect) {
|
||||
for (i = 0; i < spec->num_pins; i++)
|
||||
reprogram_jack_detect(spec->codec,
|
||||
get_pin(spec, i)->pin_nid,
|
||||
get_pin(spec, i)->dev_id,
|
||||
use_acomp);
|
||||
}
|
||||
for (i = 0; i < spec->num_pins; i++)
|
||||
reprogram_jack_detect(spec->codec,
|
||||
get_pin(spec, i)->pin_nid,
|
||||
get_pin(spec, i)->dev_id,
|
||||
use_acomp);
|
||||
mutex_unlock(&spec->bind_lock);
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,7 @@ struct alc_spec {
|
||||
unsigned int done_hp_init:1;
|
||||
unsigned int no_shutup_pins:1;
|
||||
unsigned int ultra_low_power:1;
|
||||
unsigned int has_hs_key:1;
|
||||
|
||||
/* for PLL fix */
|
||||
hda_nid_t pll_nid;
|
||||
@ -367,7 +368,9 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
|
||||
case 0x10ec0215:
|
||||
case 0x10ec0233:
|
||||
case 0x10ec0235:
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0255:
|
||||
case 0x10ec0256:
|
||||
case 0x10ec0257:
|
||||
case 0x10ec0282:
|
||||
case 0x10ec0283:
|
||||
@ -379,11 +382,6 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
|
||||
case 0x10ec0300:
|
||||
alc_update_coef_idx(codec, 0x10, 1<<9, 0);
|
||||
break;
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
alc_write_coef_idx(codec, 0x36, 0x5757);
|
||||
alc_update_coef_idx(codec, 0x10, 1<<9, 0);
|
||||
break;
|
||||
case 0x10ec0275:
|
||||
alc_update_coef_idx(codec, 0xe, 0, 1<<0);
|
||||
break;
|
||||
@ -2982,6 +2980,107 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
|
||||
return alc_parse_auto_config(codec, alc269_ignore, ssids);
|
||||
}
|
||||
|
||||
static const struct hda_jack_keymap alc_headset_btn_keymap[] = {
|
||||
{ SND_JACK_BTN_0, KEY_PLAYPAUSE },
|
||||
{ SND_JACK_BTN_1, KEY_VOICECOMMAND },
|
||||
{ SND_JACK_BTN_2, KEY_VOLUMEUP },
|
||||
{ SND_JACK_BTN_3, KEY_VOLUMEDOWN },
|
||||
{}
|
||||
};
|
||||
|
||||
static void alc_headset_btn_callback(struct hda_codec *codec,
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
int report = 0;
|
||||
|
||||
if (jack->unsol_res & (7 << 13))
|
||||
report |= SND_JACK_BTN_0;
|
||||
|
||||
if (jack->unsol_res & (1 << 16 | 3 << 8))
|
||||
report |= SND_JACK_BTN_1;
|
||||
|
||||
/* Volume up key */
|
||||
if (jack->unsol_res & (7 << 23))
|
||||
report |= SND_JACK_BTN_2;
|
||||
|
||||
/* Volume down key */
|
||||
if (jack->unsol_res & (7 << 10))
|
||||
report |= SND_JACK_BTN_3;
|
||||
|
||||
jack->jack->button_state = report;
|
||||
}
|
||||
|
||||
static void alc_disable_headset_jack_key(struct hda_codec *codec)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
if (!spec->has_hs_key)
|
||||
return;
|
||||
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0215:
|
||||
case 0x10ec0225:
|
||||
case 0x10ec0285:
|
||||
case 0x10ec0295:
|
||||
case 0x10ec0289:
|
||||
case 0x10ec0299:
|
||||
alc_write_coef_idx(codec, 0x48, 0x0);
|
||||
alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
|
||||
alc_update_coef_idx(codec, 0x44, 0x0045 << 8, 0x0);
|
||||
break;
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
alc_write_coef_idx(codec, 0x48, 0x0);
|
||||
alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc_enable_headset_jack_key(struct hda_codec *codec)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
if (!spec->has_hs_key)
|
||||
return;
|
||||
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0215:
|
||||
case 0x10ec0225:
|
||||
case 0x10ec0285:
|
||||
case 0x10ec0295:
|
||||
case 0x10ec0289:
|
||||
case 0x10ec0299:
|
||||
alc_write_coef_idx(codec, 0x48, 0xd011);
|
||||
alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
|
||||
alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8);
|
||||
break;
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
alc_write_coef_idx(codec, 0x48, 0xd011);
|
||||
alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc_fixup_headset_jack(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
switch (action) {
|
||||
case HDA_FIXUP_ACT_PRE_PROBE:
|
||||
spec->has_hs_key = 1;
|
||||
snd_hda_jack_detect_enable_callback(codec, 0x55,
|
||||
alc_headset_btn_callback);
|
||||
snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false,
|
||||
SND_JACK_HEADSET, alc_headset_btn_keymap);
|
||||
break;
|
||||
case HDA_FIXUP_ACT_INIT:
|
||||
alc_enable_headset_jack_key(codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
|
||||
{
|
||||
alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0);
|
||||
@ -3269,7 +3368,13 @@ static void alc256_init(struct hda_codec *codec)
|
||||
alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
|
||||
alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 1 << 15); /* Clear bit */
|
||||
alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 0 << 15);
|
||||
alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/
|
||||
/*
|
||||
* Expose headphone mic (or possibly Line In on some machines) instead
|
||||
* of PC Beep on 1Ah, and disable 1Ah loopback for all outputs. See
|
||||
* Documentation/sound/hd-audio/realtek-pc-beep.rst for details of
|
||||
* this register.
|
||||
*/
|
||||
alc_write_coef_idx(codec, 0x36, 0x5757);
|
||||
}
|
||||
|
||||
static void alc256_shutup(struct hda_codec *codec)
|
||||
@ -3372,6 +3477,8 @@ static void alc225_shutup(struct hda_codec *codec)
|
||||
|
||||
if (!hp_pin)
|
||||
hp_pin = 0x21;
|
||||
|
||||
alc_disable_headset_jack_key(codec);
|
||||
/* 3k pull low control for Headset jack. */
|
||||
alc_update_coef_idx(codec, 0x4a, 0, 3 << 10);
|
||||
|
||||
@ -3411,6 +3518,9 @@ static void alc225_shutup(struct hda_codec *codec)
|
||||
alc_update_coef_idx(codec, 0x4a, 3<<4, 2<<4);
|
||||
msleep(30);
|
||||
}
|
||||
|
||||
alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
|
||||
alc_enable_headset_jack_key(codec);
|
||||
}
|
||||
|
||||
static void alc_default_init(struct hda_codec *codec)
|
||||
@ -4008,6 +4118,12 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
|
||||
alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10);
|
||||
}
|
||||
|
||||
static void alc285_fixup_hp_gpio_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
alc_fixup_hp_gpio_led(codec, action, 0x04, 0x00);
|
||||
}
|
||||
|
||||
static void alc286_fixup_hp_gpio_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
@ -5375,17 +5491,6 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
static void alc256_fixup_dell_xps_13_headphone_noise2(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix,
|
||||
int action)
|
||||
{
|
||||
if (action != HDA_FIXUP_ACT_PRE_PROBE)
|
||||
return;
|
||||
|
||||
snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 0, HDA_AMP_VOLMASK, 1);
|
||||
snd_hda_override_wcaps(codec, 0x1a, get_wcaps(codec, 0x1a) & ~AC_WCAP_IN_AMP);
|
||||
}
|
||||
|
||||
static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix,
|
||||
int action)
|
||||
@ -5662,69 +5767,6 @@ static void alc285_fixup_invalidate_dacs(struct hda_codec *codec,
|
||||
snd_hda_override_wcaps(codec, 0x03, 0);
|
||||
}
|
||||
|
||||
static const struct hda_jack_keymap alc_headset_btn_keymap[] = {
|
||||
{ SND_JACK_BTN_0, KEY_PLAYPAUSE },
|
||||
{ SND_JACK_BTN_1, KEY_VOICECOMMAND },
|
||||
{ SND_JACK_BTN_2, KEY_VOLUMEUP },
|
||||
{ SND_JACK_BTN_3, KEY_VOLUMEDOWN },
|
||||
{}
|
||||
};
|
||||
|
||||
static void alc_headset_btn_callback(struct hda_codec *codec,
|
||||
struct hda_jack_callback *jack)
|
||||
{
|
||||
int report = 0;
|
||||
|
||||
if (jack->unsol_res & (7 << 13))
|
||||
report |= SND_JACK_BTN_0;
|
||||
|
||||
if (jack->unsol_res & (1 << 16 | 3 << 8))
|
||||
report |= SND_JACK_BTN_1;
|
||||
|
||||
/* Volume up key */
|
||||
if (jack->unsol_res & (7 << 23))
|
||||
report |= SND_JACK_BTN_2;
|
||||
|
||||
/* Volume down key */
|
||||
if (jack->unsol_res & (7 << 10))
|
||||
report |= SND_JACK_BTN_3;
|
||||
|
||||
jack->jack->button_state = report;
|
||||
}
|
||||
|
||||
static void alc_fixup_headset_jack(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
|
||||
switch (action) {
|
||||
case HDA_FIXUP_ACT_PRE_PROBE:
|
||||
snd_hda_jack_detect_enable_callback(codec, 0x55,
|
||||
alc_headset_btn_callback);
|
||||
snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false,
|
||||
SND_JACK_HEADSET, alc_headset_btn_keymap);
|
||||
break;
|
||||
case HDA_FIXUP_ACT_INIT:
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0215:
|
||||
case 0x10ec0225:
|
||||
case 0x10ec0285:
|
||||
case 0x10ec0295:
|
||||
case 0x10ec0289:
|
||||
case 0x10ec0299:
|
||||
alc_write_coef_idx(codec, 0x48, 0xd011);
|
||||
alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
|
||||
alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8);
|
||||
break;
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
alc_write_coef_idx(codec, 0x48, 0xd011);
|
||||
alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc295_fixup_chromebook(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
@ -5863,8 +5905,6 @@ enum {
|
||||
ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
|
||||
ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE,
|
||||
ALC275_FIXUP_DELL_XPS,
|
||||
ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
|
||||
ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2,
|
||||
ALC293_FIXUP_LENOVO_SPK_NOISE,
|
||||
ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
|
||||
ALC255_FIXUP_DELL_SPK_NOISE,
|
||||
@ -5923,6 +5963,7 @@ enum {
|
||||
ALC294_FIXUP_ASUS_DUAL_SPK,
|
||||
ALC285_FIXUP_THINKPAD_HEADSET_JACK,
|
||||
ALC294_FIXUP_ASUS_HPE,
|
||||
ALC285_FIXUP_HP_GPIO_LED,
|
||||
};
|
||||
|
||||
static const struct hda_fixup alc269_fixups[] = {
|
||||
@ -6604,23 +6645,6 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||
{}
|
||||
}
|
||||
},
|
||||
[ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE] = {
|
||||
.type = HDA_FIXUP_VERBS,
|
||||
.v.verbs = (const struct hda_verb[]) {
|
||||
/* Disable pass-through path for FRONT 14h */
|
||||
{0x20, AC_VERB_SET_COEF_INDEX, 0x36},
|
||||
{0x20, AC_VERB_SET_PROC_COEF, 0x1737},
|
||||
{}
|
||||
},
|
||||
.chained = true,
|
||||
.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
|
||||
},
|
||||
[ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc256_fixup_dell_xps_13_headphone_noise2,
|
||||
.chained = true,
|
||||
.chain_id = ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE
|
||||
},
|
||||
[ALC293_FIXUP_LENOVO_SPK_NOISE] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_disable_aamix,
|
||||
@ -7061,6 +7085,10 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||
.chained = true,
|
||||
.chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
|
||||
},
|
||||
[ALC285_FIXUP_HP_GPIO_LED] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_hp_gpio_led,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
@ -7114,17 +7142,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
|
||||
SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
|
||||
SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2),
|
||||
SND_PCI_QUIRK(0x1028, 0x0706, "Dell Inspiron 7559", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
|
||||
SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0738, "Dell Precision 5820", ALC269_FIXUP_NO_SHUTUP),
|
||||
SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2),
|
||||
SND_PCI_QUIRK(0x1028, 0x075c, "Dell XPS 27 7760", ALC298_FIXUP_SPK_VOLUME),
|
||||
SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
|
||||
SND_PCI_QUIRK(0x1028, 0x07b0, "Dell Precision 7520", ALC295_FIXUP_DISABLE_DAC3),
|
||||
SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
|
||||
SND_PCI_QUIRK(0x1028, 0x080c, "Dell WYSE", ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2),
|
||||
SND_PCI_QUIRK(0x1028, 0x084b, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
|
||||
SND_PCI_QUIRK(0x1028, 0x084e, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
|
||||
SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
|
||||
@ -7208,6 +7233,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
|
||||
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
@ -7477,7 +7503,6 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
|
||||
{.id = ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc298-dell1"},
|
||||
{.id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE, .name = "alc298-dell-aio"},
|
||||
{.id = ALC275_FIXUP_DELL_XPS, .name = "alc275-dell-xps"},
|
||||
{.id = ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE, .name = "alc256-dell-xps13"},
|
||||
{.id = ALC293_FIXUP_LENOVO_SPK_NOISE, .name = "lenovo-spk-noise"},
|
||||
{.id = ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, .name = "lenovo-hotkey"},
|
||||
{.id = ALC255_FIXUP_DELL_SPK_NOISE, .name = "dell-spk-noise"},
|
||||
|
@ -30,7 +30,7 @@
|
||||
#if K1212_DEBUG_LEVEL > 0
|
||||
#define K1212_DEBUG_PRINTK(fmt,args...) printk(KERN_DEBUG fmt,##args)
|
||||
#else
|
||||
#define K1212_DEBUG_PRINTK(fmt,...)
|
||||
#define K1212_DEBUG_PRINTK(fmt,...) do { } while (0)
|
||||
#endif
|
||||
#if K1212_DEBUG_LEVEL > 1
|
||||
#define K1212_DEBUG_PRINTK_VERBOSE(fmt,args...) printk(KERN_DEBUG fmt,##args)
|
||||
|
@ -3353,7 +3353,8 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
int err = -EINVAL;
|
||||
int err;
|
||||
|
||||
err = hdsp_request_fw_loader(hdsp);
|
||||
if (err < 0) {
|
||||
snd_iprintf(buffer,
|
||||
|
@ -414,6 +414,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
|
||||
{
|
||||
unsigned int i, idx, ofs, rest;
|
||||
struct via82xx *chip = snd_pcm_substream_chip(substream);
|
||||
__le32 *pgtbl;
|
||||
|
||||
if (dev->table.area == NULL) {
|
||||
/* the start of each lists must be aligned to 8 bytes,
|
||||
@ -435,6 +436,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
|
||||
/* fill the entries */
|
||||
idx = 0;
|
||||
ofs = 0;
|
||||
pgtbl = (__le32 *)dev->table.area;
|
||||
for (i = 0; i < periods; i++) {
|
||||
rest = fragsize;
|
||||
/* fill descriptors for a period.
|
||||
@ -451,7 +453,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = snd_pcm_sgbuf_get_addr(substream, ofs);
|
||||
((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr);
|
||||
pgtbl[idx << 1] = cpu_to_le32(addr);
|
||||
r = snd_pcm_sgbuf_get_chunk_size(substream, ofs, rest);
|
||||
rest -= r;
|
||||
if (! rest) {
|
||||
@ -466,7 +468,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
|
||||
"tbl %d: at %d size %d (rest %d)\n",
|
||||
idx, ofs, r, rest);
|
||||
*/
|
||||
((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag);
|
||||
pgtbl[(idx<<1) + 1] = cpu_to_le32(r | flag);
|
||||
dev->idx_table[idx].offset = ofs;
|
||||
dev->idx_table[idx].size = r;
|
||||
ofs += r;
|
||||
|
@ -267,6 +267,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
|
||||
{
|
||||
unsigned int i, idx, ofs, rest;
|
||||
struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
|
||||
__le32 *pgtbl;
|
||||
|
||||
if (dev->table.area == NULL) {
|
||||
/* the start of each lists must be aligned to 8 bytes,
|
||||
@ -288,6 +289,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
|
||||
/* fill the entries */
|
||||
idx = 0;
|
||||
ofs = 0;
|
||||
pgtbl = (__le32 *)dev->table.area;
|
||||
for (i = 0; i < periods; i++) {
|
||||
rest = fragsize;
|
||||
/* fill descriptors for a period.
|
||||
@ -304,7 +306,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = snd_pcm_sgbuf_get_addr(substream, ofs);
|
||||
((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr);
|
||||
pgtbl[idx << 1] = cpu_to_le32(addr);
|
||||
r = PAGE_SIZE - (ofs % PAGE_SIZE);
|
||||
if (rest < r)
|
||||
r = rest;
|
||||
@ -321,7 +323,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
|
||||
"tbl %d: at %d size %d (rest %d)\n",
|
||||
idx, ofs, r, rest);
|
||||
*/
|
||||
((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag);
|
||||
pgtbl[(idx<<1) + 1] = cpu_to_le32(r | flag);
|
||||
dev->idx_table[idx].offset = ofs;
|
||||
dev->idx_table[idx].size = r;
|
||||
ofs += r;
|
||||
|
@ -40,6 +40,7 @@ static int keywest_probe(struct i2c_client *client,
|
||||
static int keywest_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct i2c_board_info info;
|
||||
struct i2c_client *client;
|
||||
|
||||
if (! keywest_ctx)
|
||||
return -EINVAL;
|
||||
@ -50,9 +51,11 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "keywest", I2C_NAME_SIZE);
|
||||
info.addr = keywest_ctx->addr;
|
||||
keywest_ctx->client = i2c_new_device(adapter, &info);
|
||||
if (!keywest_ctx->client)
|
||||
return -ENODEV;
|
||||
client = i2c_new_client_device(adapter, &info);
|
||||
if (IS_ERR(client))
|
||||
return PTR_ERR(client);
|
||||
keywest_ctx->client = client;
|
||||
|
||||
/*
|
||||
* We know the driver is already loaded, so the device should be
|
||||
* already bound. If not it means binding failed, and then there
|
||||
|
@ -26,3 +26,13 @@ config SND_SOC_AMD_ACP3x
|
||||
depends on X86 && PCI
|
||||
help
|
||||
This option enables ACP v3.x I2S support on AMD platform
|
||||
|
||||
config SND_SOC_AMD_RV_RT5682_MACH
|
||||
tristate "AMD RV support for RT5682"
|
||||
select SND_SOC_RT5682
|
||||
select SND_SOC_MAX98357A
|
||||
select SND_SOC_CROS_EC_CODEC
|
||||
select I2C_CROS_EC_TUNNEL
|
||||
depends on SND_SOC_AMD_ACP3x && I2C && CROS_EC
|
||||
help
|
||||
This option enables machine driver for RT5682 and MAX9835.
|
||||
|
@ -2,8 +2,10 @@
|
||||
acp_audio_dma-objs := acp-pcm-dma.o
|
||||
snd-soc-acp-da7219mx98357-mach-objs := acp-da7219-max98357a.o
|
||||
snd-soc-acp-rt5645-mach-objs := acp-rt5645.o
|
||||
snd-soc-acp-rt5682-mach-objs := acp3x-rt5682-max9836.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP) += acp_audio_dma.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH) += snd-soc-acp-da7219mx98357-mach.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/
|
||||
obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o
|
||||
|
@ -54,7 +54,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
|
||||
dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
|
||||
|
@ -48,7 +48,7 @@ static int cz_aif1_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
int ret = 0;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
|
||||
ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK,
|
||||
CZ_PLAT_CLK, params_rate(params) * 512);
|
||||
@ -73,7 +73,7 @@ static int cz_init(struct snd_soc_pcm_runtime *rtd)
|
||||
struct snd_soc_card *card;
|
||||
struct snd_soc_component *codec;
|
||||
|
||||
codec = rtd->codec_dai->component;
|
||||
codec = asoc_rtd_to_codec(rtd, 0)->component;
|
||||
card = rtd->card;
|
||||
|
||||
ret = snd_soc_card_jack_new(card, "Headset Jack",
|
||||
|
376
sound/soc/amd/acp3x-rt5682-max9836.c
Normal file
376
sound/soc/amd/acp3x-rt5682-max9836.c
Normal file
@ -0,0 +1,376 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// Machine driver for AMD ACP Audio engine using DA7219 & MAX98357 codec.
|
||||
//
|
||||
//Copyright 2016 Advanced Micro Devices, Inc.
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/jack.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include "raven/acp3x.h"
|
||||
#include "../codecs/rt5682.h"
|
||||
|
||||
#define PCO_PLAT_CLK 48000000
|
||||
#define RT5682_PLL_FREQ (48000 * 512)
|
||||
#define DUAL_CHANNEL 2
|
||||
|
||||
static struct snd_soc_jack pco_jack;
|
||||
static struct clk *rt5682_dai_wclk;
|
||||
static struct clk *rt5682_dai_bclk;
|
||||
static struct gpio_desc *dmic_sel;
|
||||
|
||||
static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
|
||||
dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
|
||||
|
||||
/* set rt5682 dai fmt */
|
||||
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
|
||||
| SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->card->dev,
|
||||
"Failed to set rt5682 dai fmt: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set codec PLL */
|
||||
ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK,
|
||||
PCO_PLAT_CLK, RT5682_PLL_FREQ);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "can't set rt5682 PLL: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set codec sysclk */
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2,
|
||||
RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev,
|
||||
"Failed to set rt5682 SYSCLK: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set tdm/i2s1 master bclk ratio */
|
||||
ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev,
|
||||
"Failed to set rt5682 tdm bclk ratio: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rt5682_dai_wclk = clk_get(component->dev, "rt5682-dai-wclk");
|
||||
rt5682_dai_bclk = clk_get(component->dev, "rt5682-dai-bclk");
|
||||
|
||||
ret = snd_soc_card_jack_new(card, "Headset Jack",
|
||||
SND_JACK_HEADSET | SND_JACK_LINEOUT |
|
||||
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
|
||||
SND_JACK_BTN_2 | SND_JACK_BTN_3,
|
||||
&pco_jack, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "HP jack creation failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
|
||||
|
||||
ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
|
||||
if (ret) {
|
||||
dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rt5682_clk_enable(struct snd_pcm_substream *substream)
|
||||
{
|
||||
int ret = 0;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
|
||||
/* RT5682 will support only 48K output with 48M mclk */
|
||||
clk_set_rate(rt5682_dai_wclk, 48000);
|
||||
clk_set_rate(rt5682_dai_bclk, 48000 * 64);
|
||||
ret = clk_prepare_enable(rt5682_dai_wclk);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "can't enable wclk %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rt5682_clk_disable(void)
|
||||
{
|
||||
clk_disable_unprepare(rt5682_dai_wclk);
|
||||
}
|
||||
|
||||
static const unsigned int channels[] = {
|
||||
DUAL_CHANNEL,
|
||||
};
|
||||
|
||||
static const unsigned int rates[] = {
|
||||
48000,
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hw_constraint_list constraints_rates = {
|
||||
.count = ARRAY_SIZE(rates),
|
||||
.list = rates,
|
||||
.mask = 0,
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hw_constraint_list constraints_channels = {
|
||||
.count = ARRAY_SIZE(channels),
|
||||
.list = channels,
|
||||
.mask = 0,
|
||||
};
|
||||
|
||||
static int acp3x_5682_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
machine->play_i2s_instance = I2S_SP_INSTANCE;
|
||||
machine->cap_i2s_instance = I2S_SP_INSTANCE;
|
||||
|
||||
runtime->hw.channels_max = DUAL_CHANNEL;
|
||||
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
&constraints_channels);
|
||||
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
||||
&constraints_rates);
|
||||
return rt5682_clk_enable(substream);
|
||||
}
|
||||
|
||||
static int acp3x_max_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
machine->play_i2s_instance = I2S_BT_INSTANCE;
|
||||
|
||||
runtime->hw.channels_max = DUAL_CHANNEL;
|
||||
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
&constraints_channels);
|
||||
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
||||
&constraints_rates);
|
||||
return rt5682_clk_enable(substream);
|
||||
}
|
||||
|
||||
static int acp3x_ec_dmic0_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
machine->cap_i2s_instance = I2S_BT_INSTANCE;
|
||||
snd_soc_dai_set_bclk_ratio(codec_dai, 64);
|
||||
if (dmic_sel)
|
||||
gpiod_set_value(dmic_sel, 0);
|
||||
|
||||
return rt5682_clk_enable(substream);
|
||||
}
|
||||
|
||||
static int acp3x_ec_dmic1_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
machine->cap_i2s_instance = I2S_BT_INSTANCE;
|
||||
snd_soc_dai_set_bclk_ratio(codec_dai, 64);
|
||||
if (dmic_sel)
|
||||
gpiod_set_value(dmic_sel, 1);
|
||||
|
||||
return rt5682_clk_enable(substream);
|
||||
}
|
||||
|
||||
static void rt5682_shutdown(struct snd_pcm_substream *substream)
|
||||
{
|
||||
rt5682_clk_disable();
|
||||
}
|
||||
|
||||
static const struct snd_soc_ops acp3x_5682_ops = {
|
||||
.startup = acp3x_5682_startup,
|
||||
.shutdown = rt5682_shutdown,
|
||||
};
|
||||
|
||||
static const struct snd_soc_ops acp3x_max_play_ops = {
|
||||
.startup = acp3x_max_startup,
|
||||
.shutdown = rt5682_shutdown,
|
||||
};
|
||||
|
||||
static const struct snd_soc_ops acp3x_ec_cap0_ops = {
|
||||
.startup = acp3x_ec_dmic0_startup,
|
||||
.shutdown = rt5682_shutdown,
|
||||
};
|
||||
|
||||
static const struct snd_soc_ops acp3x_ec_cap1_ops = {
|
||||
.startup = acp3x_ec_dmic1_startup,
|
||||
.shutdown = rt5682_shutdown,
|
||||
};
|
||||
|
||||
SND_SOC_DAILINK_DEF(acp3x_i2s,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0")));
|
||||
SND_SOC_DAILINK_DEF(acp3x_bt,
|
||||
DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.2")));
|
||||
|
||||
SND_SOC_DAILINK_DEF(rt5682,
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
|
||||
SND_SOC_DAILINK_DEF(max,
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi")));
|
||||
SND_SOC_DAILINK_DEF(cros_ec,
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("GOOG0013:00", "EC Codec I2S RX")));
|
||||
|
||||
SND_SOC_DAILINK_DEF(platform,
|
||||
DAILINK_COMP_ARRAY(COMP_PLATFORM("acp3x_rv_i2s_dma.0")));
|
||||
|
||||
static struct snd_soc_dai_link acp3x_dai_5682_98357[] = {
|
||||
{
|
||||
.name = "acp3x-5682-play",
|
||||
.stream_name = "Playback",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.init = acp3x_5682_init,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ops = &acp3x_5682_ops,
|
||||
SND_SOC_DAILINK_REG(acp3x_i2s, rt5682, platform),
|
||||
},
|
||||
{
|
||||
.name = "acp3x-max98357-play",
|
||||
.stream_name = "HiFi Playback",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.dpcm_playback = 1,
|
||||
.ops = &acp3x_max_play_ops,
|
||||
SND_SOC_DAILINK_REG(acp3x_bt, max, platform),
|
||||
},
|
||||
{
|
||||
.name = "acp3x-ec-dmic0-capture",
|
||||
.stream_name = "Capture DMIC0",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBS_CFS,
|
||||
.dpcm_capture = 1,
|
||||
.ops = &acp3x_ec_cap0_ops,
|
||||
SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
|
||||
},
|
||||
{
|
||||
.name = "acp3x-ec-dmic1-capture",
|
||||
.stream_name = "Capture DMIC1",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBS_CFS,
|
||||
.dpcm_capture = 1,
|
||||
.ops = &acp3x_ec_cap1_ops,
|
||||
SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget acp3x_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||
SND_SOC_DAPM_SPK("Spk", NULL),
|
||||
SND_SOC_DAPM_MIC("Headset Mic", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route acp3x_audio_route[] = {
|
||||
{"Headphone Jack", NULL, "HPOL"},
|
||||
{"Headphone Jack", NULL, "HPOR"},
|
||||
{"IN1P", NULL, "Headset Mic"},
|
||||
{"Spk", NULL, "Speaker"},
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new acp3x_mc_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
|
||||
SOC_DAPM_PIN_SWITCH("Spk"),
|
||||
SOC_DAPM_PIN_SWITCH("Headset Mic"),
|
||||
};
|
||||
|
||||
static struct snd_soc_card acp3x_card = {
|
||||
.name = "acp3xalc5682m98357",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = acp3x_dai_5682_98357,
|
||||
.num_links = ARRAY_SIZE(acp3x_dai_5682_98357),
|
||||
.dapm_widgets = acp3x_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(acp3x_widgets),
|
||||
.dapm_routes = acp3x_audio_route,
|
||||
.num_dapm_routes = ARRAY_SIZE(acp3x_audio_route),
|
||||
.controls = acp3x_mc_controls,
|
||||
.num_controls = ARRAY_SIZE(acp3x_mc_controls),
|
||||
};
|
||||
|
||||
static int acp3x_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_card *card;
|
||||
struct acp3x_platform_info *machine;
|
||||
|
||||
machine = devm_kzalloc(&pdev->dev, sizeof(*machine), GFP_KERNEL);
|
||||
if (!machine)
|
||||
return -ENOMEM;
|
||||
|
||||
card = &acp3x_card;
|
||||
acp3x_card.dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, card);
|
||||
snd_soc_card_set_drvdata(card, machine);
|
||||
|
||||
dmic_sel = devm_gpiod_get(&pdev->dev, "dmic", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(dmic_sel)) {
|
||||
dev_err(&pdev->dev, "DMIC gpio failed err=%ld\n",
|
||||
PTR_ERR(dmic_sel));
|
||||
return PTR_ERR(dmic_sel);
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, &acp3x_card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"devm_snd_soc_register_card(%s) failed: %d\n",
|
||||
acp3x_card.name, ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id acp3x_audio_acpi_match[] = {
|
||||
{ "AMDI5682", 0 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, acp3x_audio_acpi_match);
|
||||
|
||||
static struct platform_driver acp3x_audio = {
|
||||
.driver = {
|
||||
.name = "acp3x-alc5682-max98357",
|
||||
.acpi_match_table = ACPI_PTR(acp3x_audio_acpi_match),
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = acp3x_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(acp3x_audio);
|
||||
|
||||
MODULE_AUTHOR("akshu.agrawal@amd.com");
|
||||
MODULE_DESCRIPTION("ALC5682 & MAX98357 audio support");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -42,7 +42,7 @@ static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,
|
||||
u32 tx_mask, u32 rx_mask, int slots, int slot_width)
|
||||
{
|
||||
struct i2s_dev_data *adata;
|
||||
u32 val, reg_val, frmt_reg, frm_len;
|
||||
u32 frm_len;
|
||||
u16 slot_len;
|
||||
|
||||
adata = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
@ -64,36 +64,7 @@ static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Enable I2S/BT channels TDM, respective TX/RX frame lengths.*/
|
||||
|
||||
frm_len = FRM_LEN | (slots << 15) | (slot_len << 18);
|
||||
if (adata->substream_type == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
switch (adata->i2s_instance) {
|
||||
case I2S_BT_INSTANCE:
|
||||
reg_val = mmACP_BTTDM_ITER;
|
||||
frmt_reg = mmACP_BTTDM_TXFRMT;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = mmACP_I2STDM_ITER;
|
||||
frmt_reg = mmACP_I2STDM_TXFRMT;
|
||||
}
|
||||
} else {
|
||||
switch (adata->i2s_instance) {
|
||||
case I2S_BT_INSTANCE:
|
||||
reg_val = mmACP_BTTDM_IRER;
|
||||
frmt_reg = mmACP_BTTDM_RXFRMT;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = mmACP_I2STDM_IRER;
|
||||
frmt_reg = mmACP_I2STDM_RXFRMT;
|
||||
}
|
||||
}
|
||||
val = rv_readl(adata->acp3x_base + reg_val);
|
||||
rv_writel(val | 0x2, adata->acp3x_base + reg_val);
|
||||
rv_writel(frm_len, adata->acp3x_base + frmt_reg);
|
||||
adata->tdm_fmt = frm_len;
|
||||
return 0;
|
||||
}
|
||||
@ -105,12 +76,14 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *prtd;
|
||||
struct snd_soc_card *card;
|
||||
struct acp3x_platform_info *pinfo;
|
||||
struct i2s_dev_data *adata;
|
||||
u32 val;
|
||||
u32 reg_val;
|
||||
u32 reg_val, frmt_reg;
|
||||
|
||||
prtd = substream->private_data;
|
||||
rtd = substream->runtime->private_data;
|
||||
card = prtd->card;
|
||||
adata = snd_soc_dai_get_drvdata(dai);
|
||||
pinfo = snd_soc_card_get_drvdata(card);
|
||||
if (pinfo) {
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
@ -141,21 +114,30 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_BT_INSTANCE:
|
||||
reg_val = mmACP_BTTDM_ITER;
|
||||
frmt_reg = mmACP_BTTDM_TXFRMT;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = mmACP_I2STDM_ITER;
|
||||
frmt_reg = mmACP_I2STDM_TXFRMT;
|
||||
}
|
||||
} else {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_BT_INSTANCE:
|
||||
reg_val = mmACP_BTTDM_IRER;
|
||||
frmt_reg = mmACP_BTTDM_RXFRMT;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = mmACP_I2STDM_IRER;
|
||||
frmt_reg = mmACP_I2STDM_RXFRMT;
|
||||
}
|
||||
}
|
||||
if (adata->tdm_mode) {
|
||||
val = rv_readl(rtd->acp3x_base + reg_val);
|
||||
rv_writel(val | 0x2, rtd->acp3x_base + reg_val);
|
||||
rv_writel(adata->tdm_fmt, rtd->acp3x_base + frmt_reg);
|
||||
}
|
||||
val = rv_readl(rtd->acp3x_base + reg_val);
|
||||
val = val | (rtd->xfer_resolution << 3);
|
||||
rv_writel(val, rtd->acp3x_base + reg_val);
|
||||
|
@ -458,7 +458,8 @@ static int acp3x_resume(struct device *dev)
|
||||
reg_val = mmACP_I2STDM_ITER;
|
||||
frmt_val = mmACP_I2STDM_TXFRMT;
|
||||
}
|
||||
rv_writel((rtd->xfer_resolution << 3), rtd->acp3x_base + reg_val);
|
||||
rv_writel((rtd->xfer_resolution << 3),
|
||||
rtd->acp3x_base + reg_val);
|
||||
}
|
||||
if (adata->capture_stream && adata->capture_stream->runtime) {
|
||||
struct i2s_stream_instance *rtd =
|
||||
@ -474,7 +475,8 @@ static int acp3x_resume(struct device *dev)
|
||||
reg_val = mmACP_I2STDM_IRER;
|
||||
frmt_val = mmACP_I2STDM_RXFRMT;
|
||||
}
|
||||
rv_writel((rtd->xfer_resolution << 3), rtd->acp3x_base + reg_val);
|
||||
rv_writel((rtd->xfer_resolution << 3),
|
||||
rtd->acp3x_base + reg_val);
|
||||
}
|
||||
if (adata->tdm_mode == TDM_ENABLE) {
|
||||
rv_writel(adata->tdm_fmt, adata->acp3x_base + frmt_val);
|
||||
|
@ -38,8 +38,13 @@ static int acp3x_power_on(void __iomem *acp3x_base)
|
||||
timeout = 0;
|
||||
while (++timeout < 500) {
|
||||
val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
|
||||
if (!val)
|
||||
if (!val) {
|
||||
/* Set PME_EN as after ACP power On,
|
||||
* PME_EN gets cleared
|
||||
*/
|
||||
rv_writel(0x1, acp3x_base + mmACP_PME_EN);
|
||||
return 0;
|
||||
}
|
||||
udelay(1);
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
|
@ -56,7 +56,7 @@ static void atmel_pcm_dma_irq(u32 ssc_sr,
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct atmel_pcm_dma_params *prtd;
|
||||
|
||||
prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
prtd = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
|
||||
|
||||
if (ssc_sr & prtd->mask->ssc_error) {
|
||||
if (snd_pcm_running(substream))
|
||||
@ -83,7 +83,7 @@ static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
|
||||
struct ssc_device *ssc;
|
||||
int ret;
|
||||
|
||||
prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
prtd = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
|
||||
ssc = prtd->ssc;
|
||||
|
||||
ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
|
||||
|
@ -213,7 +213,7 @@ static int atmel_pcm_hw_params(struct snd_soc_component *component,
|
||||
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
|
||||
runtime->dma_bytes = params_buffer_bytes(params);
|
||||
|
||||
prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
prtd->params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
|
||||
prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
|
||||
|
||||
prtd->dma_buffer = runtime->dma_addr;
|
||||
|
@ -27,7 +27,7 @@ static int atmel_asoc_wm8904_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_dai_set_pll(codec_dai, WM8904_FLL_MCLK, WM8904_FLL_MCLK,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user