Merge branch 'for-next' into for-linus

Pull 6.7 materials

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2023-10-31 08:58:36 +01:00
commit c468b5dd75
656 changed files with 12214 additions and 5721 deletions

View File

@ -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.

View File

@ -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

View 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>;
};
};

View File

@ -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;
};
};

View File

@ -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

View File

@ -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

View File

@ -89,6 +89,7 @@ properties:
da7219_aad:
type: object
additionalProperties: false
description:
Configuration of advanced accessory detection.
properties:

View File

@ -33,6 +33,7 @@ patternProperties:
description:
A DAI managed by this controller
type: object
additionalProperties: false
properties:
reg:

View File

@ -17,6 +17,7 @@ properties:
enum:
- mediatek,mt8188-mt6359-evb
- mediatek,mt8188-nau8825
- mediatek,mt8188-rt5682s
audio-routing:
description:

View File

@ -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

View 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>;
};
};

View File

@ -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:

View File

@ -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:

View 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>;
};
};

View 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>;
};
};

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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
...

View File

@ -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>;
};
};

View File

@ -60,6 +60,7 @@ properties:
ports:
$ref: audio-graph-port.yaml#/definitions/port-base
unevaluatedProperties: false
properties:
port@0:
$ref: audio-graph-port.yaml#

View File

@ -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 */
};

View File

@ -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

View File

@ -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 ... >

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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",

View File

@ -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",

View File

@ -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" },

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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_ */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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)
};

View File

@ -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 {

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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;
};
/**

View File

@ -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;

View File

@ -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) \

View File

@ -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; \

View File

@ -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;
/*

View File

@ -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

View File

@ -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;
};

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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>

View File

@ -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");

View File

@ -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 */

View File

@ -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>");

View File

@ -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"

View File

@ -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>");

View File

@ -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>

View File

@ -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>

View File

@ -13,7 +13,6 @@
#include <sound/pcm.h>
#include <asm/prom.h>
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>

View File

@ -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 */

View File

@ -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>

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View 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");

View 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 */

View 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");

View File

@ -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, &regid, &reg_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, &regid, &reg_revid);
if (ret)
goto err;
}
ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, &regid);
if (ret) {
dev_err(cs35l41->dev, "Get Device ID failed: %d\n", ret);
goto err;
}
ret = regmap_read(cs35l41->regmap, CS35L41_REVID, &reg_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))

View File

@ -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 {

View File

@ -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;

View File

@ -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>");

View File

@ -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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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",

View File

@ -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

View File

@ -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) {

View File

@ -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");

View File

@ -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;

View File

@ -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