Merge branch 'for-next' into for-linus
Pull 6.7 materials Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
commit
c468b5dd75
@ -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,9 +14,6 @@ description:
|
||||
digital Smart K audio amplifier with an integrated 10.25V
|
||||
smart boost convert.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
@ -32,11 +29,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 +73,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:
|
||||
|
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
@ -4912,6 +4912,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*
|
||||
@ -8125,7 +8126,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>
|
||||
@ -15423,7 +15424,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
|
||||
@ -20066,7 +20067,7 @@ F: include/linux/sony-laptop.h
|
||||
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/
|
||||
@ -20079,7 +20080,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
|
||||
@ -20105,7 +20106,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
|
||||
@ -20113,6 +20114,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
|
||||
@ -20466,6 +20471,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>
|
||||
@ -22936,7 +22948,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",
|
||||
|
@ -512,6 +512,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);
|
||||
int 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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,23 @@ 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);
|
||||
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 +1082,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 +1174,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 +1189,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 +1221,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 +1321,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 +1602,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 +1713,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 +1723,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 +1757,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 +1784,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 +1792,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 +1812,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 +1821,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 +1829,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 +1841,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 +1849,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 */
|
||||
@ -2135,6 +2135,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");
|
||||
@ -2162,11 +2192,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);
|
||||
|
||||
@ -2176,6 +2201,7 @@ static int azx_probe(struct pci_dev *pci,
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
pci_set_drvdata(pci, NULL);
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
@ -2263,30 +2289,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)
|
||||
|
@ -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",
|
||||
|
@ -17,7 +17,7 @@ snd-acp-rembrandt-objs := acp-rembrandt.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
|
||||
|
@ -80,8 +80,8 @@ void restore_acp_pdm_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *soc_runtime;
|
||||
u32 ext_int_ctrl;
|
||||
|
||||
soc_runtime = asoc_substream_to_rtd(substream);
|
||||
dai = asoc_rtd_to_cpu(soc_runtime, 0);
|
||||
soc_runtime = snd_soc_substream_to_rtd(substream);
|
||||
dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
|
||||
/* Programming channel mask and sampling rate */
|
||||
writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
|
||||
writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
|
||||
@ -192,8 +192,8 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *soc_runtime;
|
||||
u32 tdm_fmt, reg_val, fmt_reg, val;
|
||||
|
||||
soc_runtime = asoc_substream_to_rtd(substream);
|
||||
dai = asoc_rtd_to_cpu(soc_runtime, 0);
|
||||
soc_runtime = snd_soc_substream_to_rtd(substream);
|
||||
dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
tdm_fmt = adata->tdm_tx_fmt[stream->dai_id - 1];
|
||||
switch (stream->dai_id) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "acp-mach.h"
|
||||
#include "acp3x-es83xx/acp3x-es83xx.h"
|
||||
|
||||
static struct acp_card_drvdata rt5682_rt1019_data = {
|
||||
.hs_cpu_id = I2S_SP,
|
||||
@ -51,6 +52,14 @@ static struct acp_card_drvdata rt5682s_rt1019_data = {
|
||||
.tdm_mode = false,
|
||||
};
|
||||
|
||||
static struct acp_card_drvdata es83xx_rn_data = {
|
||||
.hs_cpu_id = I2S_SP,
|
||||
.dmic_cpu_id = DMIC,
|
||||
.hs_codec_id = ES83XX,
|
||||
.dmic_codec_id = DMIC,
|
||||
.platform = RENOIR,
|
||||
};
|
||||
|
||||
static struct acp_card_drvdata max_nau8825_data = {
|
||||
.hs_cpu_id = I2S_HS,
|
||||
.amp_cpu_id = I2S_HS,
|
||||
@ -75,6 +84,39 @@ static struct acp_card_drvdata rt5682s_rt1019_rmb_data = {
|
||||
.tdm_mode = false,
|
||||
};
|
||||
|
||||
static bool acp_asoc_init_ops(struct acp_card_drvdata *priv)
|
||||
{
|
||||
bool has_ops = false;
|
||||
|
||||
if (priv->hs_codec_id == ES83XX) {
|
||||
has_ops = true;
|
||||
acp3x_es83xx_init_ops(&priv->ops);
|
||||
}
|
||||
return has_ops;
|
||||
}
|
||||
|
||||
static int acp_asoc_suspend_pre(struct snd_soc_card *card)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = acp_ops_suspend_pre(card);
|
||||
if (ret == 1)
|
||||
return 0;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acp_asoc_resume_post(struct snd_soc_card *card)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = acp_ops_resume_post(card);
|
||||
if (ret == 1)
|
||||
return 0;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acp_asoc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = NULL;
|
||||
@ -83,35 +125,68 @@ static int acp_asoc_probe(struct platform_device *pdev)
|
||||
struct acp_card_drvdata *acp_card_drvdata;
|
||||
int ret;
|
||||
|
||||
if (!pdev->id_entry)
|
||||
return -EINVAL;
|
||||
if (!pdev->id_entry) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
if (!card) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
|
||||
acp_card_drvdata = card->drvdata;
|
||||
acp_card_drvdata->acpi_mach = (struct snd_soc_acpi_mach *)pdev->dev.platform_data;
|
||||
card->dev = dev;
|
||||
card->owner = THIS_MODULE;
|
||||
card->name = pdev->id_entry->name;
|
||||
card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
|
||||
/* Widgets and controls added per-codec in acp-mach-common.c */
|
||||
|
||||
acp_card_drvdata = card->drvdata;
|
||||
acp_asoc_init_ops(card->drvdata);
|
||||
|
||||
/* If widgets and controls are not set in specific callback,
|
||||
* they will be added per-codec in acp-mach-common.c
|
||||
*/
|
||||
ret = acp_ops_configure_widgets(card);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot configure widgets for card (%s): %d\n",
|
||||
card->name, ret);
|
||||
goto out;
|
||||
}
|
||||
card->suspend_pre = acp_asoc_suspend_pre;
|
||||
card->resume_post = acp_asoc_resume_post;
|
||||
|
||||
ret = acp_ops_probe(card);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot probe card (%s): %d\n",
|
||||
card->name, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dmi_id = dmi_first_match(acp_quirk_table);
|
||||
if (dmi_id && dmi_id->driver_data)
|
||||
acp_card_drvdata->tdm_mode = dmi_id->driver_data;
|
||||
|
||||
acp_legacy_dai_links_create(card);
|
||||
ret = acp_legacy_dai_links_create(card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot create dai links for card (%s): %d\n",
|
||||
card->name, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"devm_snd_soc_register_card(%s) failed: %d\n",
|
||||
card->name, ret);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct platform_device_id board_ids[] = {
|
||||
@ -127,6 +202,10 @@ static const struct platform_device_id board_ids[] = {
|
||||
.name = "acp3xalc5682s1019",
|
||||
.driver_data = (kernel_ulong_t)&rt5682s_rt1019_data,
|
||||
},
|
||||
{
|
||||
.name = "acp3x-es83xx",
|
||||
.driver_data = (kernel_ulong_t)&es83xx_rn_data,
|
||||
},
|
||||
{
|
||||
.name = "rmb-nau8825-max",
|
||||
.driver_data = (kernel_ulong_t)&max_nau8825_data,
|
||||
@ -153,6 +232,7 @@ MODULE_DESCRIPTION("ACP chrome audio support");
|
||||
MODULE_ALIAS("platform:acp3xalc56821019");
|
||||
MODULE_ALIAS("platform:acp3xalc5682sm98360");
|
||||
MODULE_ALIAS("platform:acp3xalc5682s1019");
|
||||
MODULE_ALIAS("platform:acp3x-es83xx");
|
||||
MODULE_ALIAS("platform:rmb-nau8825-max");
|
||||
MODULE_ALIAS("platform:rmb-rt5682s-rt1019");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -117,7 +117,7 @@ static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_card_drvdata *drvdata = card->drvdata;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
int ret;
|
||||
|
||||
@ -172,10 +172,10 @@ static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
|
||||
static int acp_card_hs_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_card_drvdata *drvdata = card->drvdata;
|
||||
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);
|
||||
int ret;
|
||||
unsigned int fmt;
|
||||
|
||||
@ -206,7 +206,7 @@ static int acp_card_hs_startup(struct snd_pcm_substream *substream)
|
||||
|
||||
static void acp_card_shutdown(struct snd_pcm_substream *substream)
|
||||
{
|
||||
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_card_drvdata *drvdata = card->drvdata;
|
||||
|
||||
@ -220,8 +220,8 @@ static int acp_card_rt5682_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_card_drvdata *drvdata = card->drvdata;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
int ret;
|
||||
unsigned int fmt, srate, ch, format;
|
||||
|
||||
@ -342,7 +342,7 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_card_drvdata *drvdata = card->drvdata;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
int ret;
|
||||
|
||||
@ -402,8 +402,8 @@ static int acp_card_rt5682s_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_card_drvdata *drvdata = card->drvdata;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
int ret;
|
||||
unsigned int fmt, srate, ch, format;
|
||||
|
||||
@ -573,7 +573,7 @@ static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_card_drvdata *drvdata = card->drvdata;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
int i, ret = 0;
|
||||
unsigned int fmt, srate, ch, format;
|
||||
|
||||
@ -737,7 +737,7 @@ static int acp_card_maxim_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_card_drvdata *drvdata = card->drvdata;
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
unsigned int fmt, srate, ch, format;
|
||||
int ret;
|
||||
|
||||
@ -928,7 +928,7 @@ static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_card_drvdata *drvdata = card->drvdata;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
int ret;
|
||||
|
||||
@ -980,11 +980,11 @@ static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)
|
||||
static int acp_nau8825_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_card_drvdata *drvdata = card->drvdata;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
int ret;
|
||||
unsigned int fmt;
|
||||
|
||||
@ -1142,7 +1142,7 @@ static struct snd_pcm_hw_constraint_list constraints_sample_bits = {
|
||||
static int acp_8821_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
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;
|
||||
int ret;
|
||||
|
||||
@ -1204,10 +1204,10 @@ static int acp_8821_startup(struct snd_pcm_substream *substream)
|
||||
static int acp_nau8821_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_card_drvdata *drvdata = card->drvdata;
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
int ret;
|
||||
unsigned int fmt;
|
||||
|
||||
@ -1358,7 +1358,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].no_pcm = 1;
|
||||
if (!drv_data->hs_codec_id) {
|
||||
/* Use dummy codec if codec id not specified */
|
||||
links[i].codecs = &asoc_dummy_dlc;
|
||||
links[i].codecs = &snd_soc_dummy_dlc;
|
||||
links[i].num_codecs = 1;
|
||||
}
|
||||
if (drv_data->hs_codec_id == RT5682) {
|
||||
@ -1395,7 +1395,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].no_pcm = 1;
|
||||
if (!drv_data->hs_codec_id) {
|
||||
/* Use dummy codec if codec id not specified */
|
||||
links[i].codecs = &asoc_dummy_dlc;
|
||||
links[i].codecs = &snd_soc_dummy_dlc;
|
||||
links[i].num_codecs = 1;
|
||||
}
|
||||
if (drv_data->hs_codec_id == NAU8825) {
|
||||
@ -1425,7 +1425,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].no_pcm = 1;
|
||||
if (!drv_data->amp_codec_id) {
|
||||
/* Use dummy codec if codec id not specified */
|
||||
links[i].codecs = &asoc_dummy_dlc;
|
||||
links[i].codecs = &snd_soc_dummy_dlc;
|
||||
links[i].num_codecs = 1;
|
||||
}
|
||||
if (drv_data->amp_codec_id == RT1019) {
|
||||
@ -1457,7 +1457,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].no_pcm = 1;
|
||||
if (!drv_data->amp_codec_id) {
|
||||
/* Use dummy codec if codec id not specified */
|
||||
links[i].codecs = &asoc_dummy_dlc;
|
||||
links[i].codecs = &snd_soc_dummy_dlc;
|
||||
links[i].num_codecs = 1;
|
||||
}
|
||||
if (drv_data->amp_codec_id == MAX98360A) {
|
||||
@ -1513,6 +1513,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
|
||||
struct device *dev = card->dev;
|
||||
struct acp_card_drvdata *drv_data = card->drvdata;
|
||||
int i = 0, num_links = 0;
|
||||
int rc;
|
||||
|
||||
if (drv_data->hs_cpu_id)
|
||||
num_links++;
|
||||
@ -1536,7 +1537,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].dpcm_capture = 1;
|
||||
if (!drv_data->hs_codec_id) {
|
||||
/* Use dummy codec if codec id not specified */
|
||||
links[i].codecs = &asoc_dummy_dlc;
|
||||
links[i].codecs = &snd_soc_dummy_dlc;
|
||||
links[i].num_codecs = 1;
|
||||
}
|
||||
if (drv_data->hs_codec_id == RT5682) {
|
||||
@ -1551,6 +1552,13 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].init = acp_card_rt5682s_init;
|
||||
links[i].ops = &acp_card_rt5682s_ops;
|
||||
}
|
||||
if (drv_data->hs_codec_id == ES83XX) {
|
||||
rc = acp_ops_configure_link(card, &links[i]);
|
||||
if (rc != 0) {
|
||||
dev_err(dev, "Failed to configure link for ES83XX: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
@ -1570,7 +1578,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].dpcm_capture = 1;
|
||||
if (!drv_data->hs_codec_id) {
|
||||
/* Use dummy codec if codec id not specified */
|
||||
links[i].codecs = &asoc_dummy_dlc;
|
||||
links[i].codecs = &snd_soc_dummy_dlc;
|
||||
links[i].num_codecs = 1;
|
||||
}
|
||||
if (drv_data->hs_codec_id == NAU8825) {
|
||||
@ -1598,7 +1606,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].dpcm_playback = 1;
|
||||
if (!drv_data->amp_codec_id) {
|
||||
/* Use dummy codec if codec id not specified */
|
||||
links[i].codecs = &asoc_dummy_dlc;
|
||||
links[i].codecs = &snd_soc_dummy_dlc;
|
||||
links[i].num_codecs = 1;
|
||||
}
|
||||
if (drv_data->amp_codec_id == RT1019) {
|
||||
@ -1633,7 +1641,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].dpcm_playback = 1;
|
||||
if (!drv_data->amp_codec_id) {
|
||||
/* Use dummy codec if codec id not specified */
|
||||
links[i].codecs = &asoc_dummy_dlc;
|
||||
links[i].codecs = &snd_soc_dummy_dlc;
|
||||
links[i].num_codecs = 1;
|
||||
}
|
||||
if (drv_data->amp_codec_id == MAX98360A) {
|
||||
@ -1661,7 +1669,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].num_codecs = ARRAY_SIZE(dmic_codec);
|
||||
} else {
|
||||
/* Use dummy codec if codec id not specified */
|
||||
links[i].codecs = &asoc_dummy_dlc;
|
||||
links[i].codecs = &snd_soc_dummy_dlc;
|
||||
links[i].num_codecs = 1;
|
||||
}
|
||||
links[i].cpus = pdm_dmic;
|
||||
|
@ -20,6 +20,10 @@
|
||||
|
||||
#define TDM_CHANNELS 8
|
||||
|
||||
#define ACP_OPS(priv, cb) ((priv)->ops.cb)
|
||||
|
||||
#define acp_get_drvdata(card) ((struct acp_card_drvdata *)(card)->drvdata)
|
||||
|
||||
enum be_id {
|
||||
HEADSET_BE_ID = 0,
|
||||
AMP_BE_ID,
|
||||
@ -43,6 +47,7 @@ enum codec_endpoints {
|
||||
NAU8825,
|
||||
NAU8821,
|
||||
MAX98388,
|
||||
ES83XX,
|
||||
};
|
||||
|
||||
enum platform_end_point {
|
||||
@ -50,6 +55,14 @@ enum platform_end_point {
|
||||
REMBRANDT,
|
||||
};
|
||||
|
||||
struct acp_mach_ops {
|
||||
int (*probe)(struct snd_soc_card *card);
|
||||
int (*configure_link)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
int (*configure_widgets)(struct snd_soc_card *card);
|
||||
int (*suspend_pre)(struct snd_soc_card *card);
|
||||
int (*resume_post)(struct snd_soc_card *card);
|
||||
};
|
||||
|
||||
struct acp_card_drvdata {
|
||||
unsigned int hs_cpu_id;
|
||||
unsigned int amp_cpu_id;
|
||||
@ -61,6 +74,9 @@ struct acp_card_drvdata {
|
||||
unsigned int platform;
|
||||
struct clk *wclk;
|
||||
struct clk *bclk;
|
||||
struct acp_mach_ops ops;
|
||||
struct snd_soc_acpi_mach *acpi_mach;
|
||||
void *mach_priv;
|
||||
bool soc_mclk;
|
||||
bool tdm_mode;
|
||||
};
|
||||
@ -69,4 +85,55 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card);
|
||||
int acp_legacy_dai_links_create(struct snd_soc_card *card);
|
||||
extern const struct dmi_system_id acp_quirk_table[];
|
||||
|
||||
static inline int acp_ops_probe(struct snd_soc_card *card)
|
||||
{
|
||||
int ret = 1;
|
||||
struct acp_card_drvdata *priv = acp_get_drvdata(card);
|
||||
|
||||
if (ACP_OPS(priv, probe))
|
||||
ret = ACP_OPS(priv, probe)(card);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int acp_ops_configure_link(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_link)
|
||||
{
|
||||
int ret = 1;
|
||||
struct acp_card_drvdata *priv = acp_get_drvdata(card);
|
||||
|
||||
if (ACP_OPS(priv, configure_link))
|
||||
ret = ACP_OPS(priv, configure_link)(card, dai_link);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int acp_ops_configure_widgets(struct snd_soc_card *card)
|
||||
{
|
||||
int ret = 1;
|
||||
struct acp_card_drvdata *priv = acp_get_drvdata(card);
|
||||
|
||||
if (ACP_OPS(priv, configure_widgets))
|
||||
ret = ACP_OPS(priv, configure_widgets)(card);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int acp_ops_suspend_pre(struct snd_soc_card *card)
|
||||
{
|
||||
int ret = 1;
|
||||
struct acp_card_drvdata *priv = acp_get_drvdata(card);
|
||||
|
||||
if (ACP_OPS(priv, suspend_pre))
|
||||
ret = ACP_OPS(priv, suspend_pre)(card);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int acp_ops_resume_post(struct snd_soc_card *card)
|
||||
{
|
||||
int ret = 1;
|
||||
struct acp_card_drvdata *priv = acp_get_drvdata(card);
|
||||
|
||||
if (ACP_OPS(priv, resume_post))
|
||||
ret = ACP_OPS(priv, resume_post)(card);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user