mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
sound updates for 6.7
Most of changes at this time are for ASoC, spread over ASoC core and drivers due to the API prefix standardization. Other than that, there have little change wrt API, rather lots of driver-specific updates and fixes. Some highlight below: ASoC: - Standardization of API prefix - GPIO API usage improvements - Support for HDA patches - Lots of work on SOF, including crash dump support - Fixes for noise when stopping some Sounwire CODECs - Support for AMD platforms with es83xx, AMD ACP 6.3 and 7.0, Awinc AT87390 and AW88399, many Intel platforms, many Mediatek platforms, Qualcomm SM6115 and SC7180 platforms, Richtek RTQ9128 and Texas Instruments TAS575x HD-audio and USB-audio: - Deferred probe support of audio component binding - More fixes and enhancements for Cirrus subcodecs - USB Scarlett2 mixer and McIntosh DSD quirk Others: - More enhancement of snd-aloop driver - Update MAINTAINERS entry for linux-sound mailing list -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmVDqXcOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE+PbhAAsmiOxjXpCNVGbhy9tR+UB9p6gCIzFv5RQQIc 0DzqnqssbJt86jtFMrv0VC6BNfnwcyBVzKxWinKz861xXiM9SRU5vTirUES3Cil/ sZaQYC9ppTrZm3q2EGF4eGC349oZGzuLzk1EkEVPfNHiELwcO4R1NZbtgWKIc8LE bNz8RT3FyxHAv+5juW5suGs0Bq4Mwa9z+eM8xEPwxPL3gpIAb5EapIesHEgaa893 w3jYwKRHCDq0ADtXIY9xI3ypqenfbeTge4nuBnw354sPRVdZInrRfCNkTJojb+tp 5Pc2gpFmTUGy6T2wG6QP23VgeV14BJHrQD3Z1Wh2aQ8V+ARa92XvY1Xeg4vJ+NE0 yhvlh028GjKrMIvhl7mmepV9mia2zA1TluqlzKEla3B5lIj0E1zvMA+vCzNAz3Ro lV2Q0dpJ3ENQ9ahGF/d37u3glrqXxISlG9uTGdY0UcF7U9Iyxb0jEnhQYl05b+zR Oaw/HApuvIUj4cdJWEYf0AnTTqeE8KSZ3wUlPPyuQAdAusCaQFMciWeO0EeLqEId KR/rbnSgVKS3zHLdNw5A67Sv36E9OG/E+EiJ6Tet15a69yq2Oyv4pwMMwbqsvBG5 8kNbtBFGxOHnCrZgM6VV2/g3BP/IwyIFd5kkS2q13FXBTYRpY01dQDjHlmspasNK hYH69AA= =2/dI -----END PGP SIGNATURE----- Merge tag 'sound-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "Most of changes at this time are for ASoC, spread over ASoC core and drivers due to the API prefix standardization. Other than that, there have little change wrt API, rather lots of driver-specific updates and fixes. Some highlight below: ASoC: - Standardization of API prefix - GPIO API usage improvements - Support for HDA patches - Lots of work on SOF, including crash dump support - Fixes for noise when stopping some Sounwire CODECs - Support for AMD platforms with es83xx, AMD ACP 6.3 and 7.0, Awinc AT87390 and AW88399, many Intel platforms, many Mediatek platforms, Qualcomm SM6115 and SC7180 platforms, Richtek RTQ9128 and Texas Instruments TAS575x HD-audio and USB-audio: - Deferred probe support of audio component binding - More fixes and enhancements for Cirrus subcodecs - USB Scarlett2 mixer and McIntosh DSD quirk Others: - More enhancement of snd-aloop driver - Update MAINTAINERS entry for linux-sound mailing list" * tag 'sound-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (485 commits) ALSA: hda: cs35l41: Fix missing error code in cs35l41_smart_amp() ALSA: hda: cs35l41: mark cs35l41_verify_id() static ASoC: codecs: wsa883x: make use of new mute_unmute_on_trigger flag ASoC: soc-dai: add flag to mute and unmute stream during trigger ASoC: ams-delta.c: use component after check ASoC: amd: acp: select SND_SOC_AMD_ACP_LEGACY_COMMON for ACP63 ASoC: codecs: aw88399: fix typo in Kconfig select ASoC: amd: acp: add ACPI dependency ASoC: Intel: avs: Add rt5514 machine board ASoC: Intel: avs: Add rt5514 machine board ALSA: scarlett2: Add missing check with firmware version control ALSA: virtio: use ack callback ALSA: scarlett2: Remap Level Meter values ALSA: scarlett2: Allow passing any output to line_out_remap() ALSA: scarlett2: Add support for reading firmware version ALSA: scarlett2: Rename Gen 3 config sets ALSA: scarlett2: Rename scarlett_gen2 to scarlett2 ASoC: cs35l41: Detect CSPL errors when sending CSPL commands ALSA: hda: cs35l41: Check CSPL state after loading firmware ALSA: hda: cs35l41: Do not unload firmware before reset in system suspend ...
This commit is contained in:
commit
edd8e84ae9
@ -13,19 +13,17 @@ select: false
|
||||
|
||||
definitions:
|
||||
port-base:
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
allOf:
|
||||
- $ref: /schemas/graph.yaml#/$defs/port-base
|
||||
- $ref: /schemas/sound/dai-params.yaml#
|
||||
properties:
|
||||
convert-rate:
|
||||
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate
|
||||
convert-channels:
|
||||
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels
|
||||
convert-sample-format:
|
||||
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format
|
||||
mclk-fs:
|
||||
$ref: simple-card.yaml#/definitions/mclk-fs
|
||||
|
||||
endpoint-base:
|
||||
$ref: /schemas/graph.yaml#/$defs/endpoint-base
|
||||
allOf:
|
||||
- $ref: /schemas/graph.yaml#/$defs/endpoint-base
|
||||
- $ref: /schemas/sound/dai-params.yaml#
|
||||
properties:
|
||||
mclk-fs:
|
||||
$ref: simple-card.yaml#/definitions/mclk-fs
|
||||
@ -68,12 +66,6 @@ definitions:
|
||||
- pdm
|
||||
- msb
|
||||
- lsb
|
||||
convert-rate:
|
||||
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate
|
||||
convert-channels:
|
||||
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels
|
||||
convert-sample-format:
|
||||
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format
|
||||
|
||||
dai-tdm-slot-num:
|
||||
description: Number of slots in use.
|
||||
|
@ -9,6 +9,9 @@ title: Audio Graph
|
||||
maintainers:
|
||||
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/sound/dai-params.yaml#
|
||||
|
||||
properties:
|
||||
dais:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
@ -30,12 +33,6 @@ properties:
|
||||
widget ("Microphone", "Line", "Headphone", "Speaker"), the
|
||||
second being the machine specific name for the widget.
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
convert-rate:
|
||||
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate
|
||||
convert-channels:
|
||||
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels
|
||||
convert-sample-format:
|
||||
$ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format
|
||||
|
||||
pa-gpios:
|
||||
maxItems: 1
|
||||
|
58
Documentation/devicetree/bindings/sound/awinic,aw87390.yaml
Normal file
58
Documentation/devicetree/bindings/sound/awinic,aw87390.yaml
Normal file
@ -0,0 +1,58 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/awinic,aw87390.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Awinic Aw87390 Audio Amplifier
|
||||
|
||||
maintainers:
|
||||
- Weidong Wang <wangweidong.a@awinic.com>
|
||||
|
||||
description:
|
||||
The awinic aw87390 is specifically designed to improve
|
||||
the musical output dynamic range, enhance the overall
|
||||
sound quallity, which is a new high efficiency, low
|
||||
noise, constant large volume, 6th Smart K audio amplifier.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: awinic,aw87390
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
awinic,audio-channel:
|
||||
description:
|
||||
It is used to distinguish multiple PA devices, so that different
|
||||
configurations can be loaded to different PA devices
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#sound-dai-cells"
|
||||
- awinic,audio-channel
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
audio-codec@58 {
|
||||
compatible = "awinic,aw87390";
|
||||
reg = <0x58>;
|
||||
#sound-dai-cells = <0>;
|
||||
awinic,audio-channel = <0>;
|
||||
};
|
||||
};
|
@ -14,14 +14,12 @@ description:
|
||||
digital Smart K audio amplifier with an integrated 10.25V
|
||||
smart boost convert.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- awinic,aw88395
|
||||
- awinic,aw88261
|
||||
- awinic,aw88399
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -32,11 +30,36 @@ properties:
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
awinic,audio-channel:
|
||||
description:
|
||||
It is used to distinguish multiple PA devices, so that different
|
||||
configurations can be loaded to different PA devices
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
|
||||
awinic,sync-flag:
|
||||
description:
|
||||
Flag bit used to keep the phase synchronized in the case of multiple PA
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#sound-dai-cells'
|
||||
- reset-gpios
|
||||
- awinic,audio-channel
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- awinic,aw88261
|
||||
then:
|
||||
properties:
|
||||
reset-gpios: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
@ -51,5 +74,7 @@ examples:
|
||||
reg = <0x34>;
|
||||
#sound-dai-cells = <0>;
|
||||
reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
|
||||
awinic,audio-channel = <0>;
|
||||
awinic,sync-flag;
|
||||
};
|
||||
};
|
||||
|
@ -83,7 +83,7 @@ properties:
|
||||
Current at which the headset micbias sense clamp will engage, 0 to
|
||||
disable.
|
||||
enum: [ 0, 14, 24, 43, 52, 61, 71, 90, 99 ]
|
||||
default: 0
|
||||
default: 14
|
||||
|
||||
cirrus,bias-ramp-ms:
|
||||
description:
|
||||
@ -97,7 +97,7 @@ properties:
|
||||
Time in microseconds the type detection will run for. Long values will
|
||||
cause more audible effects, but give more accurate detection.
|
||||
enum: [ 20, 100, 1000, 10000, 50000, 75000, 100000, 200000 ]
|
||||
default: 10000
|
||||
default: 1000
|
||||
|
||||
cirrus,button-automute:
|
||||
type: boolean
|
||||
|
@ -11,15 +11,14 @@ maintainers:
|
||||
|
||||
select: false
|
||||
|
||||
$defs:
|
||||
|
||||
dai-channels:
|
||||
properties:
|
||||
convert-channels:
|
||||
description: Number of audio channels used by DAI
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 1
|
||||
maximum: 32
|
||||
|
||||
dai-sample-format:
|
||||
convert-sample-format:
|
||||
description: Audio sample format used by DAI
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum:
|
||||
@ -29,12 +28,10 @@ $defs:
|
||||
- s24_3le
|
||||
- s32_le
|
||||
|
||||
dai-sample-rate:
|
||||
convert-rate:
|
||||
description: Audio sample rate used by DAI
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 8000
|
||||
maximum: 192000
|
||||
|
||||
properties: {}
|
||||
|
||||
additionalProperties: true
|
||||
|
@ -89,6 +89,7 @@ properties:
|
||||
|
||||
da7219_aad:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description:
|
||||
Configuration of advanced accessory detection.
|
||||
properties:
|
||||
|
@ -33,6 +33,7 @@ patternProperties:
|
||||
description:
|
||||
A DAI managed by this controller
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
reg:
|
||||
|
@ -17,6 +17,7 @@ properties:
|
||||
enum:
|
||||
- mediatek,mt8188-mt6359-evb
|
||||
- mediatek,mt8188-nau8825
|
||||
- mediatek,mt8188-rt5682s
|
||||
|
||||
audio-routing:
|
||||
description:
|
||||
|
@ -17,6 +17,7 @@ properties:
|
||||
enum:
|
||||
- mediatek,mt8186-mt6366-rt1019-rt5682s-sound
|
||||
- mediatek,mt8186-mt6366-rt5682s-max98360-sound
|
||||
- mediatek,mt8186-mt6366-rt5650-sound
|
||||
|
||||
mediatek,platform:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
44
Documentation/devicetree/bindings/sound/nxp,tfa9879.yaml
Normal file
44
Documentation/devicetree/bindings/sound/nxp,tfa9879.yaml
Normal file
@ -0,0 +1,44 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/nxp,tfa9879.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP TFA9879 class-D audio amplifier
|
||||
|
||||
maintainers:
|
||||
- Peter Rosin <peda@axentia.se>
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: nxp,tfa9879
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#sound-dai-cells'
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
amplifier@6c {
|
||||
compatible = "nxp,tfa9879";
|
||||
reg = <0x6c>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_i2c1>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
};
|
@ -1,12 +1,12 @@
|
||||
PCM512x audio CODECs
|
||||
PCM512x and TAS575x audio CODECs/amplifiers
|
||||
|
||||
These devices support both I2C and SPI (configured with pin strapping
|
||||
on the board).
|
||||
on the board). The TAS575x devices only support I2C.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141" or
|
||||
"ti,pcm5142"
|
||||
- compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141",
|
||||
"ti,pcm5142", "ti,tas5754" or "ti,tas5756"
|
||||
|
||||
- reg : the I2C address of the device for I2C, the chip select
|
||||
number for SPI.
|
||||
@ -25,6 +25,7 @@ Optional properties:
|
||||
through <6>. The device will be configured for clock input on the
|
||||
given pll-in pin and PLL output on the given pll-out pin. An
|
||||
external connection from the pll-out pin to the SCLK pin is assumed.
|
||||
Caution: the TAS-desvices only support gpios 1,2 and 3
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -13,6 +13,7 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sc7280-lpass-tx-macro
|
||||
- qcom,sm6115-lpass-tx-macro
|
||||
- qcom,sm8250-lpass-tx-macro
|
||||
- qcom,sm8450-lpass-tx-macro
|
||||
- qcom,sm8550-lpass-tx-macro
|
||||
@ -97,6 +98,23 @@ allOf:
|
||||
- const: dcodec
|
||||
- const: fsgen
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sm6115-lpass-tx-macro
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: mclk
|
||||
- const: npl
|
||||
- const: dcodec
|
||||
- const: fsgen
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -25,6 +25,7 @@ properties:
|
||||
- qcom,apq8016-sbc-sndcard
|
||||
- qcom,msm8916-qdsp6-sndcard
|
||||
- qcom,qrb5165-rb5-sndcard
|
||||
- qcom,sc7180-qdsp6-sndcard
|
||||
- qcom,sc8280xp-sndcard
|
||||
- qcom,sdm845-sndcard
|
||||
- qcom,sm8250-sndcard
|
||||
|
49
Documentation/devicetree/bindings/sound/realtek,rt5616.yaml
Normal file
49
Documentation/devicetree/bindings/sound/realtek,rt5616.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/realtek,rt5616.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Realtek rt5616 ALSA SoC audio codec driver
|
||||
|
||||
description: |
|
||||
Pins on the device (for linking into audio routes) for RT5616:
|
||||
|
||||
* IN1P
|
||||
* IN2P
|
||||
* IN2N
|
||||
* LOUTL
|
||||
* LOUTR
|
||||
* HPOL
|
||||
* HPOR
|
||||
|
||||
maintainers:
|
||||
- Bard Liao <bardliao@realtek.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: realtek,rt5616
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
audio-codec@1b {
|
||||
compatible = "realtek,rt5616";
|
||||
reg = <0x1b>;
|
||||
};
|
||||
};
|
61
Documentation/devicetree/bindings/sound/richtek,rtq9128.yaml
Normal file
61
Documentation/devicetree/bindings/sound/richtek,rtq9128.yaml
Normal file
@ -0,0 +1,61 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/richtek,rtq9128.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Richtek RTQ9128 Automative Audio Power Amplifier
|
||||
|
||||
maintainers:
|
||||
- ChiYuan Huang <cy_huang@richtek.com>
|
||||
|
||||
description:
|
||||
The RTQ9128 is a ultra-low output noise, high-efficiency, four-channel
|
||||
class-D audio power amplifier and delivering 4x75W into 4OHm at 10%
|
||||
THD+N from a 25V supply in automotive applications.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- richtek,rtq9128
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
enable-gpios:
|
||||
maxItems: 1
|
||||
|
||||
richtek,tdm-input-data2-select:
|
||||
type: boolean
|
||||
description:
|
||||
By default, if TDM mode is used, TDM data input will select 'DATA1' pin
|
||||
as the data source. This option will configure TDM data input source from
|
||||
'DATA1' to 'DATA2' pin.
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#sound-dai-cells'
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
speaker@1a {
|
||||
compatible = "richtek,rtq9128";
|
||||
reg = <0x1a>;
|
||||
enable-gpios = <&gpio 26 GPIO_ACTIVE_HIGH>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
};
|
@ -1,32 +0,0 @@
|
||||
RT5616 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "realtek,rt5616".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- clocks: The phandle of the master clock to the CODEC.
|
||||
|
||||
- clock-names: Should be "mclk".
|
||||
|
||||
Pins on the device (for linking into audio routes) for RT5616:
|
||||
|
||||
* IN1P
|
||||
* IN2P
|
||||
* IN2N
|
||||
* LOUTL
|
||||
* LOUTR
|
||||
* HPOL
|
||||
* HPOR
|
||||
|
||||
Example:
|
||||
|
||||
rt5616: codec@1b {
|
||||
compatible = "realtek,rt5616";
|
||||
reg = <0x1b>;
|
||||
};
|
@ -0,0 +1,76 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/starfive,jh7110-pwmdac.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: StarFive JH7110 PWM-DAC Controller
|
||||
|
||||
description:
|
||||
The PWM-DAC Controller uses PWM square wave generators plus RC filters to
|
||||
form a DAC for audio play in StarFive JH7110 SoC. This audio play controller
|
||||
supports 16 bit audio format, up to 48K sampling frequency, up to left and
|
||||
right dual channels.
|
||||
|
||||
maintainers:
|
||||
- Hal Feng <hal.feng@starfivetech.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: starfive,jh7110-pwmdac
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: PWMDAC APB
|
||||
- description: PWMDAC CORE
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: apb
|
||||
- const: core
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
description: PWMDAC APB
|
||||
|
||||
dmas:
|
||||
maxItems: 1
|
||||
description: TX DMA Channel
|
||||
|
||||
dma-names:
|
||||
const: tx
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- dmas
|
||||
- dma-names
|
||||
- "#sound-dai-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
pwmdac@100b0000 {
|
||||
compatible = "starfive,jh7110-pwmdac";
|
||||
reg = <0x100b0000 0x1000>;
|
||||
clocks = <&syscrg 157>,
|
||||
<&syscrg 158>;
|
||||
clock-names = "apb", "core";
|
||||
resets = <&syscrg 96>;
|
||||
dmas = <&dma 22>;
|
||||
dma-names = "tx";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
@ -37,6 +37,8 @@ properties:
|
||||
generated from TI's PPC3 tool.
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
@ -52,5 +54,4 @@ examples:
|
||||
ti,dsp-config-name = "mono_pbtl_48khz";
|
||||
};
|
||||
};
|
||||
|
||||
additionalProperties: true
|
||||
...
|
||||
|
@ -1,23 +0,0 @@
|
||||
NXP TFA9879 class-D audio amplifier
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "nxp,tfa9879"
|
||||
|
||||
- reg : the I2C address of the device
|
||||
|
||||
- #sound-dai-cells : must be 0.
|
||||
|
||||
Example:
|
||||
|
||||
&i2c1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_i2c1>;
|
||||
|
||||
amp: amp@6c {
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "nxp,tfa9879";
|
||||
reg = <0x6c>;
|
||||
};
|
||||
};
|
||||
|
@ -60,6 +60,7 @@ properties:
|
||||
|
||||
ports:
|
||||
$ref: audio-graph-port.yaml#/definitions/port-base
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
port@0:
|
||||
$ref: audio-graph-port.yaml#
|
||||
|
@ -8,10 +8,17 @@ Required properties:
|
||||
- Vdda-supply : phandle to a regulator for the analog power supply (2.7V - 5.5V)
|
||||
- Vdd-supply : phandle to a regulator for the digital power supply (2.7V - 3.6V)
|
||||
|
||||
Optional properties:
|
||||
|
||||
- wlf,fsampen:
|
||||
FSAMPEN pin value, 0 for low, 1 for high, 2 for disconnected.
|
||||
Defaults to 0 if left unspecified.
|
||||
|
||||
Example:
|
||||
|
||||
wm8782: stereo-adc {
|
||||
compatible = "wlf,wm8782";
|
||||
Vdda-supply = <&vdda_supply>;
|
||||
Vdd-supply = <&vdd_supply>;
|
||||
wlf,fsampen = <2>; /* 192KHz */
|
||||
};
|
||||
|
@ -70,7 +70,8 @@ file:
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.ignore_suspend = 1,
|
||||
.params = &dsp_codec_params,
|
||||
.c2c_params = &dsp_codec_params,
|
||||
.num_c2c_params = 1,
|
||||
},
|
||||
{
|
||||
.name = "DSP-CODEC",
|
||||
@ -81,12 +82,13 @@ file:
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.ignore_suspend = 1,
|
||||
.params = &dsp_codec_params,
|
||||
.c2c_params = &dsp_codec_params,
|
||||
.num_c2c_params = 1,
|
||||
},
|
||||
|
||||
Above code snippet is motivated from sound/soc/samsung/speyside.c.
|
||||
|
||||
Note the "params" callback which lets the dapm know that this
|
||||
Note the "c2c_params" callback which lets the dapm know that this
|
||||
dai_link is a codec to codec connection.
|
||||
|
||||
In dapm core a route is created between cpu_dai playback widget
|
||||
|
@ -368,7 +368,8 @@ The machine driver sets some additional parameters to the DAI link i.e.
|
||||
.codec_name = "modem",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.params = &dai_params,
|
||||
.c2c_params = &dai_params,
|
||||
.num_c2c_params = 1,
|
||||
}
|
||||
< ... more DAI links here ... >
|
||||
|
||||
|
24
MAINTAINERS
24
MAINTAINERS
@ -4959,6 +4959,7 @@ F: drivers/spi/spi-cs42l43*
|
||||
F: include/dt-bindings/sound/cs*
|
||||
F: include/linux/mfd/cs42l43*
|
||||
F: include/sound/cs*
|
||||
F: sound/pci/hda/cirrus*
|
||||
F: sound/pci/hda/cs*
|
||||
F: sound/pci/hda/hda_cs_dsp_ctl.*
|
||||
F: sound/soc/codecs/cs*
|
||||
@ -8217,7 +8218,7 @@ M: Geoffrey D. Bennett <g@b4.vu>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
|
||||
F: sound/usb/mixer_scarlett_gen2.c
|
||||
F: sound/usb/mixer_scarlett2.c
|
||||
|
||||
FORCEDETH GIGABIT ETHERNET DRIVER
|
||||
M: Rain River <rain.1986.08.12@gmail.com>
|
||||
@ -15522,7 +15523,7 @@ NXP TFA9879 DRIVER
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/tfa9879.txt
|
||||
F: Documentation/devicetree/bindings/sound/nxp,tfa9879.yaml
|
||||
F: sound/soc/codecs/tfa9879*
|
||||
|
||||
NXP-NCI NFC DRIVER
|
||||
@ -20187,7 +20188,7 @@ F: Documentation/devicetree/bindings/riscv/sophgo.yaml
|
||||
SOUND
|
||||
M: Jaroslav Kysela <perex@perex.cz>
|
||||
M: Takashi Iwai <tiwai@suse.com>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
W: http://www.alsa-project.org/
|
||||
Q: http://patchwork.kernel.org/project/alsa-devel/list/
|
||||
@ -20200,7 +20201,7 @@ F: tools/testing/selftests/alsa
|
||||
|
||||
SOUND - ALSA SELFTESTS
|
||||
M: Mark Brown <broonie@kernel.org>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
L: linux-sound@vger.kernel.org
|
||||
L: linux-kselftest@vger.kernel.org
|
||||
S: Supported
|
||||
F: tools/testing/selftests/alsa
|
||||
@ -20226,7 +20227,7 @@ F: sound/soc/soc-generic-dmaengine-pcm.c
|
||||
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
|
||||
M: Liam Girdwood <lgirdwood@gmail.com>
|
||||
M: Mark Brown <broonie@kernel.org>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://alsa-project.org/main/index.php/ASoC
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
|
||||
@ -20234,6 +20235,10 @@ F: Documentation/devicetree/bindings/sound/
|
||||
F: Documentation/sound/soc/
|
||||
F: include/dt-bindings/sound/
|
||||
F: include/sound/soc*
|
||||
F: include/sound/sof.h
|
||||
F: include/sound/sof/
|
||||
F: include/trace/events/sof*.h
|
||||
F: include/uapi/sound/asoc.h
|
||||
F: sound/soc/
|
||||
|
||||
SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS
|
||||
@ -20587,6 +20592,13 @@ S: Supported
|
||||
F: Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml
|
||||
F: drivers/clk/starfive/clk-starfive-jh7110-pll.c
|
||||
|
||||
STARFIVE JH7110 PWMDAC DRIVER
|
||||
M: Hal Feng <hal.feng@starfivetech.com>
|
||||
M: Xingyu Wu <xingyu.wu@starfivetech.com>
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
|
||||
F: sound/soc/starfive/jh7110_pwmdac.c
|
||||
|
||||
STARFIVE JH7110 SYSCON
|
||||
M: William Qiu <william.qiu@starfivetech.com>
|
||||
M: Xingyu Wu <xingyu.wu@starfivetech.com>
|
||||
@ -23061,7 +23073,7 @@ F: fs/vboxsf/*
|
||||
|
||||
VIRTUAL PCM TEST DRIVER
|
||||
M: Ivan Orlov <ivan.orlov0322@gmail.com>
|
||||
L: alsa-devel@alsa-project.org
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/sound/cards/pcmtest.rst
|
||||
F: sound/drivers/pcmtest.c
|
||||
|
@ -498,6 +498,15 @@ struct menelaus_platform_data n8x0_menelaus_platform_data = {
|
||||
.late_init = n8x0_menelaus_late_init,
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table nokia810_asoc_gpio_table = {
|
||||
.dev_id = "soc-audio",
|
||||
.table = {
|
||||
GPIO_LOOKUP("gpio-0-15", 10, "headset", GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP("gpio-80-111", 21, "speaker", GPIO_ACTIVE_HIGH),
|
||||
{ }
|
||||
},
|
||||
};
|
||||
|
||||
static int __init n8x0_late_initcall(void)
|
||||
{
|
||||
if (!board_caps)
|
||||
@ -505,6 +514,7 @@ static int __init n8x0_late_initcall(void)
|
||||
|
||||
n8x0_mmc_init();
|
||||
n8x0_usb_init();
|
||||
gpiod_add_lookup_table(&nokia810_asoc_gpio_table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -275,9 +275,19 @@ static struct platform_device pandora_backlight = {
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table pandora_soc_audio_gpios = {
|
||||
.dev_id = "soc-audio",
|
||||
.table = {
|
||||
GPIO_LOOKUP("gpio-112-127", 6, "dac", GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP("gpio-0-15", 14, "amp", GPIO_ACTIVE_HIGH),
|
||||
{ }
|
||||
},
|
||||
};
|
||||
|
||||
static void __init omap3_pandora_legacy_init(void)
|
||||
{
|
||||
platform_device_register(&pandora_backlight);
|
||||
gpiod_add_lookup_table(&pandora_soc_audio_gpios);
|
||||
}
|
||||
#endif /* CONFIG_ARCH_OMAP3 */
|
||||
|
||||
|
@ -881,7 +881,7 @@ static struct platform_device fsi_device = {
|
||||
.resource = fsi_resources,
|
||||
};
|
||||
|
||||
static struct asoc_simple_card_info fsi_da7210_info = {
|
||||
static struct simple_util_info fsi_da7210_info = {
|
||||
.name = "DA7210",
|
||||
.card = "FSIB-DA7210",
|
||||
.codec = "da7210.0-001a",
|
||||
|
@ -300,7 +300,7 @@ static struct platform_device fsi_device = {
|
||||
.resource = fsi_resources,
|
||||
};
|
||||
|
||||
static struct asoc_simple_card_info fsi_ak4642_info = {
|
||||
static struct simple_util_info fsi_ak4642_info = {
|
||||
.name = "AK4642",
|
||||
.card = "FSIA-AK4642",
|
||||
.codec = "ak4642-codec.0-0012",
|
||||
|
@ -522,6 +522,10 @@ static struct gpio_desc *of_find_gpio_rename(struct device_node *np,
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_CS42L56)
|
||||
{ "reset", "cirrus,gpio-nreset", "cirrus,cs42l56" },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_MT2701_CS42448)
|
||||
{ "i2s1-in-sel-gpio1", NULL, "mediatek,mt2701-cs42448-machine" },
|
||||
{ "i2s1-in-sel-gpio2", NULL, "mediatek,mt2701-cs42448-machine" },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_TLV320AIC3X)
|
||||
{ "reset", "gpio-reset", "ti,tlv320aic3x" },
|
||||
{ "reset", "gpio-reset", "ti,tlv320aic33" },
|
||||
|
@ -759,7 +759,7 @@ static int intel_prepare(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
if (dai_runtime->suspended) {
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_pcm_hw_params *hw_params;
|
||||
|
||||
hw_params = &rtd->dpcm[substream->stream].hw_params;
|
||||
|
@ -327,7 +327,7 @@ static int intel_prepare(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
if (dai_runtime->suspended) {
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_pcm_hw_params *hw_params;
|
||||
|
||||
hw_params = &rtd->dpcm[substream->stream].hw_params;
|
||||
|
@ -1819,7 +1819,7 @@ void sdw_shutdown_stream(void *sdw_substream)
|
||||
struct snd_soc_dai *dai;
|
||||
|
||||
/* Find stream from first CPU DAI */
|
||||
dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
|
||||
sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
|
||||
|
||||
|
@ -37,9 +37,6 @@ struct omap_tw4030_pdata {
|
||||
bool has_digimic0;
|
||||
bool has_digimic1;
|
||||
u8 has_linein;
|
||||
|
||||
/* Jack detect GPIO or <= 0 if it is not implemented */
|
||||
int jack_detect;
|
||||
};
|
||||
|
||||
#endif /* _OMAP_TWL4030_H_ */
|
||||
|
@ -11,7 +11,6 @@
|
||||
#define __CS35L41_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/firmware/cirrus/cs_dsp.h>
|
||||
|
||||
#define CS35L41_FIRSTREG 0x00000000
|
||||
@ -736,6 +735,7 @@
|
||||
#define CS35L41_REVID_B2 0xB2
|
||||
|
||||
#define CS35L41_HALO_CORE_RESET 0x00000200
|
||||
#define CS35L41_SOFTWARE_RESET 0x5A000000
|
||||
|
||||
#define CS35L41_FS1_WINDOW_MASK 0x000007FF
|
||||
#define CS35L41_FS2_WINDOW_MASK 0x00FFF800
|
||||
@ -816,6 +816,8 @@ struct cs35l41_otp_map_element_t {
|
||||
};
|
||||
|
||||
enum cs35l41_cspl_mbox_status {
|
||||
CSPL_MBOX_STS_ERROR = U32_MAX,
|
||||
CSPL_MBOX_STS_ERROR2 = 0x00ffffff, // firmware not always sign-extending 24-bit value
|
||||
CSPL_MBOX_STS_RUNNING = 0,
|
||||
CSPL_MBOX_STS_PAUSED = 1,
|
||||
CSPL_MBOX_STS_RDY_FOR_REINIT = 2,
|
||||
@ -902,7 +904,8 @@ int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap);
|
||||
int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
|
||||
struct cs35l41_hw_cfg *hw_cfg);
|
||||
bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type);
|
||||
int cs35l41_mdsync_up(struct regmap *regmap);
|
||||
int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l41_boost_type b_type,
|
||||
int enable, struct completion *pll_lock, bool firmware_running);
|
||||
int enable, bool firmware_running);
|
||||
|
||||
#endif /* __CS35L41_H */
|
||||
|
@ -242,9 +242,8 @@
|
||||
#define CS35L56_CONTROL_PORT_READY_US 2200
|
||||
#define CS35L56_HALO_STATE_POLL_US 1000
|
||||
#define CS35L56_HALO_STATE_TIMEOUT_US 50000
|
||||
#define CS35L56_HIBERNATE_WAKE_POLL_US 500
|
||||
#define CS35L56_HIBERNATE_WAKE_TIMEOUT_US 5000
|
||||
#define CS35L56_RESET_PULSE_MIN_US 1100
|
||||
#define CS35L56_WAKE_HOLD_TIME_US 1000
|
||||
|
||||
#define CS35L56_SDW1_PLAYBACK_PORT 1
|
||||
#define CS35L56_SDW1_CAPTURE_PORT 3
|
||||
|
@ -9,27 +9,27 @@
|
||||
|
||||
#include <sound/simple_card_utils.h>
|
||||
|
||||
typedef int (*GRAPH2_CUSTOM)(struct asoc_simple_priv *priv,
|
||||
typedef int (*GRAPH2_CUSTOM)(struct simple_util_priv *priv,
|
||||
struct device_node *lnk,
|
||||
struct link_info *li);
|
||||
|
||||
struct graph2_custom_hooks {
|
||||
int (*hook_pre)(struct asoc_simple_priv *priv);
|
||||
int (*hook_post)(struct asoc_simple_priv *priv);
|
||||
int (*hook_pre)(struct simple_util_priv *priv);
|
||||
int (*hook_post)(struct simple_util_priv *priv);
|
||||
GRAPH2_CUSTOM custom_normal;
|
||||
GRAPH2_CUSTOM custom_dpcm;
|
||||
GRAPH2_CUSTOM custom_c2c;
|
||||
};
|
||||
|
||||
int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev);
|
||||
int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev,
|
||||
int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev);
|
||||
int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev,
|
||||
struct graph2_custom_hooks *hooks);
|
||||
|
||||
int audio_graph2_link_normal(struct asoc_simple_priv *priv,
|
||||
int audio_graph2_link_normal(struct simple_util_priv *priv,
|
||||
struct device_node *lnk, struct link_info *li);
|
||||
int audio_graph2_link_dpcm(struct asoc_simple_priv *priv,
|
||||
int audio_graph2_link_dpcm(struct simple_util_priv *priv,
|
||||
struct device_node *lnk, struct link_info *li);
|
||||
int audio_graph2_link_c2c(struct asoc_simple_priv *priv,
|
||||
int audio_graph2_link_c2c(struct simple_util_priv *priv,
|
||||
struct device_node *lnk, struct link_info *li);
|
||||
|
||||
#endif /* __GRAPH_CARD_H */
|
||||
|
@ -91,6 +91,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
|
||||
#define AZX_REG_SD_BDLPL 0x18
|
||||
#define AZX_REG_SD_BDLPU 0x1c
|
||||
|
||||
#define AZX_SD_FIFOSIZE_MASK GENMASK(15, 0)
|
||||
|
||||
/* GTS registers */
|
||||
#define AZX_REG_LLCH 0x14
|
||||
|
||||
|
@ -573,7 +573,7 @@ void snd_hdac_stream_release(struct hdac_stream *azx_dev);
|
||||
struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus,
|
||||
int dir, int stream_tag);
|
||||
|
||||
int snd_hdac_stream_setup(struct hdac_stream *azx_dev);
|
||||
int snd_hdac_stream_setup(struct hdac_stream *azx_dev, bool code_loading);
|
||||
void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev);
|
||||
int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev);
|
||||
int snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
|
||||
@ -624,6 +624,9 @@ int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value);
|
||||
#define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
|
||||
read_poll_timeout_atomic(snd_hdac_reg_readb, val, cond, delay_us, timeout_us, \
|
||||
false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
#define snd_hdac_stream_readw_poll(dev, reg, val, cond, delay_us, timeout_us) \
|
||||
read_poll_timeout_atomic(snd_hdac_reg_readw, val, cond, delay_us, timeout_us, \
|
||||
false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
#define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
|
||||
read_poll_timeout_atomic(snd_hdac_reg_readl, val, cond, delay_us, timeout_us, \
|
||||
false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
|
@ -60,6 +60,8 @@ struct hdac_ext_stream {
|
||||
bool link_locked:1;
|
||||
bool link_prepared;
|
||||
|
||||
int (*host_setup)(struct hdac_stream *, bool);
|
||||
|
||||
struct snd_pcm_substream *link_substream;
|
||||
};
|
||||
|
||||
@ -86,6 +88,7 @@ void snd_hdac_ext_stream_start(struct hdac_ext_stream *hext_stream);
|
||||
void snd_hdac_ext_stream_clear(struct hdac_ext_stream *hext_stream);
|
||||
void snd_hdac_ext_stream_reset(struct hdac_ext_stream *hext_stream);
|
||||
int snd_hdac_ext_stream_setup(struct hdac_ext_stream *hext_stream, int fmt);
|
||||
int snd_hdac_ext_host_stream_setup(struct hdac_ext_stream *hext_stream, bool code_loading);
|
||||
|
||||
struct hdac_ext_link {
|
||||
struct hdac_bus *bus;
|
||||
|
@ -9,14 +9,10 @@
|
||||
|
||||
/**
|
||||
* struct max9768_pdata - optional platform specific MAX9768 configuration
|
||||
* @shdn_gpio: GPIO to SHDN pin. If not valid, pin must be hardwired HIGH
|
||||
* @mute_gpio: GPIO to MUTE pin. If not valid, control for mute won't be added
|
||||
* @flags: configuration flags, e.g. set classic PWM mode (check datasheet
|
||||
* regarding "filterless modulation" which is default).
|
||||
*/
|
||||
struct max9768_pdata {
|
||||
int shdn_gpio;
|
||||
int mute_gpio;
|
||||
unsigned flags;
|
||||
#define MAX9768_FLAG_CLASSIC_PWM (1 << 0)
|
||||
};
|
||||
|
@ -229,7 +229,7 @@ struct fm_operator {
|
||||
unsigned char attack_decay;
|
||||
unsigned char sustain_release;
|
||||
unsigned char wave_select;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* Instrument data */
|
||||
struct fm_instrument {
|
||||
|
@ -12,15 +12,15 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/simple_card_utils.h>
|
||||
|
||||
struct asoc_simple_card_info {
|
||||
struct simple_util_info {
|
||||
const char *name;
|
||||
const char *card;
|
||||
const char *codec;
|
||||
const char *platform;
|
||||
|
||||
unsigned int daifmt;
|
||||
struct asoc_simple_dai cpu_dai;
|
||||
struct asoc_simple_dai codec_dai;
|
||||
struct simple_util_dai cpu_dai;
|
||||
struct simple_util_dai codec_dai;
|
||||
};
|
||||
|
||||
#endif /* __SIMPLE_CARD_H */
|
||||
|
@ -11,18 +11,18 @@
|
||||
#include <linux/clk.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#define asoc_simple_init_hp(card, sjack, prefix) \
|
||||
asoc_simple_init_jack(card, sjack, 1, prefix, NULL)
|
||||
#define asoc_simple_init_mic(card, sjack, prefix) \
|
||||
asoc_simple_init_jack(card, sjack, 0, prefix, NULL)
|
||||
#define simple_util_init_hp(card, sjack, prefix) \
|
||||
simple_util_init_jack(card, sjack, 1, prefix, NULL)
|
||||
#define simple_util_init_mic(card, sjack, prefix) \
|
||||
simple_util_init_jack(card, sjack, 0, prefix, NULL)
|
||||
|
||||
struct asoc_simple_tdm_width_map {
|
||||
struct simple_util_tdm_width_map {
|
||||
u8 sample_bits;
|
||||
u8 slot_count;
|
||||
u16 slot_width;
|
||||
};
|
||||
|
||||
struct asoc_simple_dai {
|
||||
struct simple_util_dai {
|
||||
const char *name;
|
||||
unsigned int sysclk;
|
||||
int clk_direction;
|
||||
@ -32,17 +32,17 @@ struct asoc_simple_dai {
|
||||
unsigned int rx_slot_mask;
|
||||
struct clk *clk;
|
||||
bool clk_fixed;
|
||||
struct asoc_simple_tdm_width_map *tdm_width_map;
|
||||
struct simple_util_tdm_width_map *tdm_width_map;
|
||||
int n_tdm_widths;
|
||||
};
|
||||
|
||||
struct asoc_simple_data {
|
||||
struct simple_util_data {
|
||||
u32 convert_rate;
|
||||
u32 convert_channels;
|
||||
const char *convert_sample_format;
|
||||
};
|
||||
|
||||
struct asoc_simple_jack {
|
||||
struct simple_util_jack {
|
||||
struct snd_soc_jack jack;
|
||||
struct snd_soc_jack_pin pin;
|
||||
struct snd_soc_jack_gpio gpio;
|
||||
@ -54,21 +54,21 @@ struct prop_nums {
|
||||
int platforms;
|
||||
};
|
||||
|
||||
struct asoc_simple_priv {
|
||||
struct simple_util_priv {
|
||||
struct snd_soc_card snd_card;
|
||||
struct simple_dai_props {
|
||||
struct asoc_simple_dai *cpu_dai;
|
||||
struct asoc_simple_dai *codec_dai;
|
||||
struct asoc_simple_data adata;
|
||||
struct simple_util_dai *cpu_dai;
|
||||
struct simple_util_dai *codec_dai;
|
||||
struct simple_util_data adata;
|
||||
struct snd_soc_codec_conf *codec_conf;
|
||||
struct prop_nums num;
|
||||
unsigned int mclk_fs;
|
||||
} *dai_props;
|
||||
struct asoc_simple_jack hp_jack;
|
||||
struct asoc_simple_jack mic_jack;
|
||||
struct simple_util_jack hp_jack;
|
||||
struct simple_util_jack mic_jack;
|
||||
struct snd_soc_jack *aux_jacks;
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
struct asoc_simple_dai *dais;
|
||||
struct simple_util_dai *dais;
|
||||
struct snd_soc_dai_link_component *dlcs;
|
||||
struct snd_soc_codec_conf *codec_conf;
|
||||
struct gpio_desc *pa_gpio;
|
||||
@ -130,75 +130,75 @@ struct link_info {
|
||||
struct prop_nums num[SNDRV_MAX_LINKS];
|
||||
};
|
||||
|
||||
int asoc_simple_parse_daifmt(struct device *dev,
|
||||
int simple_util_parse_daifmt(struct device *dev,
|
||||
struct device_node *node,
|
||||
struct device_node *codec,
|
||||
char *prefix,
|
||||
unsigned int *retfmt);
|
||||
int asoc_simple_parse_tdm_width_map(struct device *dev, struct device_node *np,
|
||||
struct asoc_simple_dai *dai);
|
||||
int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np,
|
||||
struct simple_util_dai *dai);
|
||||
|
||||
__printf(3, 4)
|
||||
int asoc_simple_set_dailink_name(struct device *dev,
|
||||
int simple_util_set_dailink_name(struct device *dev,
|
||||
struct snd_soc_dai_link *dai_link,
|
||||
const char *fmt, ...);
|
||||
int asoc_simple_parse_card_name(struct snd_soc_card *card,
|
||||
int simple_util_parse_card_name(struct snd_soc_card *card,
|
||||
char *prefix);
|
||||
|
||||
int asoc_simple_parse_clk(struct device *dev,
|
||||
int simple_util_parse_clk(struct device *dev,
|
||||
struct device_node *node,
|
||||
struct asoc_simple_dai *simple_dai,
|
||||
struct simple_util_dai *simple_dai,
|
||||
struct snd_soc_dai_link_component *dlc);
|
||||
int asoc_simple_startup(struct snd_pcm_substream *substream);
|
||||
void asoc_simple_shutdown(struct snd_pcm_substream *substream);
|
||||
int asoc_simple_hw_params(struct snd_pcm_substream *substream,
|
||||
int simple_util_startup(struct snd_pcm_substream *substream);
|
||||
void simple_util_shutdown(struct snd_pcm_substream *substream);
|
||||
int simple_util_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params);
|
||||
int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd);
|
||||
int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd);
|
||||
int simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params);
|
||||
|
||||
#define asoc_simple_parse_tdm(np, dai) \
|
||||
#define simple_util_parse_tdm(np, dai) \
|
||||
snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \
|
||||
&(dai)->rx_slot_mask, \
|
||||
&(dai)->slots, \
|
||||
&(dai)->slot_width);
|
||||
|
||||
void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platforms,
|
||||
void simple_util_canonicalize_platform(struct snd_soc_dai_link_component *platforms,
|
||||
struct snd_soc_dai_link_component *cpus);
|
||||
void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus,
|
||||
void simple_util_canonicalize_cpu(struct snd_soc_dai_link_component *cpus,
|
||||
int is_single_links);
|
||||
|
||||
void asoc_simple_clean_reference(struct snd_soc_card *card);
|
||||
void simple_util_clean_reference(struct snd_soc_card *card);
|
||||
|
||||
void asoc_simple_parse_convert(struct device_node *np, char *prefix,
|
||||
struct asoc_simple_data *data);
|
||||
bool asoc_simple_is_convert_required(const struct asoc_simple_data *data);
|
||||
void simple_util_parse_convert(struct device_node *np, char *prefix,
|
||||
struct simple_util_data *data);
|
||||
bool simple_util_is_convert_required(const struct simple_util_data *data);
|
||||
|
||||
int asoc_simple_parse_routing(struct snd_soc_card *card,
|
||||
int simple_util_parse_routing(struct snd_soc_card *card,
|
||||
char *prefix);
|
||||
int asoc_simple_parse_widgets(struct snd_soc_card *card,
|
||||
int simple_util_parse_widgets(struct snd_soc_card *card,
|
||||
char *prefix);
|
||||
int asoc_simple_parse_pin_switches(struct snd_soc_card *card,
|
||||
int simple_util_parse_pin_switches(struct snd_soc_card *card,
|
||||
char *prefix);
|
||||
|
||||
int asoc_simple_init_jack(struct snd_soc_card *card,
|
||||
struct asoc_simple_jack *sjack,
|
||||
int simple_util_init_jack(struct snd_soc_card *card,
|
||||
struct simple_util_jack *sjack,
|
||||
int is_hp, char *prefix, char *pin);
|
||||
int asoc_simple_init_aux_jacks(struct asoc_simple_priv *priv,
|
||||
int simple_util_init_aux_jacks(struct simple_util_priv *priv,
|
||||
char *prefix);
|
||||
int asoc_simple_init_priv(struct asoc_simple_priv *priv,
|
||||
int simple_util_init_priv(struct simple_util_priv *priv,
|
||||
struct link_info *li);
|
||||
int asoc_simple_remove(struct platform_device *pdev);
|
||||
void simple_util_remove(struct platform_device *pdev);
|
||||
|
||||
int asoc_graph_card_probe(struct snd_soc_card *card);
|
||||
int asoc_graph_is_ports0(struct device_node *port);
|
||||
int asoc_graph_parse_dai(struct device *dev, struct device_node *ep,
|
||||
int graph_util_card_probe(struct snd_soc_card *card);
|
||||
int graph_util_is_ports0(struct device_node *port);
|
||||
int graph_util_parse_dai(struct device *dev, struct device_node *ep,
|
||||
struct snd_soc_dai_link_component *dlc, int *is_single_link);
|
||||
|
||||
#ifdef DEBUG
|
||||
static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
|
||||
static inline void simple_util_debug_dai(struct simple_util_priv *priv,
|
||||
char *name,
|
||||
struct asoc_simple_dai *dai)
|
||||
struct simple_util_dai *dai)
|
||||
{
|
||||
struct device *dev = simple_priv_to_dev(priv);
|
||||
|
||||
@ -228,7 +228,7 @@ static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
|
||||
name, dai->clk_direction ? "OUT" : "IN");
|
||||
}
|
||||
|
||||
static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
|
||||
static inline void simple_util_debug_info(struct simple_util_priv *priv)
|
||||
{
|
||||
struct snd_soc_card *card = simple_priv_to_card(priv);
|
||||
struct device *dev = simple_priv_to_dev(priv);
|
||||
@ -241,7 +241,7 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
|
||||
for (i = 0; i < card->num_links; i++) {
|
||||
struct simple_dai_props *props = simple_priv_to_props(priv, i);
|
||||
struct snd_soc_dai_link *link = simple_priv_to_link(priv, i);
|
||||
struct asoc_simple_dai *dai;
|
||||
struct simple_util_dai *dai;
|
||||
struct snd_soc_codec_conf *cnf;
|
||||
int j;
|
||||
|
||||
@ -249,10 +249,10 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
|
||||
|
||||
dev_dbg(dev, "cpu num = %d\n", link->num_cpus);
|
||||
for_each_prop_dai_cpu(props, j, dai)
|
||||
asoc_simple_debug_dai(priv, "cpu", dai);
|
||||
simple_util_debug_dai(priv, "cpu", dai);
|
||||
dev_dbg(dev, "codec num = %d\n", link->num_codecs);
|
||||
for_each_prop_dai_codec(props, j, dai)
|
||||
asoc_simple_debug_dai(priv, "codec", dai);
|
||||
simple_util_debug_dai(priv, "codec", dai);
|
||||
|
||||
if (link->name)
|
||||
dev_dbg(dev, "dai name = %s\n", link->name);
|
||||
@ -270,7 +270,7 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define asoc_simple_debug_info(priv)
|
||||
#define simple_util_debug_info(priv)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#endif /* __SIMPLE_CARD_UTILS_H */
|
||||
|
@ -32,6 +32,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[];
|
||||
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[];
|
||||
@ -42,6 +43,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[];
|
||||
|
||||
/*
|
||||
* generic table used for HDA codec-based platforms, possibly with
|
||||
|
@ -68,6 +68,10 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
|
||||
* @i2s_link_mask: I2S/TDM links enabled on the board
|
||||
* @num_dai_drivers: number of elements in @dai_drivers
|
||||
* @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode
|
||||
* @subsystem_vendor: optional PCI SSID vendor value
|
||||
* @subsystem_device: optional PCI SSID device value
|
||||
* @subsystem_id_set: true if a value has been written to
|
||||
* subsystem_vendor and subsystem_device.
|
||||
*/
|
||||
struct snd_soc_acpi_mach_params {
|
||||
u32 acpi_ipc_irq_index;
|
||||
@ -80,6 +84,9 @@ struct snd_soc_acpi_mach_params {
|
||||
u32 i2s_link_mask;
|
||||
u32 num_dai_drivers;
|
||||
struct snd_soc_dai_driver *dai_drivers;
|
||||
unsigned short subsystem_vendor;
|
||||
unsigned short subsystem_device;
|
||||
bool subsystem_id_set;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -59,6 +59,43 @@ int snd_soc_card_add_dai_link(struct snd_soc_card *card,
|
||||
void snd_soc_card_remove_dai_link(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_link);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static inline void snd_soc_card_set_pci_ssid(struct snd_soc_card *card,
|
||||
unsigned short vendor,
|
||||
unsigned short device)
|
||||
{
|
||||
card->pci_subsystem_vendor = vendor;
|
||||
card->pci_subsystem_device = device;
|
||||
card->pci_subsystem_set = true;
|
||||
}
|
||||
|
||||
static inline int snd_soc_card_get_pci_ssid(struct snd_soc_card *card,
|
||||
unsigned short *vendor,
|
||||
unsigned short *device)
|
||||
{
|
||||
if (!card->pci_subsystem_set)
|
||||
return -ENOENT;
|
||||
|
||||
*vendor = card->pci_subsystem_vendor;
|
||||
*device = card->pci_subsystem_device;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* !CONFIG_PCI */
|
||||
static inline void snd_soc_card_set_pci_ssid(struct snd_soc_card *card,
|
||||
unsigned short vendor,
|
||||
unsigned short device)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int snd_soc_card_get_pci_ssid(struct snd_soc_card *card,
|
||||
unsigned short *vendor,
|
||||
unsigned short *device)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/* device driver data */
|
||||
static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
|
||||
void *data)
|
||||
@ -78,8 +115,8 @@ struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card,
|
||||
struct snd_soc_pcm_runtime *rtd;
|
||||
|
||||
for_each_card_rtds(card, rtd) {
|
||||
if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name))
|
||||
return asoc_rtd_to_codec(rtd, 0);
|
||||
if (!strcmp(snd_soc_rtd_to_codec(rtd, 0)->name, dai_name))
|
||||
return snd_soc_rtd_to_codec(rtd, 0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -370,6 +370,7 @@ struct snd_soc_dai_ops {
|
||||
|
||||
/* bit field */
|
||||
unsigned int no_capture_mute:1;
|
||||
unsigned int mute_unmute_on_trigger:1;
|
||||
};
|
||||
|
||||
struct snd_soc_cdai_ops {
|
||||
|
@ -718,7 +718,7 @@ struct snd_soc_dapm_context {
|
||||
/* A list of widgets associated with an object, typically a snd_kcontrol */
|
||||
struct snd_soc_dapm_widget_list {
|
||||
int num_widgets;
|
||||
struct snd_soc_dapm_widget *widgets[];
|
||||
struct snd_soc_dapm_widget *widgets[] __counted_by(num_widgets);
|
||||
};
|
||||
|
||||
#define for_each_dapm_widgets(list, i, widget) \
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef __LINUX_SND_SOC_H
|
||||
#define __LINUX_SND_SOC_H
|
||||
|
||||
#include <linux/args.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
@ -775,36 +776,36 @@ struct snd_soc_dai_link {
|
||||
};
|
||||
|
||||
static inline struct snd_soc_dai_link_component*
|
||||
asoc_link_to_cpu(struct snd_soc_dai_link *link, int n) {
|
||||
snd_soc_link_to_cpu(struct snd_soc_dai_link *link, int n) {
|
||||
return &(link)->cpus[n];
|
||||
}
|
||||
|
||||
static inline struct snd_soc_dai_link_component*
|
||||
asoc_link_to_codec(struct snd_soc_dai_link *link, int n) {
|
||||
snd_soc_link_to_codec(struct snd_soc_dai_link *link, int n) {
|
||||
return &(link)->codecs[n];
|
||||
}
|
||||
|
||||
static inline struct snd_soc_dai_link_component*
|
||||
asoc_link_to_platform(struct snd_soc_dai_link *link, int n) {
|
||||
snd_soc_link_to_platform(struct snd_soc_dai_link *link, int n) {
|
||||
return &(link)->platforms[n];
|
||||
}
|
||||
|
||||
#define for_each_link_codecs(link, i, codec) \
|
||||
for ((i) = 0; \
|
||||
((i) < link->num_codecs) && \
|
||||
((codec) = asoc_link_to_codec(link, i)); \
|
||||
((codec) = snd_soc_link_to_codec(link, i)); \
|
||||
(i)++)
|
||||
|
||||
#define for_each_link_platforms(link, i, platform) \
|
||||
for ((i) = 0; \
|
||||
((i) < link->num_platforms) && \
|
||||
((platform) = asoc_link_to_platform(link, i)); \
|
||||
((platform) = snd_soc_link_to_platform(link, i)); \
|
||||
(i)++)
|
||||
|
||||
#define for_each_link_cpus(link, i, cpu) \
|
||||
for ((i) = 0; \
|
||||
((i) < link->num_cpus) && \
|
||||
((cpu) = asoc_link_to_cpu(link, i)); \
|
||||
((cpu) = snd_soc_link_to_cpu(link, i)); \
|
||||
(i)++)
|
||||
|
||||
/*
|
||||
@ -870,12 +871,8 @@ asoc_link_to_platform(struct snd_soc_dai_link *link, int n) {
|
||||
.platforms = platform, \
|
||||
.num_platforms = ARRAY_SIZE(platform)
|
||||
|
||||
#define SND_SOC_DAILINK_REGx(_1, _2, _3, func, ...) func
|
||||
#define SND_SOC_DAILINK_REG(...) \
|
||||
SND_SOC_DAILINK_REGx(__VA_ARGS__, \
|
||||
SND_SOC_DAILINK_REG3, \
|
||||
SND_SOC_DAILINK_REG2, \
|
||||
SND_SOC_DAILINK_REG1)(__VA_ARGS__)
|
||||
CONCATENATE(SND_SOC_DAILINK_REG, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#define SND_SOC_DAILINK_DEF(name, def...) \
|
||||
static struct snd_soc_dai_link_component name[] = { def }
|
||||
@ -895,7 +892,7 @@ asoc_link_to_platform(struct snd_soc_dai_link *link, int n) {
|
||||
#define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", }
|
||||
|
||||
extern struct snd_soc_dai_link_component null_dailink_component[0];
|
||||
extern struct snd_soc_dai_link_component asoc_dummy_dlc;
|
||||
extern struct snd_soc_dai_link_component snd_soc_dummy_dlc;
|
||||
|
||||
|
||||
struct snd_soc_codec_conf {
|
||||
@ -932,6 +929,17 @@ struct snd_soc_card {
|
||||
#ifdef CONFIG_DMI
|
||||
char dmi_longname[80];
|
||||
#endif /* CONFIG_DMI */
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/*
|
||||
* PCI does not define 0 as invalid, so pci_subsystem_set indicates
|
||||
* whether a value has been written to these fields.
|
||||
*/
|
||||
unsigned short pci_subsystem_vendor;
|
||||
unsigned short pci_subsystem_device;
|
||||
bool pci_subsystem_set;
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
char topology_shortname[32];
|
||||
|
||||
struct device *dev;
|
||||
@ -1102,8 +1110,8 @@ struct snd_soc_pcm_runtime {
|
||||
* dais = cpu_dai + codec_dai
|
||||
* see
|
||||
* soc_new_pcm_runtime()
|
||||
* asoc_rtd_to_cpu()
|
||||
* asoc_rtd_to_codec()
|
||||
* snd_soc_rtd_to_cpu()
|
||||
* snd_soc_rtd_to_codec()
|
||||
*/
|
||||
struct snd_soc_dai **dais;
|
||||
|
||||
@ -1131,10 +1139,11 @@ struct snd_soc_pcm_runtime {
|
||||
int num_components;
|
||||
struct snd_soc_component *components[]; /* CPU/Codec/Platform */
|
||||
};
|
||||
|
||||
/* see soc_new_pcm_runtime() */
|
||||
#define asoc_rtd_to_cpu(rtd, n) (rtd)->dais[n]
|
||||
#define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus]
|
||||
#define asoc_substream_to_rtd(substream) \
|
||||
#define snd_soc_rtd_to_cpu(rtd, n) (rtd)->dais[n]
|
||||
#define snd_soc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus]
|
||||
#define snd_soc_substream_to_rtd(substream) \
|
||||
(struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream)
|
||||
|
||||
#define for_each_rtd_components(rtd, i, component) \
|
||||
@ -1143,11 +1152,11 @@ struct snd_soc_pcm_runtime {
|
||||
(i)++)
|
||||
#define for_each_rtd_cpu_dais(rtd, i, dai) \
|
||||
for ((i) = 0; \
|
||||
((i) < rtd->dai_link->num_cpus) && ((dai) = asoc_rtd_to_cpu(rtd, i)); \
|
||||
((i) < rtd->dai_link->num_cpus) && ((dai) = snd_soc_rtd_to_cpu(rtd, i)); \
|
||||
(i)++)
|
||||
#define for_each_rtd_codec_dais(rtd, i, dai) \
|
||||
for ((i) = 0; \
|
||||
((i) < rtd->dai_link->num_codecs) && ((dai) = asoc_rtd_to_codec(rtd, i)); \
|
||||
((i) < rtd->dai_link->num_codecs) && ((dai) = snd_soc_rtd_to_codec(rtd, i)); \
|
||||
(i)++)
|
||||
#define for_each_rtd_dais(rtd, i, dai) \
|
||||
for ((i) = 0; \
|
||||
|
@ -52,8 +52,8 @@ enum sof_dsp_power_states {
|
||||
|
||||
/* Definitions for multiple IPCs */
|
||||
enum sof_ipc_type {
|
||||
SOF_IPC,
|
||||
SOF_INTEL_IPC4,
|
||||
SOF_IPC_TYPE_3,
|
||||
SOF_IPC_TYPE_4,
|
||||
SOF_IPC_TYPE_COUNT
|
||||
};
|
||||
|
||||
@ -64,6 +64,14 @@ struct snd_sof_pdata {
|
||||
const char *name;
|
||||
const char *platform;
|
||||
|
||||
/*
|
||||
* PCI SSID. As PCI does not define 0 as invalid, the subsystem_id_set
|
||||
* flag indicates that a value has been written to these members.
|
||||
*/
|
||||
unsigned short subsystem_vendor;
|
||||
unsigned short subsystem_device;
|
||||
bool subsystem_id_set;
|
||||
|
||||
struct device *dev;
|
||||
|
||||
/*
|
||||
|
@ -106,12 +106,19 @@ enum sof_ipc4_global_msg {
|
||||
SOF_IPC4_GLB_SAVE_PIPELINE,
|
||||
SOF_IPC4_GLB_RESTORE_PIPELINE,
|
||||
|
||||
/* Loads library (using Code Load or HD/A Host Output DMA) */
|
||||
/*
|
||||
* library loading
|
||||
*
|
||||
* Loads library (using Code Load or HD/A Host Output DMA)
|
||||
*/
|
||||
SOF_IPC4_GLB_LOAD_LIBRARY,
|
||||
/*
|
||||
* Prepare the host DMA channel for library loading, must be followed by
|
||||
* a SOF_IPC4_GLB_LOAD_LIBRARY message as the library loading step
|
||||
*/
|
||||
SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE,
|
||||
|
||||
/* 25: RESERVED - do not use */
|
||||
|
||||
SOF_IPC4_GLB_INTERNAL_MESSAGE = 26,
|
||||
SOF_IPC4_GLB_INTERNAL_MESSAGE,
|
||||
|
||||
/* Notification (FW to SW driver) */
|
||||
SOF_IPC4_GLB_NOTIFICATION,
|
||||
@ -508,6 +515,23 @@ struct sof_ipc4_notify_resource_data {
|
||||
uint32_t data[6];
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define SOF_IPC4_DEBUG_DESCRIPTOR_SIZE 12 /* 3 x u32 */
|
||||
|
||||
/*
|
||||
* The debug memory window is divided into 16 slots, and the
|
||||
* first slot is used as a recorder for the other 15 slots.
|
||||
*/
|
||||
#define SOF_IPC4_MAX_DEBUG_SLOTS 15
|
||||
#define SOF_IPC4_DEBUG_SLOT_SIZE 0x1000
|
||||
|
||||
/* debug log slot types */
|
||||
#define SOF_IPC4_DEBUG_SLOT_UNUSED 0x00000000
|
||||
#define SOF_IPC4_DEBUG_SLOT_CRITICAL_LOG 0x54524300 /* byte 0: core ID */
|
||||
#define SOF_IPC4_DEBUG_SLOT_DEBUG_LOG 0x474f4c00 /* byte 0: core ID */
|
||||
#define SOF_IPC4_DEBUG_SLOT_GDB_STUB 0x42444700
|
||||
#define SOF_IPC4_DEBUG_SLOT_TELEMETRY 0x4c455400
|
||||
#define SOF_IPC4_DEBUG_SLOT_BROKEN 0x44414544
|
||||
|
||||
/** @}*/
|
||||
|
||||
#endif
|
||||
|
@ -77,6 +77,11 @@ struct tasdev_blk {
|
||||
unsigned int nr_cmds;
|
||||
unsigned int blk_size;
|
||||
unsigned int nr_subblocks;
|
||||
/* fixed m68k compiling issue, storing the dev_idx as a member of block
|
||||
* can reduce unnecessary timeand system resource comsumption of
|
||||
* dev_idx mapping every time the block data writing to the dsp.
|
||||
*/
|
||||
unsigned char dev_idx;
|
||||
unsigned char *data;
|
||||
};
|
||||
|
||||
|
@ -8,34 +8,6 @@
|
||||
* Copyright (c) by Paul Barton-Davis <pbd@op.net>
|
||||
*/
|
||||
|
||||
#if (!defined(__GNUC__) && !defined(__GNUG__))
|
||||
|
||||
You will not be able to compile this file correctly without gcc, because
|
||||
it is necessary to pack the "wavefront_alias" structure to a size
|
||||
of 22 bytes, corresponding to 16-bit alignment (as would have been
|
||||
the case on the original platform, MS-DOS). If this is not done,
|
||||
then WavePatch-format files cannot be read/written correctly.
|
||||
The method used to do this here ("__attribute__((packed)") is
|
||||
completely compiler dependent.
|
||||
|
||||
All other wavefront_* types end up aligned to 32 bit values and
|
||||
still have the same (correct) size.
|
||||
|
||||
#else
|
||||
|
||||
/* However, note that as of G++ 2.7.3.2, g++ was unable to
|
||||
correctly parse *type* __attribute__ tags. It will do the
|
||||
right thing if we use the "packed" attribute on each struct
|
||||
member, which has the same semantics anyway.
|
||||
*/
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
/***************************** WARNING ********************************
|
||||
PLEASE DO NOT MODIFY THIS FILE IN ANY WAY THAT AFFECTS ITS ABILITY TO
|
||||
BE USED WITH EITHER C *OR* C++.
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef NUM_MIDIKEYS
|
||||
#define NUM_MIDIKEYS 128
|
||||
#endif /* NUM_MIDIKEYS */
|
||||
@ -44,29 +16,6 @@
|
||||
#define NUM_MIDICHANNELS 16
|
||||
#endif /* NUM_MIDICHANNELS */
|
||||
|
||||
/* These are very useful/important. the original wavefront interface
|
||||
was developed on a 16 bit system, where sizeof(int) = 2
|
||||
bytes. Defining things like this makes the code much more portable, and
|
||||
easier to understand without having to toggle back and forth
|
||||
between a 16-bit view of the world and a 32-bit one.
|
||||
*/
|
||||
|
||||
#ifndef __KERNEL__
|
||||
/* keep them for compatibility */
|
||||
typedef short s16;
|
||||
typedef unsigned short u16;
|
||||
typedef int s32;
|
||||
typedef unsigned int u32;
|
||||
typedef char s8;
|
||||
typedef unsigned char u8;
|
||||
typedef s16 INT16;
|
||||
typedef u16 UINT16;
|
||||
typedef s32 INT32;
|
||||
typedef u32 UINT32;
|
||||
typedef s8 CHAR8;
|
||||
typedef u8 UCHAR8;
|
||||
#endif
|
||||
|
||||
/* Pseudo-commands not part of the WaveFront command set.
|
||||
These are used for various driver controls and direct
|
||||
hardware control.
|
||||
@ -468,7 +417,7 @@ typedef struct wf_alias {
|
||||
*/
|
||||
|
||||
u8 sixteen_bit_padding;
|
||||
} __attribute__((packed)) wavefront_alias;
|
||||
} __packed wavefront_alias;
|
||||
|
||||
typedef struct wf_drum {
|
||||
u8 PatchNumber;
|
||||
|
@ -207,7 +207,7 @@ struct snd_seq_ev_raw32 {
|
||||
struct snd_seq_ev_ext {
|
||||
unsigned int len; /* length of data */
|
||||
void *ptr; /* pointer to data (note: maybe 64-bit) */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct snd_seq_result {
|
||||
int event; /* processed event type */
|
||||
@ -251,7 +251,7 @@ struct snd_seq_ev_quote {
|
||||
struct snd_seq_addr origin; /* original sender */
|
||||
unsigned short value; /* optional data */
|
||||
struct snd_seq_event *event; /* quoted event */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
union snd_seq_event_data { /* event data... */
|
||||
struct snd_seq_ev_note note;
|
||||
|
@ -9,7 +9,6 @@
|
||||
#define __AOA_GPIO_H
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
typedef void (*notify_func_t)(void *data);
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#ifndef __AOA_H
|
||||
#define __AOA_H
|
||||
#include <asm/prom.h>
|
||||
#include <linux/module.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/asound.h>
|
||||
|
@ -30,6 +30,7 @@
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -8,7 +8,6 @@
|
||||
#define __SND_AOA_CODEC_ONYX_H
|
||||
#include <linux/i2c.h>
|
||||
#include <asm/pmac_low_i2c.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
/* PCM3052 register definitions */
|
||||
|
||||
|
@ -60,10 +60,10 @@
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
#include <asm/pmac_low_i2c.h>
|
||||
#include <asm/prom.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
|
||||
|
@ -7,9 +7,10 @@
|
||||
* This fabric module looks for sound codecs based on the
|
||||
* layout-id or device-id property in the device tree.
|
||||
*/
|
||||
#include <asm/prom.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include "../aoa.h"
|
||||
#include "../soundbus/soundbus.h"
|
||||
|
@ -6,6 +6,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include "soundbus.h"
|
||||
|
||||
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
#include <asm/macio.h>
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/pmac_pfunc.h>
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include <sound/pcm.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/dbdma.h>
|
||||
|
||||
|
@ -34,7 +34,7 @@ struct i2s_interface_regs {
|
||||
__le32 peak_level_in1; /* 0x90 */
|
||||
PAD(12);
|
||||
/* total size: 0x100 bytes */
|
||||
} __attribute__((__packed__));
|
||||
} __packed;
|
||||
|
||||
/* interrupt register is just a bitfield with
|
||||
* interrupt enable and pending bits */
|
||||
|
@ -7,7 +7,7 @@
|
||||
#ifndef __SOUNDBUS_H
|
||||
#define __SOUNDBUS_H
|
||||
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
|
@ -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(asoc_rtd_to_cpu(rtd, 0), substream);
|
||||
dma_params = snd_soc_dai_get_dma_data(snd_soc_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(asoc_rtd_to_cpu(rtd, 0), substream),
|
||||
snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream),
|
||||
&config);
|
||||
|
||||
ret = dmaengine_slave_config(chan, &config);
|
||||
@ -86,7 +86,7 @@ int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
|
||||
|
||||
runtime->hw = pxa2xx_pcm_hardware;
|
||||
|
||||
dma_params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
|
||||
dma_params = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream);
|
||||
if (!dma_params)
|
||||
return 0;
|
||||
|
||||
@ -111,7 +111,7 @@ int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
|
||||
return ret;
|
||||
|
||||
return snd_dmaengine_pcm_open(
|
||||
substream, dma_request_slave_channel(asoc_rtd_to_cpu(rtd, 0)->dev,
|
||||
substream, dma_request_slave_channel(snd_soc_rtd_to_cpu(rtd, 0)->dev,
|
||||
dma_params->chan_name));
|
||||
}
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_open);
|
||||
|
@ -74,7 +74,7 @@ struct snd_ctl_elem_info32 {
|
||||
unsigned char reserved[128];
|
||||
} value;
|
||||
unsigned char reserved[64];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
|
||||
struct snd_ctl_elem_info32 __user *data32)
|
||||
|
@ -3089,7 +3089,7 @@ struct snd_pcm_mmap_status32 {
|
||||
snd_pcm_state_t suspended_state;
|
||||
s32 audio_tstamp_sec;
|
||||
s32 audio_tstamp_nsec;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct snd_pcm_mmap_control32 {
|
||||
u32 appl_ptr;
|
||||
@ -3106,7 +3106,7 @@ struct snd_pcm_sync_ptr32 {
|
||||
struct snd_pcm_mmap_control32 control;
|
||||
unsigned char reserved[64];
|
||||
} c;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* recalcuate the boundary within 32bit */
|
||||
static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
|
||||
|
@ -15,7 +15,7 @@ struct snd_rawmidi_params32 {
|
||||
unsigned int no_active_sensing; /* avoid bit-field */
|
||||
unsigned int mode;
|
||||
unsigned char reserved[12];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
|
||||
struct snd_rawmidi_params32 __user *src)
|
||||
@ -51,7 +51,7 @@ struct compat_snd_rawmidi_status64 {
|
||||
u32 avail;
|
||||
u32 xruns;
|
||||
unsigned char reserved[16];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
static int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile,
|
||||
struct compat_snd_rawmidi_status64 __user *src)
|
||||
|
@ -119,11 +119,13 @@ struct loopback_setup {
|
||||
unsigned int rate_shift;
|
||||
snd_pcm_format_t format;
|
||||
unsigned int rate;
|
||||
snd_pcm_access_t access;
|
||||
unsigned int channels;
|
||||
struct snd_ctl_elem_id active_id;
|
||||
struct snd_ctl_elem_id format_id;
|
||||
struct snd_ctl_elem_id rate_id;
|
||||
struct snd_ctl_elem_id channels_id;
|
||||
struct snd_ctl_elem_id access_id;
|
||||
};
|
||||
|
||||
struct loopback {
|
||||
@ -158,6 +160,9 @@ struct loopback_pcm {
|
||||
unsigned long last_jiffies;
|
||||
/* If jiffies timer is used */
|
||||
struct timer_list timer;
|
||||
|
||||
/* size of per channel buffer in case of non-interleaved access */
|
||||
unsigned int channel_buf_n;
|
||||
};
|
||||
|
||||
static struct platform_device *devices[SNDRV_CARDS];
|
||||
@ -335,7 +340,8 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
|
||||
substream->runtime;
|
||||
check = runtime->format != cruntime->format ||
|
||||
runtime->rate != cruntime->rate ||
|
||||
runtime->channels != cruntime->channels;
|
||||
runtime->channels != cruntime->channels ||
|
||||
runtime->access != cruntime->access;
|
||||
if (!check)
|
||||
return 0;
|
||||
if (stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
@ -363,6 +369,11 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
|
||||
&setup->channels_id);
|
||||
setup->channels = runtime->channels;
|
||||
}
|
||||
if (setup->access != runtime->access) {
|
||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
|
||||
&setup->access_id);
|
||||
setup->access = runtime->access;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -472,6 +483,7 @@ static int loopback_prepare(struct snd_pcm_substream *substream)
|
||||
|
||||
dpcm->buf_pos = 0;
|
||||
dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
|
||||
dpcm->channel_buf_n = dpcm->pcm_buffer_size / runtime->channels;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
/* clear capture buffer */
|
||||
dpcm->silent_size = dpcm->pcm_buffer_size;
|
||||
@ -522,6 +534,22 @@ static void clear_capture_buf(struct loopback_pcm *dpcm, unsigned int bytes)
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_play_buf_part_n(struct loopback_pcm *play, struct loopback_pcm *capt,
|
||||
unsigned int size, unsigned int src_off, unsigned int dst_off)
|
||||
{
|
||||
unsigned int channels = capt->substream->runtime->channels;
|
||||
unsigned int size_p_ch = size / channels;
|
||||
unsigned int src_off_ch = src_off / channels;
|
||||
unsigned int dst_off_ch = dst_off / channels;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < channels; i++) {
|
||||
memcpy(capt->substream->runtime->dma_area + capt->channel_buf_n * i + dst_off_ch,
|
||||
play->substream->runtime->dma_area + play->channel_buf_n * i + src_off_ch,
|
||||
size_p_ch);
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_play_buf(struct loopback_pcm *play,
|
||||
struct loopback_pcm *capt,
|
||||
unsigned int bytes)
|
||||
@ -556,7 +584,11 @@ static void copy_play_buf(struct loopback_pcm *play,
|
||||
size = play->pcm_buffer_size - src_off;
|
||||
if (dst_off + size > capt->pcm_buffer_size)
|
||||
size = capt->pcm_buffer_size - dst_off;
|
||||
memcpy(dst + dst_off, src + src_off, size);
|
||||
if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ||
|
||||
runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED)
|
||||
copy_play_buf_part_n(play, capt, size, src_off, dst_off);
|
||||
else
|
||||
memcpy(dst + dst_off, src + src_off, size);
|
||||
capt->silent_size = 0;
|
||||
bytes -= size;
|
||||
if (!bytes)
|
||||
@ -878,7 +910,7 @@ static const struct snd_pcm_hardware loopback_pcm_hardware =
|
||||
{
|
||||
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE |
|
||||
SNDRV_PCM_INFO_RESUME),
|
||||
SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_NONINTERLEAVED),
|
||||
.formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |
|
||||
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
|
||||
@ -1495,6 +1527,30 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int loopback_access_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
const char * const texts[] = {"Interleaved", "Non-interleaved"};
|
||||
|
||||
return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
|
||||
}
|
||||
|
||||
static int loopback_access_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
|
||||
snd_pcm_access_t access;
|
||||
|
||||
mutex_lock(&loopback->cable_lock);
|
||||
access = loopback->setup[kcontrol->id.subdevice][kcontrol->id.device].access;
|
||||
|
||||
ucontrol->value.enumerated.item[0] = access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ||
|
||||
access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED;
|
||||
|
||||
mutex_unlock(&loopback->cable_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new loopback_controls[] = {
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
||||
@ -1541,7 +1597,15 @@ static const struct snd_kcontrol_new loopback_controls[] = {
|
||||
.name = "PCM Slave Channels",
|
||||
.info = loopback_channels_info,
|
||||
.get = loopback_channels_get
|
||||
}
|
||||
},
|
||||
#define ACCESS_IDX 6
|
||||
{
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READ,
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
||||
.name = "PCM Slave Access Mode",
|
||||
.info = loopback_access_info,
|
||||
.get = loopback_access_get,
|
||||
},
|
||||
};
|
||||
|
||||
static int loopback_mixer_new(struct loopback *loopback, int notify)
|
||||
@ -1562,6 +1626,7 @@ static int loopback_mixer_new(struct loopback *loopback, int notify)
|
||||
setup->notify = notify;
|
||||
setup->rate_shift = NO_PITCH;
|
||||
setup->format = SNDRV_PCM_FORMAT_S16_LE;
|
||||
setup->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
|
||||
setup->rate = 48000;
|
||||
setup->channels = 2;
|
||||
for (idx = 0; idx < ARRAY_SIZE(loopback_controls);
|
||||
@ -1593,6 +1658,9 @@ static int loopback_mixer_new(struct loopback *loopback, int notify)
|
||||
case CHANNELS_IDX:
|
||||
setup->channels_id = kctl->id;
|
||||
break;
|
||||
case ACCESS_IDX:
|
||||
setup->access_id = kctl->id;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -10,12 +10,47 @@
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci_ids.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/hda_register.h>
|
||||
#include <sound/hdaudio_ext.h>
|
||||
#include <sound/compress_driver.h>
|
||||
|
||||
/**
|
||||
* snd_hdac_ext_host_stream_setup - Setup a HOST stream.
|
||||
* @hext_stream: HDAudio stream to set up.
|
||||
* @code_loading: Whether the stream is for PCM or code-loading.
|
||||
*
|
||||
* Return: Zero on success or negative error code.
|
||||
*/
|
||||
int snd_hdac_ext_host_stream_setup(struct hdac_ext_stream *hext_stream, bool code_loading)
|
||||
{
|
||||
return hext_stream->host_setup(hdac_stream(hext_stream), code_loading);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_ext_host_stream_setup);
|
||||
|
||||
/**
|
||||
* snd_hdac_apl_host_stream_setup - Setup a HOST stream following procedure
|
||||
* recommended for ApolloLake devices.
|
||||
* @hstream: HDAudio stream to set up.
|
||||
* @code_loading: Whether the stream is for PCM or code-loading.
|
||||
*
|
||||
* Return: Zero on success or negative error code.
|
||||
*/
|
||||
static int snd_hdac_apl_host_stream_setup(struct hdac_stream *hstream, bool code_loading)
|
||||
{
|
||||
struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
|
||||
int ret;
|
||||
|
||||
snd_hdac_ext_stream_decouple(hstream->bus, hext_stream, false);
|
||||
ret = snd_hdac_stream_setup(hstream, code_loading);
|
||||
snd_hdac_ext_stream_decouple(hstream->bus, hext_stream, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_hdac_ext_stream_init - initialize each stream (aka device)
|
||||
* @bus: HD-audio core bus
|
||||
@ -55,9 +90,16 @@ static void snd_hdac_ext_stream_init(struct hdac_bus *bus,
|
||||
int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
|
||||
int num_stream, int dir)
|
||||
{
|
||||
struct pci_dev *pci = to_pci_dev(bus->dev);
|
||||
int (*setup_op)(struct hdac_stream *, bool);
|
||||
int stream_tag = 0;
|
||||
int i, tag, idx = start_idx;
|
||||
|
||||
if (pci->device == PCI_DEVICE_ID_INTEL_HDA_APL)
|
||||
setup_op = snd_hdac_apl_host_stream_setup;
|
||||
else
|
||||
setup_op = snd_hdac_stream_setup;
|
||||
|
||||
for (i = 0; i < num_stream; i++) {
|
||||
struct hdac_ext_stream *hext_stream =
|
||||
kzalloc(sizeof(*hext_stream), GFP_KERNEL);
|
||||
@ -66,6 +108,7 @@ int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
|
||||
tag = ++stream_tag;
|
||||
snd_hdac_ext_stream_init(bus, hext_stream, idx, dir, tag);
|
||||
idx++;
|
||||
hext_stream->host_setup = setup_op;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -10,6 +10,12 @@
|
||||
#include <sound/hdaudio.h>
|
||||
#include <sound/hda_i915.h>
|
||||
#include <sound/hda_register.h>
|
||||
#include <video/nomodeset.h>
|
||||
|
||||
static int gpu_bind = -1;
|
||||
module_param(gpu_bind, int, 0644);
|
||||
MODULE_PARM_DESC(gpu_bind, "Whether to bind sound component to GPU "
|
||||
"(1=always, 0=never, -1=on nomodeset(default))");
|
||||
|
||||
/**
|
||||
* snd_hdac_i915_set_bclk - Reprogram BCLK for HSW/BDW
|
||||
@ -109,7 +115,8 @@ static int i915_component_master_match(struct device *dev, int subcomponent,
|
||||
hdac_pci = to_pci_dev(bus->dev);
|
||||
i915_pci = to_pci_dev(dev);
|
||||
|
||||
if (!strcmp(dev->driver->name, "i915") &&
|
||||
if ((!strcmp(dev->driver->name, "i915") ||
|
||||
!strcmp(dev->driver->name, "xe")) &&
|
||||
subcomponent == I915_COMPONENT_AUDIO &&
|
||||
connectivity_check(i915_pci, hdac_pci))
|
||||
return 1;
|
||||
@ -122,6 +129,9 @@ static int i915_gfx_present(struct pci_dev *hdac_pci)
|
||||
{
|
||||
struct pci_dev *display_dev = NULL;
|
||||
|
||||
if (!gpu_bind || (gpu_bind < 0 && video_firmware_drivers_only()))
|
||||
return false;
|
||||
|
||||
for_each_pci_dev(display_dev) {
|
||||
if (display_dev->vendor == PCI_VENDOR_ID_INTEL &&
|
||||
(display_dev->class >> 16) == PCI_BASE_CLASS_DISPLAY &&
|
||||
@ -163,17 +173,9 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
|
||||
if (!acomp)
|
||||
return -ENODEV;
|
||||
if (!acomp->ops) {
|
||||
if (!IS_ENABLED(CONFIG_MODULES) ||
|
||||
!request_module("i915")) {
|
||||
/* 60s timeout */
|
||||
wait_for_completion_killable_timeout(&acomp->master_bind_complete,
|
||||
msecs_to_jiffies(60 * 1000));
|
||||
}
|
||||
}
|
||||
if (!acomp->ops) {
|
||||
dev_info(bus->dev, "couldn't bind with audio component\n");
|
||||
snd_hdac_acomp_exit(bus);
|
||||
return -ENODEV;
|
||||
return dev_err_probe(bus->dev, -EPROBE_DEFER,
|
||||
"couldn't bind with audio component\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -252,12 +252,15 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_reset);
|
||||
/**
|
||||
* snd_hdac_stream_setup - set up the SD for streaming
|
||||
* @azx_dev: HD-audio core stream to set up
|
||||
* @code_loading: Whether the stream is for PCM or code-loading.
|
||||
*/
|
||||
int snd_hdac_stream_setup(struct hdac_stream *azx_dev)
|
||||
int snd_hdac_stream_setup(struct hdac_stream *azx_dev, bool code_loading)
|
||||
{
|
||||
struct hdac_bus *bus = azx_dev->bus;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
unsigned int val;
|
||||
u16 reg;
|
||||
int ret;
|
||||
|
||||
if (azx_dev->substream)
|
||||
runtime = azx_dev->substream->runtime;
|
||||
@ -300,7 +303,15 @@ int snd_hdac_stream_setup(struct hdac_stream *azx_dev)
|
||||
/* set the interrupt enable bits in the descriptor control register */
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK);
|
||||
|
||||
azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1;
|
||||
if (!code_loading) {
|
||||
/* Once SDxFMT is set, the controller programs SDxFIFOS to non-zero value. */
|
||||
ret = snd_hdac_stream_readw_poll(azx_dev, SD_FIFOSIZE, reg,
|
||||
reg & AZX_SD_FIFOSIZE_MASK, 3, 300);
|
||||
if (ret)
|
||||
dev_dbg(bus->dev, "polling SD_FIFOSIZE 0x%04x failed: %d\n",
|
||||
AZX_REG_SD_FIFOSIZE, ret);
|
||||
azx_dev->fifo_size = reg;
|
||||
}
|
||||
|
||||
/* when LPIB delay correction gives a small negative value,
|
||||
* we ignore it; currently set the threshold statically to
|
||||
@ -354,8 +365,10 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
|
||||
struct hdac_stream *res = NULL;
|
||||
|
||||
/* make a non-zero unique key for the substream */
|
||||
int key = (substream->pcm->device << 16) | (substream->number << 2) |
|
||||
(substream->stream + 1);
|
||||
int key = (substream->number << 2) | (substream->stream + 1);
|
||||
|
||||
if (substream->pcm)
|
||||
key |= (substream->pcm->device << 16);
|
||||
|
||||
spin_lock_irq(&bus->reg_lock);
|
||||
list_for_each_entry(azx_dev, &bus->stream_list, list) {
|
||||
@ -943,7 +956,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
snd_hdac_stream_setup(azx_dev);
|
||||
snd_hdac_stream_setup(azx_dev, true);
|
||||
snd_hdac_dsp_unlock(azx_dev);
|
||||
return azx_dev->stream_tag;
|
||||
|
||||
|
@ -336,6 +336,12 @@ static const struct config_entry config_table[] = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "Google firmware",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "Google"),
|
||||
}
|
||||
},
|
||||
{}
|
||||
}
|
||||
},
|
||||
|
@ -1383,7 +1383,7 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,
|
||||
u32 dma_start_1;
|
||||
u32 dma_start_2;
|
||||
u32 dma_lengths;
|
||||
} __attribute__((packed)) setup_io;
|
||||
} __packed setup_io;
|
||||
|
||||
area_length = buffer_bytes/2;
|
||||
|
||||
|
@ -91,6 +91,22 @@ config SND_HDA_PATCH_LOADER
|
||||
start up. The "patch" file can be specified via patch module
|
||||
option, such as patch=hda-init.
|
||||
|
||||
config SND_HDA_CIRRUS_SCODEC
|
||||
tristate
|
||||
|
||||
config SND_HDA_CIRRUS_SCODEC_KUNIT_TEST
|
||||
tristate "KUnit test for Cirrus side-codec library" if !KUNIT_ALL_TESTS
|
||||
select SND_HDA_CIRRUS_SCODEC
|
||||
select GPIOLIB
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
This builds KUnit tests for the cirrus side-codec library.
|
||||
For more information on KUnit and unit tests in general,
|
||||
please refer to the KUnit documentation in
|
||||
Documentation/dev-tools/kunit/.
|
||||
If in doubt, say "N".
|
||||
|
||||
config SND_HDA_SCODEC_CS35L41
|
||||
tristate
|
||||
select SND_HDA_GENERIC
|
||||
@ -144,6 +160,7 @@ config SND_HDA_SCODEC_CS35L56_I2C
|
||||
select SND_HDA_GENERIC
|
||||
select SND_SOC_CS35L56_SHARED
|
||||
select SND_HDA_SCODEC_CS35L56
|
||||
select SND_HDA_CIRRUS_SCODEC
|
||||
select SND_HDA_CS_DSP_CONTROLS
|
||||
help
|
||||
Say Y or M here to include CS35L56 amplifier support with
|
||||
@ -158,6 +175,7 @@ config SND_HDA_SCODEC_CS35L56_SPI
|
||||
select SND_HDA_GENERIC
|
||||
select SND_SOC_CS35L56_SHARED
|
||||
select SND_HDA_SCODEC_CS35L56
|
||||
select SND_HDA_CIRRUS_SCODEC
|
||||
select SND_HDA_CS_DSP_CONTROLS
|
||||
help
|
||||
Say Y or M here to include CS35L56 amplifier support with
|
||||
|
@ -28,6 +28,8 @@ snd-hda-codec-via-objs := patch_via.o
|
||||
snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
|
||||
|
||||
# side codecs
|
||||
snd-hda-cirrus-scodec-objs := cirrus_scodec.o
|
||||
snd-hda-cirrus-scodec-test-objs := cirrus_scodec_test.o
|
||||
snd-hda-scodec-cs35l41-objs := cs35l41_hda.o cs35l41_hda_property.o
|
||||
snd-hda-scodec-cs35l41-i2c-objs := cs35l41_hda_i2c.o
|
||||
snd-hda-scodec-cs35l41-spi-objs := cs35l41_hda_spi.o
|
||||
@ -56,6 +58,8 @@ obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o
|
||||
obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
|
||||
|
||||
# side codecs
|
||||
obj-$(CONFIG_SND_HDA_CIRRUS_SCODEC) += snd-hda-cirrus-scodec.o
|
||||
obj-$(CONFIG_SND_HDA_CIRRUS_SCODEC_KUNIT_TEST) += snd-hda-cirrus-scodec-test.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) += snd-hda-scodec-cs35l41.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o
|
||||
|
73
sound/pci/hda/cirrus_scodec.c
Normal file
73
sound/pci/hda/cirrus_scodec.c
Normal file
@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// Common code for Cirrus side-codecs.
|
||||
//
|
||||
// Copyright (C) 2021, 2023 Cirrus Logic, Inc. and
|
||||
// Cirrus Logic International Semiconductor Ltd.
|
||||
|
||||
#include <linux/dev_printk.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "cirrus_scodec.h"
|
||||
|
||||
int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
|
||||
int num_amps, int fixed_gpio_id)
|
||||
{
|
||||
struct gpio_desc *speaker_id_desc;
|
||||
int speaker_id = -ENOENT;
|
||||
|
||||
if (fixed_gpio_id >= 0) {
|
||||
dev_dbg(dev, "Found Fixed Speaker ID GPIO (index = %d)\n", fixed_gpio_id);
|
||||
speaker_id_desc = gpiod_get_index(dev, NULL, fixed_gpio_id, GPIOD_IN);
|
||||
if (IS_ERR(speaker_id_desc)) {
|
||||
speaker_id = PTR_ERR(speaker_id_desc);
|
||||
return speaker_id;
|
||||
}
|
||||
speaker_id = gpiod_get_value_cansleep(speaker_id_desc);
|
||||
gpiod_put(speaker_id_desc);
|
||||
} else {
|
||||
int base_index;
|
||||
int gpios_per_amp;
|
||||
int count;
|
||||
int tmp;
|
||||
int i;
|
||||
|
||||
count = gpiod_count(dev, "spk-id");
|
||||
if (count > 0) {
|
||||
speaker_id = 0;
|
||||
gpios_per_amp = count / num_amps;
|
||||
base_index = gpios_per_amp * amp_index;
|
||||
|
||||
if (count % num_amps)
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(dev, "Found %d Speaker ID GPIOs per Amp\n", gpios_per_amp);
|
||||
|
||||
for (i = 0; i < gpios_per_amp; i++) {
|
||||
speaker_id_desc = gpiod_get_index(dev, "spk-id", i + base_index,
|
||||
GPIOD_IN);
|
||||
if (IS_ERR(speaker_id_desc)) {
|
||||
speaker_id = PTR_ERR(speaker_id_desc);
|
||||
break;
|
||||
}
|
||||
tmp = gpiod_get_value_cansleep(speaker_id_desc);
|
||||
gpiod_put(speaker_id_desc);
|
||||
if (tmp < 0) {
|
||||
speaker_id = tmp;
|
||||
break;
|
||||
}
|
||||
speaker_id |= tmp << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(dev, "Speaker ID = %d\n", speaker_id);
|
||||
|
||||
return speaker_id;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cirrus_scodec_get_speaker_id, SND_HDA_CIRRUS_SCODEC);
|
||||
|
||||
MODULE_DESCRIPTION("HDA Cirrus side-codec library");
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
13
sound/pci/hda/cirrus_scodec.h
Normal file
13
sound/pci/hda/cirrus_scodec.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2023 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*/
|
||||
|
||||
#ifndef CIRRUS_SCODEC_H
|
||||
#define CIRRUS_SCODEC_H
|
||||
|
||||
int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
|
||||
int num_amps, int fixed_gpio_id);
|
||||
|
||||
#endif /* CIRRUS_SCODEC_H */
|
370
sound/pci/hda/cirrus_scodec_test.c
Normal file
370
sound/pci/hda/cirrus_scodec_test.c
Normal file
@ -0,0 +1,370 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// KUnit test for the Cirrus side-codec library.
|
||||
//
|
||||
// Copyright (C) 2023 Cirrus Logic, Inc. and
|
||||
// Cirrus Logic International Semiconductor Ltd.
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "cirrus_scodec.h"
|
||||
|
||||
struct cirrus_scodec_test_gpio {
|
||||
unsigned int pin_state;
|
||||
struct gpio_chip chip;
|
||||
};
|
||||
|
||||
struct cirrus_scodec_test_priv {
|
||||
struct platform_device amp_pdev;
|
||||
struct platform_device *gpio_pdev;
|
||||
struct cirrus_scodec_test_gpio *gpio_priv;
|
||||
};
|
||||
|
||||
static int cirrus_scodec_test_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int cirrus_scodec_test_gpio_direction_in(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cirrus_scodec_test_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct cirrus_scodec_test_gpio *gpio_priv = gpiochip_get_data(chip);
|
||||
|
||||
return !!(gpio_priv->pin_state & BIT(offset));
|
||||
}
|
||||
|
||||
static int cirrus_scodec_test_gpio_direction_out(struct gpio_chip *chip,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void cirrus_scodec_test_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
}
|
||||
|
||||
static int cirrus_scodec_test_gpio_set_config(struct gpio_chip *gc,
|
||||
unsigned int offset,
|
||||
unsigned long config)
|
||||
{
|
||||
switch (pinconf_to_config_param(config)) {
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
return -EOPNOTSUPP;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct gpio_chip cirrus_scodec_test_gpio_chip = {
|
||||
.label = "cirrus_scodec_test_gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.request = gpiochip_generic_request,
|
||||
.free = gpiochip_generic_free,
|
||||
.get_direction = cirrus_scodec_test_gpio_get_direction,
|
||||
.direction_input = cirrus_scodec_test_gpio_direction_in,
|
||||
.get = cirrus_scodec_test_gpio_get,
|
||||
.direction_output = cirrus_scodec_test_gpio_direction_out,
|
||||
.set = cirrus_scodec_test_gpio_set,
|
||||
.set_config = cirrus_scodec_test_gpio_set_config,
|
||||
.base = -1,
|
||||
.ngpio = 32,
|
||||
};
|
||||
|
||||
static int cirrus_scodec_test_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cirrus_scodec_test_gpio *gpio_priv;
|
||||
int ret;
|
||||
|
||||
gpio_priv = devm_kzalloc(&pdev->dev, sizeof(*gpio_priv), GFP_KERNEL);
|
||||
if (!gpio_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
/* GPIO core modifies our struct gpio_chip so use a copy */
|
||||
gpio_priv->chip = cirrus_scodec_test_gpio_chip;
|
||||
ret = devm_gpiochip_add_data(&pdev->dev, &gpio_priv->chip, gpio_priv);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "Failed to add gpiochip\n");
|
||||
|
||||
dev_set_drvdata(&pdev->dev, gpio_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cirrus_scodec_test_gpio_driver = {
|
||||
.driver.name = "cirrus_scodec_test_gpio_drv",
|
||||
.probe = cirrus_scodec_test_gpio_probe,
|
||||
};
|
||||
|
||||
/* software_node referencing the gpio driver */
|
||||
static const struct software_node cirrus_scodec_test_gpio_swnode = {
|
||||
.name = "cirrus_scodec_test_gpio",
|
||||
};
|
||||
|
||||
static int cirrus_scodec_test_create_gpio(struct kunit *test)
|
||||
{
|
||||
struct cirrus_scodec_test_priv *priv = test->priv;
|
||||
int ret;
|
||||
|
||||
priv->gpio_pdev = platform_device_alloc(cirrus_scodec_test_gpio_driver.driver.name, -1);
|
||||
if (!priv->gpio_pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = device_add_software_node(&priv->gpio_pdev->dev, &cirrus_scodec_test_gpio_swnode);
|
||||
if (ret) {
|
||||
platform_device_put(priv->gpio_pdev);
|
||||
KUNIT_FAIL(test, "Failed to add swnode to gpio: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = platform_device_add(priv->gpio_pdev);
|
||||
if (ret) {
|
||||
platform_device_put(priv->gpio_pdev);
|
||||
KUNIT_FAIL(test, "Failed to add gpio platform device: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->gpio_priv = dev_get_drvdata(&priv->gpio_pdev->dev);
|
||||
if (!priv->gpio_priv) {
|
||||
platform_device_put(priv->gpio_pdev);
|
||||
KUNIT_FAIL(test, "Failed to get gpio private data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cirrus_scodec_test_set_gpio_ref_arg(struct software_node_ref_args *arg,
|
||||
int gpio_num)
|
||||
{
|
||||
struct software_node_ref_args template =
|
||||
SOFTWARE_NODE_REFERENCE(&cirrus_scodec_test_gpio_swnode, gpio_num, 0);
|
||||
|
||||
*arg = template;
|
||||
}
|
||||
|
||||
static int cirrus_scodec_test_set_spkid_swnode(struct kunit *test,
|
||||
struct device *dev,
|
||||
struct software_node_ref_args *args,
|
||||
int num_args)
|
||||
{
|
||||
const struct property_entry props_template[] = {
|
||||
PROPERTY_ENTRY_REF_ARRAY_LEN("spk-id-gpios", args, num_args),
|
||||
{ }
|
||||
};
|
||||
struct property_entry *props;
|
||||
struct software_node *node;
|
||||
|
||||
node = kunit_kzalloc(test, sizeof(*node), GFP_KERNEL);
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
|
||||
props = kunit_kzalloc(test, sizeof(props_template), GFP_KERNEL);
|
||||
if (!props)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(props, props_template, sizeof(props_template));
|
||||
node->properties = props;
|
||||
|
||||
return device_add_software_node(dev, node);
|
||||
}
|
||||
|
||||
struct cirrus_scodec_test_spkid_param {
|
||||
int num_amps;
|
||||
int gpios_per_amp;
|
||||
int num_amps_sharing;
|
||||
};
|
||||
|
||||
static void cirrus_scodec_test_spkid_parse(struct kunit *test)
|
||||
{
|
||||
struct cirrus_scodec_test_priv *priv = test->priv;
|
||||
const struct cirrus_scodec_test_spkid_param *param = test->param_value;
|
||||
int num_spk_id_refs = param->num_amps * param->gpios_per_amp;
|
||||
struct software_node_ref_args *refs;
|
||||
struct device *dev = &priv->amp_pdev.dev;
|
||||
unsigned int v;
|
||||
int i, ret;
|
||||
|
||||
refs = kunit_kcalloc(test, num_spk_id_refs, sizeof(*refs), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, refs);
|
||||
|
||||
for (i = 0, v = 0; i < num_spk_id_refs; ) {
|
||||
cirrus_scodec_test_set_gpio_ref_arg(&refs[i++], v++);
|
||||
|
||||
/*
|
||||
* If amps are sharing GPIOs repeat the last set of
|
||||
* GPIOs until we've done that number of amps.
|
||||
* We have done all GPIOs for an amp when i is a multiple
|
||||
* of gpios_per_amp.
|
||||
* We have done all amps sharing the same GPIOs when i is
|
||||
* a multiple of (gpios_per_amp * num_amps_sharing).
|
||||
*/
|
||||
if (!(i % param->gpios_per_amp) &&
|
||||
(i % (param->gpios_per_amp * param->num_amps_sharing)))
|
||||
v -= param->gpios_per_amp;
|
||||
}
|
||||
|
||||
ret = cirrus_scodec_test_set_spkid_swnode(test, dev, refs, num_spk_id_refs);
|
||||
KUNIT_EXPECT_EQ_MSG(test, ret, 0, "Failed to add swnode\n");
|
||||
|
||||
for (i = 0; i < param->num_amps; ++i) {
|
||||
for (v = 0; v < (1 << param->gpios_per_amp); ++v) {
|
||||
/* Set only the GPIO bits used by this amp */
|
||||
priv->gpio_priv->pin_state =
|
||||
v << (param->gpios_per_amp * (i / param->num_amps_sharing));
|
||||
|
||||
ret = cirrus_scodec_get_speaker_id(dev, i, param->num_amps, -1);
|
||||
KUNIT_EXPECT_EQ_MSG(test, ret, v,
|
||||
"get_speaker_id failed amp:%d pin_state:%#x\n",
|
||||
i, priv->gpio_priv->pin_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cirrus_scodec_test_no_spkid(struct kunit *test)
|
||||
{
|
||||
struct cirrus_scodec_test_priv *priv = test->priv;
|
||||
struct device *dev = &priv->amp_pdev.dev;
|
||||
int ret;
|
||||
|
||||
ret = cirrus_scodec_get_speaker_id(dev, 0, 4, -1);
|
||||
KUNIT_EXPECT_EQ(test, ret, -ENOENT);
|
||||
}
|
||||
|
||||
static void cirrus_scodec_test_dev_release(struct device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static int cirrus_scodec_test_case_init(struct kunit *test)
|
||||
{
|
||||
struct cirrus_scodec_test_priv *priv;
|
||||
int ret;
|
||||
|
||||
priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
test->priv = priv;
|
||||
|
||||
/* Create dummy GPIO */
|
||||
ret = cirrus_scodec_test_create_gpio(test);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Create dummy amp driver dev */
|
||||
priv->amp_pdev.name = "cirrus_scodec_test_amp_drv";
|
||||
priv->amp_pdev.id = -1;
|
||||
priv->amp_pdev.dev.release = cirrus_scodec_test_dev_release;
|
||||
ret = platform_device_register(&priv->amp_pdev);
|
||||
KUNIT_ASSERT_GE_MSG(test, ret, 0, "Failed to register amp platform device\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cirrus_scodec_test_case_exit(struct kunit *test)
|
||||
{
|
||||
struct cirrus_scodec_test_priv *priv = test->priv;
|
||||
|
||||
if (priv->amp_pdev.name)
|
||||
platform_device_unregister(&priv->amp_pdev);
|
||||
|
||||
if (priv->gpio_pdev) {
|
||||
device_remove_software_node(&priv->gpio_pdev->dev);
|
||||
platform_device_unregister(priv->gpio_pdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int cirrus_scodec_test_suite_init(struct kunit_suite *suite)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Register mock GPIO driver */
|
||||
ret = platform_driver_register(&cirrus_scodec_test_gpio_driver);
|
||||
if (ret < 0) {
|
||||
kunit_err(suite, "Failed to register gpio platform driver, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cirrus_scodec_test_suite_exit(struct kunit_suite *suite)
|
||||
{
|
||||
platform_driver_unregister(&cirrus_scodec_test_gpio_driver);
|
||||
}
|
||||
|
||||
static const struct cirrus_scodec_test_spkid_param cirrus_scodec_test_spkid_param_cases[] = {
|
||||
{ .num_amps = 2, .gpios_per_amp = 1, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 2, .gpios_per_amp = 2, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 2, .gpios_per_amp = 3, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 2, .gpios_per_amp = 4, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 3, .gpios_per_amp = 1, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 3, .gpios_per_amp = 2, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 3, .gpios_per_amp = 3, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 3, .gpios_per_amp = 4, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 1, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 2, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 3, .num_amps_sharing = 1 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 4, .num_amps_sharing = 1 },
|
||||
|
||||
/* Same GPIO shared by all amps */
|
||||
{ .num_amps = 2, .gpios_per_amp = 1, .num_amps_sharing = 2 },
|
||||
{ .num_amps = 2, .gpios_per_amp = 2, .num_amps_sharing = 2 },
|
||||
{ .num_amps = 2, .gpios_per_amp = 3, .num_amps_sharing = 2 },
|
||||
{ .num_amps = 2, .gpios_per_amp = 4, .num_amps_sharing = 2 },
|
||||
{ .num_amps = 3, .gpios_per_amp = 1, .num_amps_sharing = 3 },
|
||||
{ .num_amps = 3, .gpios_per_amp = 2, .num_amps_sharing = 3 },
|
||||
{ .num_amps = 3, .gpios_per_amp = 3, .num_amps_sharing = 3 },
|
||||
{ .num_amps = 3, .gpios_per_amp = 4, .num_amps_sharing = 3 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 1, .num_amps_sharing = 4 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 2, .num_amps_sharing = 4 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 3, .num_amps_sharing = 4 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 4, .num_amps_sharing = 4 },
|
||||
|
||||
/* Two sets of shared GPIOs */
|
||||
{ .num_amps = 4, .gpios_per_amp = 1, .num_amps_sharing = 2 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 2, .num_amps_sharing = 2 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 3, .num_amps_sharing = 2 },
|
||||
{ .num_amps = 4, .gpios_per_amp = 4, .num_amps_sharing = 2 },
|
||||
};
|
||||
|
||||
static void cirrus_scodec_test_spkid_param_desc(const struct cirrus_scodec_test_spkid_param *param,
|
||||
char *desc)
|
||||
{
|
||||
snprintf(desc, KUNIT_PARAM_DESC_SIZE, "amps:%d gpios_per_amp:%d num_amps_sharing:%d",
|
||||
param->num_amps, param->gpios_per_amp, param->num_amps_sharing);
|
||||
}
|
||||
|
||||
KUNIT_ARRAY_PARAM(cirrus_scodec_test_spkid, cirrus_scodec_test_spkid_param_cases,
|
||||
cirrus_scodec_test_spkid_param_desc);
|
||||
|
||||
static struct kunit_case cirrus_scodec_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(cirrus_scodec_test_spkid_parse, cirrus_scodec_test_spkid_gen_params),
|
||||
KUNIT_CASE(cirrus_scodec_test_no_spkid),
|
||||
{ } /* terminator */
|
||||
};
|
||||
|
||||
static struct kunit_suite cirrus_scodec_test_suite = {
|
||||
.name = "snd-hda-scodec-cs35l56-test",
|
||||
.suite_init = cirrus_scodec_test_suite_init,
|
||||
.suite_exit = cirrus_scodec_test_suite_exit,
|
||||
.init = cirrus_scodec_test_case_init,
|
||||
.exit = cirrus_scodec_test_case_exit,
|
||||
.test_cases = cirrus_scodec_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(cirrus_scodec_test_suite);
|
||||
|
||||
MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -33,6 +33,9 @@
|
||||
#define CAL_AMBIENT_DSP_CTL_NAME "CAL_AMBIENT"
|
||||
#define CAL_DSP_CTL_TYPE 5
|
||||
#define CAL_DSP_CTL_ALG 205
|
||||
#define CS35L41_UUID "50d90cdc-3de4-4f18-b528-c7fe3b71f40d"
|
||||
#define CS35L41_DSM_GET_MUTE 5
|
||||
#define CS35L41_NOTIFY_EVENT 0x91
|
||||
|
||||
static bool firmware_autostart = 1;
|
||||
module_param(firmware_autostart, bool, 0444);
|
||||
@ -563,6 +566,31 @@ static void cs35l41_hda_play_start(struct device *dev)
|
||||
|
||||
}
|
||||
|
||||
static void cs35l41_mute(struct device *dev, bool mute)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
|
||||
struct regmap *reg = cs35l41->regmap;
|
||||
|
||||
dev_dbg(dev, "Mute(%d:%d) Playback Started: %d\n", mute, cs35l41->mute_override,
|
||||
cs35l41->playback_started);
|
||||
|
||||
if (cs35l41->playback_started) {
|
||||
if (mute || cs35l41->mute_override) {
|
||||
dev_dbg(dev, "Muting\n");
|
||||
regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));
|
||||
} else {
|
||||
dev_dbg(dev, "Unmuting\n");
|
||||
if (cs35l41->firmware_running) {
|
||||
regmap_multi_reg_write(reg, cs35l41_hda_unmute_dsp,
|
||||
ARRAY_SIZE(cs35l41_hda_unmute_dsp));
|
||||
} else {
|
||||
regmap_multi_reg_write(reg, cs35l41_hda_unmute,
|
||||
ARRAY_SIZE(cs35l41_hda_unmute));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cs35l41_hda_play_done(struct device *dev)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
|
||||
@ -570,15 +598,9 @@ static void cs35l41_hda_play_done(struct device *dev)
|
||||
|
||||
dev_dbg(dev, "Play (Complete)\n");
|
||||
|
||||
cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 1, NULL,
|
||||
cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 1,
|
||||
cs35l41->firmware_running);
|
||||
if (cs35l41->firmware_running) {
|
||||
regmap_multi_reg_write(reg, cs35l41_hda_unmute_dsp,
|
||||
ARRAY_SIZE(cs35l41_hda_unmute_dsp));
|
||||
} else {
|
||||
regmap_multi_reg_write(reg, cs35l41_hda_unmute,
|
||||
ARRAY_SIZE(cs35l41_hda_unmute));
|
||||
}
|
||||
cs35l41_mute(dev, false);
|
||||
}
|
||||
|
||||
static void cs35l41_hda_pause_start(struct device *dev)
|
||||
@ -588,8 +610,8 @@ static void cs35l41_hda_pause_start(struct device *dev)
|
||||
|
||||
dev_dbg(dev, "Pause (Start)\n");
|
||||
|
||||
regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));
|
||||
cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0, NULL,
|
||||
cs35l41_mute(dev, true);
|
||||
cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0,
|
||||
cs35l41->firmware_running);
|
||||
}
|
||||
|
||||
@ -708,43 +730,46 @@ static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsi
|
||||
rx_slot);
|
||||
}
|
||||
|
||||
static int cs35l41_verify_id(struct cs35l41_hda *cs35l41, unsigned int *regid, unsigned int *reg_revid)
|
||||
{
|
||||
unsigned int mtl_revid, chipid;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, regid);
|
||||
if (ret) {
|
||||
dev_err_probe(cs35l41->dev, ret, "Get Device ID failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_read(cs35l41->regmap, CS35L41_REVID, reg_revid);
|
||||
if (ret) {
|
||||
dev_err_probe(cs35l41->dev, ret, "Get Revision ID failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mtl_revid = *reg_revid & CS35L41_MTLREVID_MASK;
|
||||
|
||||
chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
|
||||
if (*regid != chipid) {
|
||||
dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", *regid, chipid);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&cs35l41->fw_mutex);
|
||||
if (cs35l41->firmware_running) {
|
||||
|
||||
regcache_cache_only(cs35l41->regmap, false);
|
||||
|
||||
ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap);
|
||||
if (ret) {
|
||||
dev_warn(cs35l41->dev, "Unable to exit Hibernate.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Test key needs to be unlocked to allow the OTP settings to re-apply */
|
||||
cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
|
||||
ret = regcache_sync(cs35l41->regmap);
|
||||
cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);
|
||||
if (ret) {
|
||||
dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
|
||||
cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
|
||||
|
||||
cs35l41_shutdown_dsp(cs35l41);
|
||||
cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
|
||||
cs35l41->cs_dsp.running = false;
|
||||
cs35l41->cs_dsp.booted = false;
|
||||
cs35l41->firmware_running = false;
|
||||
}
|
||||
err:
|
||||
regcache_cache_only(cs35l41->regmap, true);
|
||||
regcache_mark_dirty(cs35l41->regmap);
|
||||
|
||||
mutex_unlock(&cs35l41->fw_mutex);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs35l41_system_suspend_prep(struct device *dev)
|
||||
@ -791,17 +816,44 @@ static int cs35l41_system_suspend(struct device *dev)
|
||||
|
||||
/* Shutdown DSP before system suspend */
|
||||
ret = cs35l41_ready_for_reset(cs35l41);
|
||||
|
||||
if (ret)
|
||||
dev_err(dev, "System Suspend Failed, not ready for Reset: %d\n", ret);
|
||||
|
||||
/*
|
||||
* Reset GPIO may be shared, so cannot reset here.
|
||||
* However beyond this point, amps may be powered down.
|
||||
*/
|
||||
if (cs35l41->reset_gpio) {
|
||||
dev_info(cs35l41->dev, "Asserting Reset\n");
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
|
||||
usleep_range(2000, 2100);
|
||||
}
|
||||
|
||||
dev_dbg(cs35l41->dev, "System Suspended\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs35l41_wait_boot_done(struct cs35l41_hda *cs35l41)
|
||||
{
|
||||
unsigned int int_status;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,
|
||||
int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);
|
||||
if (ret) {
|
||||
dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_status);
|
||||
if (ret || (int_status & CS35L41_OTP_BOOT_ERR)) {
|
||||
dev_err(cs35l41->dev, "OTP Boot status %x error\n",
|
||||
int_status & CS35L41_OTP_BOOT_ERR);
|
||||
if (!ret)
|
||||
ret = -EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs35l41_system_resume(struct device *dev)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
|
||||
@ -815,12 +867,24 @@ static int cs35l41_system_resume(struct device *dev)
|
||||
}
|
||||
|
||||
if (cs35l41->reset_gpio) {
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
|
||||
usleep_range(2000, 2100);
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
|
||||
}
|
||||
|
||||
usleep_range(2000, 2100);
|
||||
|
||||
regcache_cache_only(cs35l41->regmap, false);
|
||||
|
||||
regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);
|
||||
usleep_range(2000, 2100);
|
||||
|
||||
ret = cs35l41_wait_boot_done(cs35l41);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regcache_cache_only(cs35l41->regmap, true);
|
||||
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "System Resume Failed: Unable to runtime resume: %d\n", ret);
|
||||
@ -882,6 +946,7 @@ err:
|
||||
static int cs35l41_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
|
||||
unsigned int regid, reg_revid;
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(cs35l41->dev, "Runtime Resume\n");
|
||||
@ -903,6 +968,10 @@ static int cs35l41_runtime_resume(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
ret = cs35l41_verify_id(cs35l41, ®id, ®_revid);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* Test key needs to be unlocked to allow the OTP settings to re-apply */
|
||||
cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
|
||||
ret = regcache_sync(cs35l41->regmap);
|
||||
@ -915,6 +984,8 @@ static int cs35l41_runtime_resume(struct device *dev)
|
||||
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
|
||||
cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
|
||||
|
||||
dev_dbg(cs35l41->dev, "CS35L41 Resumed (%x), Revision: %02X\n", regid, reg_revid);
|
||||
|
||||
err:
|
||||
mutex_unlock(&cs35l41->fw_mutex);
|
||||
|
||||
@ -923,6 +994,7 @@ err:
|
||||
|
||||
static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
|
||||
{
|
||||
unsigned int fw_status;
|
||||
__be32 halo_sts;
|
||||
int ret;
|
||||
|
||||
@ -956,6 +1028,24 @@ static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
|
||||
goto clean_dsp;
|
||||
}
|
||||
|
||||
ret = regmap_read(cs35l41->regmap, CS35L41_DSP_MBOX_2, &fw_status);
|
||||
if (ret < 0) {
|
||||
dev_err(cs35l41->dev,
|
||||
"Failed to read firmware status: %d\n", ret);
|
||||
goto clean_dsp;
|
||||
}
|
||||
|
||||
switch (fw_status) {
|
||||
case CSPL_MBOX_STS_RUNNING:
|
||||
case CSPL_MBOX_STS_PAUSED:
|
||||
break;
|
||||
default:
|
||||
dev_err(cs35l41->dev, "Firmware status is invalid: %u\n",
|
||||
fw_status);
|
||||
ret = -EINVAL;
|
||||
goto clean_dsp;
|
||||
}
|
||||
|
||||
ret = cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, CSPL_MBOX_CMD_PAUSE);
|
||||
if (ret) {
|
||||
dev_err(cs35l41->dev, "Error waiting for DSP to pause: %u\n", ret);
|
||||
@ -993,6 +1083,15 @@ static int cs35l41_fw_load_ctl_get(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs35l41_mute_override_ctl_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
ucontrol->value.integer.value[0] = cs35l41->mute_override;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cs35l41_fw_load_work(struct work_struct *work)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = container_of(work, struct cs35l41_hda, fw_load_work);
|
||||
@ -1076,6 +1175,7 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
|
||||
{
|
||||
char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
char fw_load_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
char mute_override_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
struct snd_kcontrol_new fw_type_ctl = {
|
||||
.name = fw_type_ctl_name,
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
|
||||
@ -1090,12 +1190,21 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
|
||||
.get = cs35l41_fw_load_ctl_get,
|
||||
.put = cs35l41_fw_load_ctl_put,
|
||||
};
|
||||
struct snd_kcontrol_new mute_override_ctl = {
|
||||
.name = mute_override_ctl_name,
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
|
||||
.info = snd_ctl_boolean_mono_info,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
|
||||
.get = cs35l41_mute_override_ctl_get,
|
||||
};
|
||||
int ret;
|
||||
|
||||
scnprintf(fw_type_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Type",
|
||||
cs35l41->amp_name);
|
||||
scnprintf(fw_load_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Load",
|
||||
cs35l41->amp_name);
|
||||
scnprintf(mute_override_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s Forced Mute Status",
|
||||
cs35l41->amp_name);
|
||||
|
||||
ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41));
|
||||
if (ret) {
|
||||
@ -1113,9 +1222,65 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
|
||||
|
||||
dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name);
|
||||
|
||||
ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&mute_override_ctl, cs35l41));
|
||||
if (ret) {
|
||||
dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", mute_override_ctl.name,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(cs35l41->dev, "Added Control %s\n", mute_override_ctl.name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool cs35l41_dsm_supported(acpi_handle handle, unsigned int commands)
|
||||
{
|
||||
guid_t guid;
|
||||
|
||||
guid_parse(CS35L41_UUID, &guid);
|
||||
|
||||
return acpi_check_dsm(handle, &guid, 0, BIT(commands));
|
||||
}
|
||||
|
||||
static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle handle)
|
||||
{
|
||||
guid_t guid;
|
||||
union acpi_object *ret;
|
||||
int mute = -ENODEV;
|
||||
|
||||
guid_parse(CS35L41_UUID, &guid);
|
||||
|
||||
if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) {
|
||||
ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL);
|
||||
mute = *ret->buffer.pointer;
|
||||
dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute);
|
||||
}
|
||||
|
||||
dev_dbg(cs35l41->dev, "%s: %d\n", __func__, mute);
|
||||
|
||||
return mute;
|
||||
}
|
||||
|
||||
static void cs35l41_acpi_device_notify(acpi_handle handle, u32 event, struct device *dev)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
|
||||
int mute;
|
||||
|
||||
if (event != CS35L41_NOTIFY_EVENT)
|
||||
return;
|
||||
|
||||
mute = cs35l41_get_acpi_mute_state(cs35l41, handle);
|
||||
if (mute < 0) {
|
||||
dev_warn(cs35l41->dev, "Unable to retrieve mute state: %d\n", mute);
|
||||
return;
|
||||
}
|
||||
|
||||
dev_dbg(cs35l41->dev, "Requesting mute value: %d\n", mute);
|
||||
cs35l41->mute_override = (mute > 0);
|
||||
cs35l41_mute(cs35l41->dev, cs35l41->mute_override);
|
||||
}
|
||||
|
||||
static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
|
||||
@ -1157,6 +1322,14 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
|
||||
comps->playback_hook = cs35l41_hda_playback_hook;
|
||||
comps->pre_playback_hook = cs35l41_hda_pre_playback_hook;
|
||||
comps->post_playback_hook = cs35l41_hda_post_playback_hook;
|
||||
comps->acpi_notify = cs35l41_acpi_device_notify;
|
||||
comps->adev = cs35l41->dacpi;
|
||||
|
||||
comps->acpi_notifications_supported = cs35l41_dsm_supported(acpi_device_handle(comps->adev),
|
||||
CS35L41_DSM_GET_MUTE);
|
||||
|
||||
cs35l41->mute_override = cs35l41_get_acpi_mute_state(cs35l41,
|
||||
acpi_device_handle(cs35l41->dacpi)) > 0;
|
||||
|
||||
mutex_unlock(&cs35l41->fw_mutex);
|
||||
|
||||
@ -1430,8 +1603,8 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
cs35l41->dacpi = adev;
|
||||
physdev = get_device(acpi_get_first_physical_node(adev));
|
||||
acpi_dev_put(adev);
|
||||
|
||||
sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
|
||||
if (IS_ERR(sub))
|
||||
@ -1541,6 +1714,7 @@ err:
|
||||
hw_cfg->valid = false;
|
||||
hw_cfg->gpio1.valid = false;
|
||||
hw_cfg->gpio2.valid = false;
|
||||
acpi_dev_put(cs35l41->dacpi);
|
||||
put_physdev:
|
||||
put_device(physdev);
|
||||
|
||||
@ -1550,7 +1724,7 @@ put_physdev:
|
||||
int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
|
||||
struct regmap *regmap)
|
||||
{
|
||||
unsigned int int_sts, regid, reg_revid, mtl_revid, chipid, int_status;
|
||||
unsigned int regid, reg_revid;
|
||||
struct cs35l41_hda *cs35l41;
|
||||
int ret;
|
||||
|
||||
@ -1584,47 +1758,22 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
|
||||
}
|
||||
}
|
||||
if (cs35l41->reset_gpio) {
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
|
||||
usleep_range(2000, 2100);
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
|
||||
}
|
||||
|
||||
usleep_range(2000, 2100);
|
||||
regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);
|
||||
usleep_range(2000, 2100);
|
||||
|
||||
ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,
|
||||
int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);
|
||||
if (ret) {
|
||||
dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE: %d\n", ret);
|
||||
ret = cs35l41_wait_boot_done(cs35l41);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
|
||||
if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
|
||||
dev_err(cs35l41->dev, "OTP Boot status %x error: %d\n",
|
||||
int_sts & CS35L41_OTP_BOOT_ERR, ret);
|
||||
ret = -EIO;
|
||||
ret = cs35l41_verify_id(cs35l41, ®id, ®_revid);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, ®id);
|
||||
if (ret) {
|
||||
dev_err(cs35l41->dev, "Get Device ID failed: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = regmap_read(cs35l41->regmap, CS35L41_REVID, ®_revid);
|
||||
if (ret) {
|
||||
dev_err(cs35l41->dev, "Get Revision ID failed: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
mtl_revid = reg_revid & CS35L41_MTLREVID_MASK;
|
||||
|
||||
chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
|
||||
if (regid != chipid) {
|
||||
dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", regid, chipid);
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
|
||||
if (ret)
|
||||
@ -1636,7 +1785,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
|
||||
|
||||
ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
|
||||
if (ret) {
|
||||
dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
|
||||
dev_err_probe(cs35l41->dev, ret, "OTP Unpack failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -1644,10 +1793,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute,
|
||||
ARRAY_SIZE(cs35l41_hda_mute));
|
||||
if (ret)
|
||||
goto err;
|
||||
cs35l41_mute(cs35l41->dev, true);
|
||||
|
||||
INIT_WORK(&cs35l41->fw_load_work, cs35l41_fw_load_work);
|
||||
mutex_init(&cs35l41->fw_mutex);
|
||||
@ -1667,9 +1813,8 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
|
||||
|
||||
ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);
|
||||
if (ret) {
|
||||
dev_err(cs35l41->dev, "Register component failed: %d\n", ret);
|
||||
pm_runtime_disable(cs35l41->dev);
|
||||
goto err;
|
||||
dev_err_probe(cs35l41->dev, ret, "Register component failed\n");
|
||||
goto err_pm;
|
||||
}
|
||||
|
||||
dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid);
|
||||
@ -1677,6 +1822,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
|
||||
return 0;
|
||||
|
||||
err_pm:
|
||||
pm_runtime_dont_use_autosuspend(cs35l41->dev);
|
||||
pm_runtime_disable(cs35l41->dev);
|
||||
pm_runtime_put_noidle(cs35l41->dev);
|
||||
|
||||
@ -1684,6 +1830,7 @@ err:
|
||||
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
|
||||
gpiod_put(cs35l41->reset_gpio);
|
||||
acpi_dev_put(cs35l41->dacpi);
|
||||
kfree(cs35l41->acpi_subsystem_id);
|
||||
|
||||
return ret;
|
||||
@ -1695,6 +1842,7 @@ void cs35l41_hda_remove(struct device *dev)
|
||||
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
|
||||
|
||||
pm_runtime_get_sync(cs35l41->dev);
|
||||
pm_runtime_dont_use_autosuspend(cs35l41->dev);
|
||||
pm_runtime_disable(cs35l41->dev);
|
||||
|
||||
if (cs35l41->halo_initialized)
|
||||
@ -1702,6 +1850,8 @@ void cs35l41_hda_remove(struct device *dev)
|
||||
|
||||
component_del(cs35l41->dev, &cs35l41_hda_comp_ops);
|
||||
|
||||
acpi_dev_put(cs35l41->dacpi);
|
||||
|
||||
pm_runtime_put_noidle(cs35l41->dev);
|
||||
|
||||
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef __CS35L41_HDA_H__
|
||||
#define __CS35L41_HDA_H__
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
@ -70,6 +71,8 @@ struct cs35l41_hda {
|
||||
bool halo_initialized;
|
||||
bool playback_started;
|
||||
struct cs_dsp cs_dsp;
|
||||
struct acpi_device *dacpi;
|
||||
bool mute_override;
|
||||
};
|
||||
|
||||
enum halo_state {
|
||||
|
@ -58,9 +58,16 @@ static int hp_vision_acpi_fix(struct cs35l41_hda *cs35l41, struct device *physde
|
||||
|
||||
cs35l41->index = id;
|
||||
cs35l41->channel_index = 0;
|
||||
cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 1, GPIOD_OUT_HIGH);
|
||||
|
||||
/*
|
||||
* This system has _DSD, it just contains an error, so we can still get the reset using
|
||||
* the "reset" label.
|
||||
*/
|
||||
cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset",
|
||||
cs35l41->index, GPIOD_OUT_LOW,
|
||||
"cs35l41-reset");
|
||||
cs35l41->speaker_id = -ENOENT;
|
||||
hw_cfg->spk_pos = cs35l41->index ? 1 : 0; // right:left
|
||||
hw_cfg->spk_pos = cs35l41->index ? 0 : 1; // right:left
|
||||
hw_cfg->gpio1.func = CS35L41_NOT_USED;
|
||||
hw_cfg->gpio1.valid = true;
|
||||
hw_cfg->gpio2.func = CS35L41_INTERRUPT;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <sound/core.h>
|
||||
#include <sound/hda_codec.h>
|
||||
#include <sound/tlv.h>
|
||||
#include "cirrus_scodec.h"
|
||||
#include "cs35l56_hda.h"
|
||||
#include "hda_component.h"
|
||||
#include "hda_cs_dsp_ctl.h"
|
||||
@ -869,7 +870,17 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int id)
|
||||
"Read ACPI _SUB failed(%ld): fallback to generic firmware\n",
|
||||
PTR_ERR(sub));
|
||||
} else {
|
||||
cs35l56->system_name = sub;
|
||||
ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index, nval, -1);
|
||||
if (ret == -ENOENT) {
|
||||
cs35l56->system_name = sub;
|
||||
} else if (ret >= 0) {
|
||||
cs35l56->system_name = kasprintf(GFP_KERNEL, "%s-spkid%d", sub, ret);
|
||||
kfree(sub);
|
||||
if (!cs35l56->system_name)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev,
|
||||
@ -1024,7 +1035,18 @@ const struct dev_pm_ops cs35l56_hda_pm_ops = {
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56);
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_HDA_SCODEC_CS35L56_KUNIT_TEST)
|
||||
/* Hooks to export static function to KUnit test */
|
||||
|
||||
int cs35l56_hda_test_hook_get_speaker_id(struct device *dev, int amp_index, int num_amps)
|
||||
{
|
||||
return cs35l56_hda_get_speaker_id(dev, amp_index, num_amps);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cs35l56_hda_test_hook_get_speaker_id, SND_HDA_SCODEC_CS35L56);
|
||||
#endif
|
||||
|
||||
MODULE_DESCRIPTION("CS35L56 HDA Driver");
|
||||
MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);
|
||||
MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS);
|
||||
MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
|
@ -88,7 +88,7 @@ struct hda_conn_list {
|
||||
struct list_head list;
|
||||
int len;
|
||||
hda_nid_t nid;
|
||||
hda_nid_t conns[];
|
||||
hda_nid_t conns[] __counted_by(len);
|
||||
};
|
||||
|
||||
/* look up the cached results */
|
||||
|
@ -6,6 +6,7 @@
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/component.h>
|
||||
|
||||
#define HDA_MAX_COMPONENTS 4
|
||||
@ -15,6 +16,9 @@ struct hda_component {
|
||||
struct device *dev;
|
||||
char name[HDA_MAX_NAME_SIZE];
|
||||
struct hda_codec *codec;
|
||||
struct acpi_device *adev;
|
||||
bool acpi_notifications_supported;
|
||||
void (*acpi_notify)(acpi_handle handle, u32 event, struct device *dev);
|
||||
void (*pre_playback_hook)(struct device *dev, int action);
|
||||
void (*playback_hook)(struct device *dev, int action);
|
||||
void (*post_playback_hook)(struct device *dev, int action);
|
||||
|
@ -182,7 +182,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
|
||||
snd_hdac_stream_setup(azx_stream(azx_dev));
|
||||
snd_hdac_stream_setup(azx_stream(azx_dev), false);
|
||||
|
||||
stream_tag = azx_dev->core.stream_tag;
|
||||
/* CA-IBG chips need the playback stream starting from 1 */
|
||||
|
@ -806,7 +806,7 @@ static unsigned int azx_via_get_position(struct azx *chip,
|
||||
mod_dma_pos = le32_to_cpu(*azx_dev->core.posbuf);
|
||||
mod_dma_pos %= azx_dev->core.period_bytes;
|
||||
|
||||
fifo_size = azx_stream(azx_dev)->fifo_size - 1;
|
||||
fifo_size = azx_stream(azx_dev)->fifo_size;
|
||||
|
||||
if (azx_dev->insufficient) {
|
||||
/* Link position never gather than FIFO size */
|
||||
@ -2129,6 +2129,36 @@ static int azx_probe(struct pci_dev *pci,
|
||||
|
||||
pci_set_drvdata(pci, card);
|
||||
|
||||
#ifdef CONFIG_SND_HDA_I915
|
||||
/* bind with i915 if needed */
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) {
|
||||
err = snd_hdac_i915_init(azx_bus(chip));
|
||||
if (err < 0) {
|
||||
/* if the controller is bound only with HDMI/DP
|
||||
* (for HSW and BDW), we need to abort the probe;
|
||||
* for other chips, still continue probing as other
|
||||
* codecs can be on the same link.
|
||||
*/
|
||||
if (HDA_CONTROLLER_IN_GPU(pci)) {
|
||||
dev_err_probe(card->dev, err,
|
||||
"HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n");
|
||||
|
||||
goto out_free;
|
||||
} else {
|
||||
/* don't bother any longer */
|
||||
chip->driver_caps &= ~AZX_DCAPS_I915_COMPONENT;
|
||||
}
|
||||
}
|
||||
|
||||
/* HSW/BDW controllers need this power */
|
||||
if (HDA_CONTROLLER_IN_GPU(pci))
|
||||
hda->need_i915_power = true;
|
||||
}
|
||||
#else
|
||||
if (HDA_CONTROLLER_IN_GPU(pci))
|
||||
dev_err(card->dev, "Haswell/Broadwell HDMI/DP must build in CONFIG_SND_HDA_I915\n");
|
||||
#endif
|
||||
|
||||
err = register_vga_switcheroo(chip);
|
||||
if (err < 0) {
|
||||
dev_err(card->dev, "Error registering vga_switcheroo client\n");
|
||||
@ -2156,11 +2186,6 @@ static int azx_probe(struct pci_dev *pci,
|
||||
}
|
||||
#endif /* CONFIG_SND_HDA_PATCH_LOADER */
|
||||
|
||||
#ifndef CONFIG_SND_HDA_I915
|
||||
if (HDA_CONTROLLER_IN_GPU(pci))
|
||||
dev_err(card->dev, "Haswell/Broadwell HDMI/DP must build in CONFIG_SND_HDA_I915\n");
|
||||
#endif
|
||||
|
||||
if (schedule_probe)
|
||||
schedule_delayed_work(&hda->probe_work, 0);
|
||||
|
||||
@ -2170,6 +2195,7 @@ static int azx_probe(struct pci_dev *pci,
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
pci_set_drvdata(pci, NULL);
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
@ -2257,30 +2283,6 @@ static int azx_probe_continue(struct azx *chip)
|
||||
to_hda_bus(bus)->bus_probing = 1;
|
||||
hda->probe_continued = 1;
|
||||
|
||||
/* bind with i915 if needed */
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) {
|
||||
err = snd_hdac_i915_init(bus);
|
||||
if (err < 0) {
|
||||
/* if the controller is bound only with HDMI/DP
|
||||
* (for HSW and BDW), we need to abort the probe;
|
||||
* for other chips, still continue probing as other
|
||||
* codecs can be on the same link.
|
||||
*/
|
||||
if (HDA_CONTROLLER_IN_GPU(pci)) {
|
||||
dev_err(chip->card->dev,
|
||||
"HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n");
|
||||
goto out_free;
|
||||
} else {
|
||||
/* don't bother any longer */
|
||||
chip->driver_caps &= ~AZX_DCAPS_I915_COMPONENT;
|
||||
}
|
||||
}
|
||||
|
||||
/* HSW/BDW controllers need this power */
|
||||
if (HDA_CONTROLLER_IN_GPU(pci))
|
||||
hda->need_i915_power = true;
|
||||
}
|
||||
|
||||
/* Request display power well for the HDA controller or codec. For
|
||||
* Haswell/Broadwell, both the display HDA controller and codec need
|
||||
* this power. For other platforms, like Baytrail/Braswell, only the
|
||||
|
@ -10,6 +10,7 @@
|
||||
* Jonathan Woithe <jwoithe@just42.net>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
@ -6704,12 +6705,91 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static void comp_acpi_device_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct hda_codec *cdc = data;
|
||||
struct alc_spec *spec = cdc->spec;
|
||||
int i;
|
||||
|
||||
codec_info(cdc, "ACPI Notification %d\n", event);
|
||||
|
||||
for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
|
||||
if (spec->comps[i].dev && spec->comps[i].acpi_notify)
|
||||
spec->comps[i].acpi_notify(acpi_device_handle(spec->comps[i].adev), event,
|
||||
spec->comps[i].dev);
|
||||
}
|
||||
}
|
||||
|
||||
static int comp_bind_acpi(struct device *dev)
|
||||
{
|
||||
struct hda_codec *cdc = dev_to_hda_codec(dev);
|
||||
struct alc_spec *spec = cdc->spec;
|
||||
bool support_notifications = false;
|
||||
struct acpi_device *adev;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
adev = spec->comps[0].adev;
|
||||
if (!acpi_device_handle(adev))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < HDA_MAX_COMPONENTS; i++)
|
||||
support_notifications = support_notifications ||
|
||||
spec->comps[i].acpi_notifications_supported;
|
||||
|
||||
if (support_notifications) {
|
||||
ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
|
||||
comp_acpi_device_notify, cdc);
|
||||
if (ret < 0) {
|
||||
codec_warn(cdc, "Failed to install notify handler: %d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
codec_dbg(cdc, "Notify handler installed\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void comp_unbind_acpi(struct device *dev)
|
||||
{
|
||||
struct hda_codec *cdc = dev_to_hda_codec(dev);
|
||||
struct alc_spec *spec = cdc->spec;
|
||||
struct acpi_device *adev;
|
||||
int ret;
|
||||
|
||||
adev = spec->comps[0].adev;
|
||||
if (!acpi_device_handle(adev))
|
||||
return;
|
||||
|
||||
ret = acpi_remove_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
|
||||
comp_acpi_device_notify);
|
||||
if (ret < 0)
|
||||
codec_warn(cdc, "Failed to uninstall notify handler: %d\n", ret);
|
||||
}
|
||||
#else
|
||||
static int comp_bind_acpi(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void comp_unbind_acpi(struct device *dev)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static int comp_bind(struct device *dev)
|
||||
{
|
||||
struct hda_codec *cdc = dev_to_hda_codec(dev);
|
||||
struct alc_spec *spec = cdc->spec;
|
||||
int ret;
|
||||
|
||||
return component_bind_all(dev, spec->comps);
|
||||
ret = component_bind_all(dev, spec->comps);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return comp_bind_acpi(dev);
|
||||
}
|
||||
|
||||
static void comp_unbind(struct device *dev)
|
||||
@ -6717,6 +6797,7 @@ static void comp_unbind(struct device *dev)
|
||||
struct hda_codec *cdc = dev_to_hda_codec(dev);
|
||||
struct alc_spec *spec = cdc->spec;
|
||||
|
||||
comp_unbind_acpi(dev);
|
||||
component_unbind_all(dev, spec->comps);
|
||||
}
|
||||
|
||||
|
@ -918,7 +918,7 @@ static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing)
|
||||
}
|
||||
|
||||
if (chip->device_type == DEVICE_SIS) {
|
||||
/* unmute the output on SIS7012 */
|
||||
/* unmute the output on SIS7013 */
|
||||
iputword(chip, 0x4c, igetword(chip, 0x4c) | 1);
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ struct mixart_enum_connector_resp
|
||||
u32 uid_count;
|
||||
u32 current_uid_index;
|
||||
struct mixart_uid uid[MIXART_MAX_PHYS_CONNECTORS];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* used for following struct */
|
||||
@ -81,7 +81,7 @@ struct mixart_audio_info_req
|
||||
u32 line_max_level; /* float */
|
||||
u32 micro_max_level; /* float */
|
||||
u32 cd_max_level; /* float */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_analog_hw_info
|
||||
{
|
||||
@ -93,7 +93,7 @@ struct mixart_analog_hw_info
|
||||
u32 step_var_level; /* float */
|
||||
u32 fix_gain; /* float */
|
||||
u32 zero_var; /* float */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_digital_hw_info
|
||||
{
|
||||
@ -101,7 +101,7 @@ struct mixart_digital_hw_info
|
||||
u32 presence;
|
||||
u32 clock;
|
||||
u32 reserved;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_analog_info
|
||||
{
|
||||
@ -110,27 +110,27 @@ struct mixart_analog_info
|
||||
struct mixart_analog_hw_info line_info;
|
||||
struct mixart_analog_hw_info cd_info;
|
||||
u32 analog_level_present;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_digital_info
|
||||
{
|
||||
u32 type_mask;
|
||||
struct mixart_digital_hw_info aes_info;
|
||||
struct mixart_digital_hw_info adat_info;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_audio_info
|
||||
{
|
||||
u32 clock_type_mask;
|
||||
struct mixart_analog_info analog_info;
|
||||
struct mixart_digital_info digital_info;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_audio_info_resp
|
||||
{
|
||||
u32 txx_status;
|
||||
struct mixart_audio_info info;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* used for nb_bytes_max_per_sample */
|
||||
@ -142,7 +142,7 @@ struct mixart_stream_info
|
||||
u32 size_max_byte_frame;
|
||||
u32 size_max_sample_frame;
|
||||
u32 nb_bytes_max_per_sample; /* float */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* MSG_STREAM_ADD_INPUT_GROUP */
|
||||
/* MSG_STREAM_ADD_OUTPUT_GROUP */
|
||||
@ -157,13 +157,13 @@ struct mixart_streaming_group_req
|
||||
struct mixart_stream_info stream_info[32];
|
||||
struct mixart_uid connector;
|
||||
u32 flow_entry[32];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_stream_desc
|
||||
{
|
||||
struct mixart_uid stream_uid;
|
||||
u32 stream_desc;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_streaming_group
|
||||
{
|
||||
@ -172,7 +172,7 @@ struct mixart_streaming_group
|
||||
u32 pipe_desc;
|
||||
u32 stream_count;
|
||||
struct mixart_stream_desc stream[32];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* MSG_STREAM_DELETE_GROUP */
|
||||
|
||||
@ -182,7 +182,7 @@ struct mixart_delete_group_resp
|
||||
{
|
||||
u32 status;
|
||||
u32 unused[2];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* MSG_STREAM_START_INPUT_STAGE_PACKET = 0x130000 + 7,
|
||||
@ -195,7 +195,7 @@ struct mixart_fx_couple_uid
|
||||
{
|
||||
struct mixart_uid uid_fx_code;
|
||||
struct mixart_uid uid_fx_data;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_txx_stream_desc
|
||||
{
|
||||
@ -203,14 +203,14 @@ struct mixart_txx_stream_desc
|
||||
u32 stream_idx;
|
||||
u32 fx_number;
|
||||
struct mixart_fx_couple_uid uid_fx[4];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_flow_info
|
||||
{
|
||||
struct mixart_txx_stream_desc stream_desc;
|
||||
u32 flow_entry;
|
||||
u32 flow_phy_addr;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_stream_state_req
|
||||
{
|
||||
@ -219,7 +219,7 @@ struct mixart_stream_state_req
|
||||
u32 reserved4np[3];
|
||||
u32 stream_count; /* set to 1 for instance */
|
||||
struct mixart_flow_info stream_info; /* could be an array[stream_count] */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* MSG_STREAM_START_STREAM_GRP_PACKET = 0x130000 + 6
|
||||
MSG_STREAM_STOP_STREAM_GRP_PACKET = 0x130000 + 9
|
||||
@ -232,13 +232,13 @@ struct mixart_group_state_req
|
||||
u32 reserved4np[2];
|
||||
u32 pipe_count; /* set to 1 for instance */
|
||||
struct mixart_uid pipe_uid; /* could be an array[pipe_count], in theory */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_group_state_resp
|
||||
{
|
||||
u32 txx_status;
|
||||
u64 scheduler;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
|
||||
@ -250,7 +250,7 @@ struct mixart_sample_pos
|
||||
u32 validity;
|
||||
u32 sample_pos_high_part;
|
||||
u32 sample_pos_low_part;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This structure is limited by the size of MSG_DEFAULT_SIZE. Instead of
|
||||
@ -263,7 +263,7 @@ struct mixart_timer_notify
|
||||
{
|
||||
u32 stream_count;
|
||||
struct mixart_sample_pos streams[MIXART_MAX_TIMER_NOTIFY_STREAMS];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* MSG_CONSOLE_GET_CLOCK_UID = 0x070003,
|
||||
@ -275,7 +275,7 @@ struct mixart_return_uid
|
||||
{
|
||||
u32 error_code;
|
||||
struct mixart_uid uid;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* MSG_CLOCK_CHECK_PROPERTIES = 0x200001,
|
||||
MSG_CLOCK_SET_PROPERTIES = 0x200002,
|
||||
@ -315,13 +315,13 @@ struct mixart_clock_properties
|
||||
u32 board_mask;
|
||||
u32 nb_callers; /* set to 1 (see below) */
|
||||
struct mixart_uid uid_caller;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_clock_properties_resp
|
||||
{
|
||||
u32 status;
|
||||
u32 clock_mode;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* MSG_STREAM_SET_INPUT_STAGE_PARAM = 0x13000F */
|
||||
@ -402,7 +402,7 @@ struct mixart_stream_param_desc
|
||||
u32 pipe_count; /* set to 1 (array size !) */
|
||||
u32 stream_count; /* set to 1 (array size !) */
|
||||
struct mixart_txx_stream_desc stream_desc; /* only one stream per command, but this could be an array, in theory */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* MSG_CONNECTOR_GET_OUT_AUDIO_LEVEL = 0x050009,
|
||||
@ -418,7 +418,7 @@ struct mixart_get_out_audio_level
|
||||
u32 mute;
|
||||
u32 monitor_mute1;
|
||||
u32 monitor_mute2;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL = 0x05000A,
|
||||
@ -445,7 +445,7 @@ struct mixart_set_out_audio_level
|
||||
u32 monitor_mute1;
|
||||
u32 monitor_mute2;
|
||||
u32 reserved4np;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* MSG_SYSTEM_ENUM_PHYSICAL_IO = 0x16000E,
|
||||
@ -460,7 +460,7 @@ struct mixart_uid_enumeration
|
||||
u32 nb_uid;
|
||||
u32 current_uid_index;
|
||||
struct mixart_uid uid[MIXART_MAX_PHYS_IO];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* MSG_PHYSICALIO_SET_LEVEL = 0x0F0008,
|
||||
@ -471,13 +471,13 @@ struct mixart_io_channel_level
|
||||
{
|
||||
u32 analog_level; /* float */
|
||||
u32 unused[2];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_io_level
|
||||
{
|
||||
s32 channel; /* 0=left, 1=right, -1=both, -2=both same */
|
||||
struct mixart_io_channel_level level[2];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* MSG_STREAM_SET_IN_AUDIO_LEVEL = 0x130015,
|
||||
@ -490,7 +490,7 @@ struct mixart_in_audio_level_info
|
||||
u32 valid_mask2;
|
||||
u32 digital_level;
|
||||
u32 analog_level;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_set_in_audio_level_req
|
||||
{
|
||||
@ -499,7 +499,7 @@ struct mixart_set_in_audio_level_req
|
||||
u32 audio_count; /* set to <= 2 */
|
||||
u32 reserved4np;
|
||||
struct mixart_in_audio_level_info level[2];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* response is a 32 bit status */
|
||||
|
||||
@ -529,13 +529,13 @@ struct mixart_out_stream_level_info
|
||||
u32 digital_level2;
|
||||
u32 mute1;
|
||||
u32 mute2;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_set_out_stream_level
|
||||
{
|
||||
struct mixart_txx_stream_desc desc;
|
||||
struct mixart_out_stream_level_info out_level;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct mixart_set_out_stream_level_req
|
||||
{
|
||||
@ -544,7 +544,7 @@ struct mixart_set_out_stream_level_req
|
||||
u32 reserved4np[2];
|
||||
u32 nb_of_stream; /* set to 1 */
|
||||
struct mixart_set_out_stream_level stream_level; /* could be an array */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* response to this request is a u32 status value */
|
||||
|
||||
|
@ -61,6 +61,76 @@ static const struct config_entry config_table[] = {
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.flags = FLAG_AMD_LEGACY,
|
||||
.device = ACP_PCI_DEV_ID,
|
||||
.dmi_table = (const struct dmi_system_id []) {
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXXW"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.flags = FLAG_AMD_LEGACY,
|
||||
.device = ACP_PCI_DEV_ID,
|
||||
.dmi_table = (const struct dmi_system_id []) {
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "KLVL-WXX9"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.flags = FLAG_AMD_LEGACY,
|
||||
.device = ACP_PCI_DEV_ID,
|
||||
.dmi_table = (const struct dmi_system_id []) {
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BOM-WXX9"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.flags = FLAG_AMD_LEGACY,
|
||||
.device = ACP_PCI_DEV_ID,
|
||||
.dmi_table = (const struct dmi_system_id []) {
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1020"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.flags = FLAG_AMD_LEGACY,
|
||||
.device = ACP_PCI_DEV_ID,
|
||||
.dmi_table = (const struct dmi_system_id []) {
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1040"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
int snd_amd_acp_find_config(struct pci_dev *pci)
|
||||
@ -193,4 +263,16 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[] = {
|
||||
};
|
||||
EXPORT_SYMBOL(snd_soc_acpi_amd_rmb_sof_machines);
|
||||
|
||||
struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[] = {
|
||||
{
|
||||
.id = "AMDI1019",
|
||||
.drv_name = "acp63-dsp",
|
||||
.pdata = &acp_quirk_data,
|
||||
.fw_filename = "sof-acp_6_3.ri",
|
||||
.sof_tplg_filename = "sof-acp_6_3.tplg",
|
||||
},
|
||||
{},
|
||||
};
|
||||
EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_machines);
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
@ -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 = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *codec_dai = snd_soc_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);
|
||||
@ -106,7 +106,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
|
||||
static int da7219_clk_enable(struct snd_pcm_substream *substream)
|
||||
{
|
||||
int ret = 0;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
|
||||
/*
|
||||
* Set wclk to 48000 because the rate constraint of this driver is
|
||||
@ -134,7 +134,7 @@ static int cz_rt5682_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_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
|
||||
dev_info(codec_dai->dev, "codec dai name = %s\n", codec_dai->name);
|
||||
@ -191,7 +191,7 @@ static int cz_rt5682_init(struct snd_soc_pcm_runtime *rtd)
|
||||
static int rt5682_clk_enable(struct snd_pcm_substream *substream)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
|
||||
/*
|
||||
* Set wclk to 48000 because the rate constraint of this driver is
|
||||
@ -245,7 +245,7 @@ static const struct snd_pcm_hw_constraint_list constraints_channels = {
|
||||
static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
@ -266,7 +266,7 @@ static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
|
||||
static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
@ -288,7 +288,7 @@ static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
|
||||
static int cz_max_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
@ -309,7 +309,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream)
|
||||
static int cz_dmic0_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
@ -330,7 +330,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream *substream)
|
||||
static int cz_dmic1_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
@ -357,7 +357,7 @@ static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
|
||||
static int cz_rt5682_play_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
@ -378,7 +378,7 @@ static int cz_rt5682_play_startup(struct snd_pcm_substream *substream)
|
||||
static int cz_rt5682_cap_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
@ -400,7 +400,7 @@ static int cz_rt5682_cap_startup(struct snd_pcm_substream *substream)
|
||||
static int cz_rt5682_max_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
@ -421,7 +421,7 @@ static int cz_rt5682_max_startup(struct snd_pcm_substream *substream)
|
||||
static int cz_rt5682_dmic0_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
@ -442,7 +442,7 @@ static int cz_rt5682_dmic0_startup(struct snd_pcm_substream *substream)
|
||||
static int cz_rt5682_dmic1_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
|
@ -62,7 +62,7 @@ static int st_es8336_init(struct snd_soc_pcm_runtime *rtd)
|
||||
struct snd_soc_card *card;
|
||||
struct snd_soc_component *codec;
|
||||
|
||||
codec = asoc_rtd_to_codec(rtd, 0)->component;
|
||||
codec = snd_soc_rtd_to_codec(rtd, 0)->component;
|
||||
card = rtd->card;
|
||||
|
||||
ret = snd_soc_card_jack_new_pins(card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0,
|
||||
@ -111,10 +111,10 @@ static int st_es8336_codec_startup(struct snd_pcm_substream *substream)
|
||||
int ret;
|
||||
|
||||
runtime = substream->runtime;
|
||||
rtd = asoc_substream_to_rtd(substream);
|
||||
rtd = snd_soc_substream_to_rtd(substream);
|
||||
card = rtd->card;
|
||||
machine = snd_soc_card_get_drvdata(card);
|
||||
codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, 0, ES8336_PLL_FREQ, SND_SOC_CLOCK_IN);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
|
||||
|
@ -849,7 +849,7 @@ static int acp_dma_hw_params(struct snd_soc_component *component,
|
||||
u32 val = 0;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct audio_substream_data *rtd;
|
||||
struct snd_soc_pcm_runtime *prtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *prtd = snd_soc_substream_to_rtd(substream);
|
||||
struct audio_drv_data *adata = dev_get_drvdata(component->dev);
|
||||
struct snd_soc_card *card = prtd->card;
|
||||
struct acp_platform_info *pinfo = snd_soc_card_get_drvdata(card);
|
||||
|
@ -57,8 +57,8 @@ static int cz_aif1_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
int ret = 0;
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_dai *codec_dai = snd_soc_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);
|
||||
@ -83,7 +83,7 @@ static int cz_init(struct snd_soc_pcm_runtime *rtd)
|
||||
struct snd_soc_card *card;
|
||||
struct snd_soc_component *codec;
|
||||
|
||||
codec = asoc_rtd_to_codec(rtd, 0)->component;
|
||||
codec = snd_soc_rtd_to_codec(rtd, 0)->component;
|
||||
card = rtd->card;
|
||||
|
||||
ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
|
||||
|
@ -30,13 +30,15 @@ config SND_SOC_AMD_ACP_PCM
|
||||
|
||||
config SND_SOC_AMD_ACP_PCI
|
||||
tristate "AMD ACP PCI Driver Support"
|
||||
select SND_SOC_AMD_ACP_LEGACY_COMMON
|
||||
depends on X86 && PCI
|
||||
depends on ACPI
|
||||
select SND_SOC_AMD_ACP_LEGACY_COMMON
|
||||
help
|
||||
This options enables generic PCI driver for ACP device.
|
||||
|
||||
config SND_AMD_ASOC_RENOIR
|
||||
tristate "AMD ACP ASOC Renoir Support"
|
||||
depends on ACPI
|
||||
select SND_SOC_AMD_ACP_PCM
|
||||
select SND_SOC_AMD_ACP_I2S
|
||||
select SND_SOC_AMD_ACP_PDM
|
||||
@ -47,6 +49,7 @@ config SND_AMD_ASOC_RENOIR
|
||||
|
||||
config SND_AMD_ASOC_REMBRANDT
|
||||
tristate "AMD ACP ASOC Rembrandt Support"
|
||||
depends on ACPI
|
||||
select SND_SOC_AMD_ACP_PCM
|
||||
select SND_SOC_AMD_ACP_I2S
|
||||
select SND_SOC_AMD_ACP_PDM
|
||||
@ -57,6 +60,19 @@ config SND_AMD_ASOC_REMBRANDT
|
||||
Say Y if you want to enable AUDIO on Rembrandt
|
||||
If unsure select "N".
|
||||
|
||||
config SND_AMD_ASOC_ACP63
|
||||
tristate "AMD ACP ASOC ACP6.3 Support"
|
||||
depends on X86 && PCI
|
||||
depends on ACPI
|
||||
select SND_SOC_AMD_ACP_PCM
|
||||
select SND_SOC_AMD_ACP_I2S
|
||||
select SND_SOC_AMD_ACP_PDM
|
||||
select SND_SOC_AMD_ACP_LEGACY_COMMON
|
||||
help
|
||||
This option enables Acp6.3 I2S support on AMD platform.
|
||||
Say Y if you want to enable AUDIO on ACP6.3
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_AMD_MACH_COMMON
|
||||
tristate
|
||||
depends on X86 && PCI && I2C
|
||||
|
@ -14,10 +14,11 @@ snd-acp-pci-objs := acp-pci.o
|
||||
#platform specific driver
|
||||
snd-acp-renoir-objs := acp-renoir.o
|
||||
snd-acp-rembrandt-objs := acp-rembrandt.o
|
||||
snd-acp63-objs := acp63.o
|
||||
|
||||
#machine specific driver
|
||||
snd-acp-mach-objs := acp-mach-common.o
|
||||
snd-acp-legacy-mach-objs := acp-legacy-mach.o
|
||||
snd-acp-legacy-mach-objs := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o
|
||||
snd-acp-sof-mach-objs := acp-sof-mach.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
|
||||
@ -28,6 +29,7 @@ obj-$(CONFIG_SND_SOC_AMD_ACP_PCI) += snd-acp-pci.o
|
||||
|
||||
obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
|
||||
obj-$(CONFIG_SND_AMD_ASOC_REMBRANDT) += snd-acp-rembrandt.o
|
||||
obj-$(CONFIG_SND_AMD_ASOC_ACP63) += snd-acp63.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user