From 249b557b6e341743ba8cdb8c0ce89a897e7e1e91 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:29:59 +0100 Subject: [PATCH 001/256] dt-bindings: vendor-prefixes: Add NeoFidelity, Inc JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 5d9e6d6fc1b98c8c22d110ee931b3b233d43cd13 Author: Igor Prusov Date: Wed Sep 25 17:52:39 2024 +0300 dt-bindings: vendor-prefixes: Add NeoFidelity, Inc Add vendor prefix for NeoFidelity, Inc Signed-off-by: Igor Prusov Acked-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20240925-ntp-amps-8918-8835-v3-1-e2459a8191a6@salutedevices.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index f82a7042a761..dc2113dcd499 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -776,6 +776,8 @@ patternProperties: description: National Semiconductor "^nec,.*": description: NEC LCD Technologies, Ltd. + "^neofidelity,.*": + description: Neofidelity Inc. "^neonode,.*": description: Neonode Inc. "^netgear,.*": From 3570899506b3ac175b450084eba38859d8419cac Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:29:59 +0100 Subject: [PATCH 002/256] ASoC: codecs: Add NeoFidelity Firmware helpers JIRA: https://issues.redhat.com/browse/RHEL-80681 commit ba1850dc0f2b5638a4a6aa16905c1856dc17587b Author: Igor Prusov Date: Wed Sep 25 17:52:40 2024 +0300 ASoC: codecs: Add NeoFidelity Firmware helpers Add support for loading firmware for NeoFidelity amplifiers. Signed-off-by: Igor Prusov Link: https://patch.msgid.link/20240925-ntp-amps-8918-8835-v3-2-e2459a8191a6@salutedevices.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 3 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/ntpfw.c | 137 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/ntpfw.h | 23 +++++++ 4 files changed, 165 insertions(+) create mode 100644 sound/soc/codecs/ntpfw.c create mode 100644 sound/soc/codecs/ntpfw.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index e826ab7417a1..0bbaac472ac6 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2492,6 +2492,9 @@ config SND_SOC_NAU8825 tristate depends on I2C +config SND_SOC_NTPFW + tristate + config SND_SOC_TPA6130A2 tristate "Texas Instruments TPA6130A2 headphone amplifier" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 00ed08f1342d..1bad2c3cf8d6 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -183,6 +183,7 @@ snd-soc-nau8821-y := nau8821.o snd-soc-nau8822-y := nau8822.o snd-soc-nau8824-y := nau8824.o snd-soc-nau8825-y := nau8825.o +snd-soc-ntpfw-y := ntpfw.o snd-soc-hdmi-codec-y := hdmi-codec.o snd-soc-pcm1681-y := pcm1681.o snd-soc-pcm1789-codec-y := pcm1789.o @@ -577,6 +578,7 @@ obj-$(CONFIG_SND_SOC_NAU8821) += snd-soc-nau8821.o obj-$(CONFIG_SND_SOC_NAU8822) += snd-soc-nau8822.o obj-$(CONFIG_SND_SOC_NAU8824) += snd-soc-nau8824.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o +obj-$(CONFIG_SND_SOC_NTPFW) += snd-soc-ntpfw.o obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM179X) += snd-soc-pcm179x-codec.o diff --git a/sound/soc/codecs/ntpfw.c b/sound/soc/codecs/ntpfw.c new file mode 100644 index 000000000000..5ced2e966ab7 --- /dev/null +++ b/sound/soc/codecs/ntpfw.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ntpfw.c - Firmware helper functions for Neofidelity codecs + * + * Copyright (c) 2024, SaluteDevices. All Rights Reserved. + */ + +#include +#include +#include + +#include "ntpfw.h" + +struct ntpfw_chunk { + __be16 length; + u8 step; + u8 data[]; +} __packed; + +struct ntpfw_header { + __be32 magic; +} __packed; + +static bool ntpfw_verify(struct device *dev, const u8 *buf, size_t buf_size, u32 magic) +{ + const struct ntpfw_header *header = (struct ntpfw_header *)buf; + u32 buf_magic; + + if (buf_size <= sizeof(*header)) { + dev_err(dev, "Failed to load firmware: image too small\n"); + return false; + } + + buf_magic = be32_to_cpu(header->magic); + if (buf_magic != magic) { + dev_err(dev, "Failed to load firmware: invalid magic 0x%x:\n", buf_magic); + return false; + } + + return true; +} + +static bool ntpfw_verify_chunk(struct device *dev, const struct ntpfw_chunk *chunk, size_t buf_size) +{ + size_t chunk_size; + + if (buf_size <= sizeof(*chunk)) { + dev_err(dev, "Failed to load firmware: chunk size too big\n"); + return false; + } + + if (chunk->step != 2 && chunk->step != 5) { + dev_err(dev, "Failed to load firmware: invalid chunk step: %d\n", chunk->step); + return false; + } + + chunk_size = be16_to_cpu(chunk->length); + if (chunk_size > buf_size) { + dev_err(dev, "Failed to load firmware: invalid chunk length\n"); + return false; + } + + if (chunk_size % chunk->step) { + dev_err(dev, "Failed to load firmware: chunk length and step mismatch\n"); + return false; + } + + return true; +} + +static int ntpfw_send_chunk(struct i2c_client *i2c, const struct ntpfw_chunk *chunk) +{ + int ret; + size_t i; + size_t length = be16_to_cpu(chunk->length); + + for (i = 0; i < length; i += chunk->step) { + ret = i2c_master_send(i2c, &chunk->data[i], chunk->step); + if (ret != chunk->step) { + dev_err(&i2c->dev, "I2C send failed: %d\n", ret); + return ret < 0 ? ret : -EIO; + } + } + + return 0; +} + +int ntpfw_load(struct i2c_client *i2c, const char *name, u32 magic) +{ + struct device *dev = &i2c->dev; + const struct ntpfw_chunk *chunk; + const struct firmware *fw; + const u8 *data; + size_t leftover; + int ret; + + ret = request_firmware(&fw, name, dev); + if (ret) { + dev_warn(dev, "request_firmware '%s' failed with %d\n", + name, ret); + return ret; + } + + if (!ntpfw_verify(dev, fw->data, fw->size, magic)) { + ret = -EINVAL; + goto done; + } + + data = fw->data + sizeof(struct ntpfw_header); + leftover = fw->size - sizeof(struct ntpfw_header); + + while (leftover) { + chunk = (struct ntpfw_chunk *)data; + + if (!ntpfw_verify_chunk(dev, chunk, leftover)) { + ret = -EINVAL; + goto done; + } + + ret = ntpfw_send_chunk(i2c, chunk); + if (ret) + goto done; + + data += be16_to_cpu(chunk->length) + sizeof(*chunk); + leftover -= be16_to_cpu(chunk->length) + sizeof(*chunk); + } + +done: + release_firmware(fw); + + return ret; +} +EXPORT_SYMBOL_GPL(ntpfw_load); + +MODULE_AUTHOR("Igor Prusov "); +MODULE_DESCRIPTION("Helper for loading Neofidelity amplifiers firmware"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ntpfw.h b/sound/soc/codecs/ntpfw.h new file mode 100644 index 000000000000..1cf10d5480ee --- /dev/null +++ b/sound/soc/codecs/ntpfw.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * ntpfw.h - Firmware helper functions for Neofidelity codecs + * + * Copyright (c) 2024, SaluteDevices. All Rights Reserved. + */ + +#ifndef __NTPFW_H__ +#define __NTPFW_H__ +#include +#include + +/** + * ntpfw_load - load firmware to amplifier over i2c interface. + * + * @i2c Pointer to amplifier's I2C client. + * @name Firmware file name. + * @magic Magic number to validate firmware. + * @return 0 or error code upon error. + */ +int ntpfw_load(struct i2c_client *i2c, const char *name, const u32 magic); + +#endif /* __NTPFW_H__ */ From 65da493e11fa744da7d3fc433f5dd05f1b3abe7b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:00 +0100 Subject: [PATCH 003/256] ASoC: codecs: Add NeoFidelity NTP8918 codec JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 2bd61fff3e93b93a20f618028433bcbe8329a6db Author: Igor Prusov Date: Wed Sep 25 17:52:42 2024 +0300 ASoC: codecs: Add NeoFidelity NTP8918 codec The NeoFidelity NTP8918 is a two channel amplifier with mixer and biquad filters. Datasheet: https://datasheetspdf.com/pdf-down/N/T/P/NTP8918-NeoFidelity.pdf Signed-off-by: Igor Prusov Link: https://patch.msgid.link/20240925-ntp-amps-8918-8835-v3-4-e2459a8191a6@salutedevices.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/ntp8918.c | 397 +++++++++++++++++++++++++++++++++++++ 3 files changed, 404 insertions(+) create mode 100644 sound/soc/codecs/ntp8918.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0bbaac472ac6..c4d62bcc5532 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2495,6 +2495,11 @@ config SND_SOC_NAU8825 config SND_SOC_NTPFW tristate +config SND_SOC_NTP8918 + select SND_SOC_NTPFW + tristate "NeoFidelity NTP8918 amplifier" + depends on I2C + config SND_SOC_TPA6130A2 tristate "Texas Instruments TPA6130A2 headphone amplifier" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 1bad2c3cf8d6..fe7d7b5fb8ae 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -183,6 +183,7 @@ snd-soc-nau8821-y := nau8821.o snd-soc-nau8822-y := nau8822.o snd-soc-nau8824-y := nau8824.o snd-soc-nau8825-y := nau8825.o +snd-soc-ntp8918-y := ntp8918.o snd-soc-ntpfw-y := ntpfw.o snd-soc-hdmi-codec-y := hdmi-codec.o snd-soc-pcm1681-y := pcm1681.o @@ -578,6 +579,7 @@ obj-$(CONFIG_SND_SOC_NAU8821) += snd-soc-nau8821.o obj-$(CONFIG_SND_SOC_NAU8822) += snd-soc-nau8822.o obj-$(CONFIG_SND_SOC_NAU8824) += snd-soc-nau8824.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o +obj-$(CONFIG_SND_SOC_NTP8918) += snd-soc-ntp8918.o obj-$(CONFIG_SND_SOC_NTPFW) += snd-soc-ntpfw.o obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o diff --git a/sound/soc/codecs/ntp8918.c b/sound/soc/codecs/ntp8918.c new file mode 100644 index 000000000000..0493ab6acbe4 --- /dev/null +++ b/sound/soc/codecs/ntp8918.c @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for the NTP8918 Audio Amplifier + * + * Copyright (c) 2024, SaluteDevices. All Rights Reserved. + * + * Author: Igor Prusov + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ntpfw.h" + +#define NTP8918_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) + +#define NTP8918_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define NTP8918_INPUT_FMT 0x0 +#define NTP8918_INPUT_FMT_MASTER_MODE BIT(0) +#define NTP8918_INPUT_FMT_GSA_MODE BIT(1) +#define NTP8918_GSA_FMT 0x1 +#define NTP8918_GSA_BS_MASK GENMASK(3, 2) +#define NTP8918_GSA_BS(x) ((x) << 2) +#define NTP8918_GSA_RIGHT_J BIT(0) +#define NTP8918_GSA_LSB BIT(1) +#define NTP8918_MCLK_FREQ_CTRL 0x2 +#define NTP8918_MCLK_FREQ_MCF GENMASK(1, 0) +#define NTP8918_MASTER_VOL 0x0C +#define NTP8918_CHNL_A_VOL 0x17 +#define NTP8918_CHNL_B_VOL 0x18 +#define NTP8918_SOFT_MUTE 0x33 +#define NTP8918_SOFT_MUTE_SM1 BIT(0) +#define NTP8918_SOFT_MUTE_SM2 BIT(1) +#define NTP8918_PWM_SWITCH 0x34 +#define NTP8918_PWM_MASK_CTRL0 0x35 +#define REG_MAX NTP8918_PWM_MASK_CTRL0 + +#define NTP8918_FW_NAME "eq_8918.bin" +#define NTP8918_FW_MAGIC 0x38393138 /* "8918" */ + +struct ntp8918_priv { + struct i2c_client *i2c; + struct clk *bck; + struct reset_control *reset; + unsigned int format; +}; + +static const DECLARE_TLV_DB_SCALE(ntp8918_master_vol_scale, -12550, 50, 0); + +static const struct snd_kcontrol_new ntp8918_vol_control[] = { + SOC_SINGLE_RANGE_TLV("Playback Volume", NTP8918_MASTER_VOL, 0, + 0x04, 0xff, 0, ntp8918_master_vol_scale), + SOC_SINGLE("Playback Switch", NTP8918_PWM_MASK_CTRL0, 1, 1, 1), +}; + +static void ntp8918_reset_gpio(struct ntp8918_priv *ntp8918) +{ + /* + * Proper initialization sequence for NTP8918 amplifier requires driving + * /RESET signal low during power up for at least 0.1us. The sequence is, + * according to NTP8918 datasheet, 6.2 Timing Sequence 1: + * Deassert for T2 >= 1ms... + */ + reset_control_deassert(ntp8918->reset); + fsleep(1000); + + /* ...Assert for T3 >= 0.1us... */ + reset_control_assert(ntp8918->reset); + fsleep(1); + + /* ...Deassert, and wait for T4 >= 0.5ms before sound on sequence. */ + reset_control_deassert(ntp8918->reset); + fsleep(500); +} + +static const struct reg_sequence ntp8918_sound_off[] = { + { NTP8918_MASTER_VOL, 0 }, +}; + +static const struct reg_sequence ntp8918_sound_on[] = { + { NTP8918_MASTER_VOL, 0b11 }, +}; + +static int ntp8918_load_firmware(struct ntp8918_priv *ntp8918) +{ + int ret; + + ret = ntpfw_load(ntp8918->i2c, NTP8918_FW_NAME, NTP8918_FW_MAGIC); + if (ret == -ENOENT) { + dev_warn_once(&ntp8918->i2c->dev, "Could not find firmware %s\n", + NTP8918_FW_NAME); + return 0; + } + + return ret; +} + +static int ntp8918_snd_suspend(struct snd_soc_component *component) +{ + struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(component->regmap, true); + + regmap_multi_reg_write_bypassed(component->regmap, + ntp8918_sound_off, + ARRAY_SIZE(ntp8918_sound_off)); + + /* + * According to NTP8918 datasheet, 6.2 Timing Sequence 1: + * wait after sound off for T6 >= 0.5ms + */ + fsleep(500); + reset_control_assert(ntp8918->reset); + + regcache_mark_dirty(component->regmap); + clk_disable_unprepare(ntp8918->bck); + + return 0; +} + +static int ntp8918_snd_resume(struct snd_soc_component *component) +{ + struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component); + int ret; + + ret = clk_prepare_enable(ntp8918->bck); + if (ret) + return ret; + + ntp8918_reset_gpio(ntp8918); + + regmap_multi_reg_write_bypassed(component->regmap, + ntp8918_sound_on, + ARRAY_SIZE(ntp8918_sound_on)); + + ret = ntp8918_load_firmware(ntp8918); + if (ret) { + dev_err(&ntp8918->i2c->dev, "Failed to load firmware\n"); + return ret; + } + + regcache_cache_only(component->regmap, false); + snd_soc_component_cache_sync(component); + + return 0; +} + +static int ntp8918_probe(struct snd_soc_component *component) +{ + int ret; + struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component); + struct device *dev = component->dev; + + ret = snd_soc_add_component_controls(component, ntp8918_vol_control, + ARRAY_SIZE(ntp8918_vol_control)); + if (ret) + return dev_err_probe(dev, ret, "Failed to add controls\n"); + + ret = ntp8918_load_firmware(ntp8918); + if (ret) + return dev_err_probe(dev, ret, "Failed to load firmware\n"); + + return 0; +} + +static const struct snd_soc_dapm_widget ntp8918_dapm_widgets[] = { + SND_SOC_DAPM_DAC("AIFIN", "Playback", SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_OUTPUT("OUT1"), + SND_SOC_DAPM_OUTPUT("OUT2"), +}; + +static const struct snd_soc_dapm_route ntp8918_dapm_routes[] = { + { "OUT1", NULL, "AIFIN" }, + { "OUT2", NULL, "AIFIN" }, +}; + +static const struct snd_soc_component_driver soc_component_ntp8918 = { + .probe = ntp8918_probe, + .suspend = ntp8918_snd_suspend, + .resume = ntp8918_snd_resume, + .dapm_widgets = ntp8918_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ntp8918_dapm_widgets), + .dapm_routes = ntp8918_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ntp8918_dapm_routes), +}; + +static int ntp8918_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component); + unsigned int input_fmt = 0; + unsigned int gsa_fmt = 0; + unsigned int gsa_fmt_mask; + unsigned int mcf; + int bclk; + int ret; + + bclk = snd_soc_params_to_bclk(params); + switch (bclk) { + case 3072000: + case 2822400: + mcf = 0; + break; + case 6144000: + mcf = 1; + break; + case 2048000: + mcf = 2; + break; + default: + return -EINVAL; + } + + ret = snd_soc_component_update_bits(component, NTP8918_MCLK_FREQ_CTRL, + NTP8918_MCLK_FREQ_MCF, mcf); + if (ret) + return ret; + + switch (ntp8918->format) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_RIGHT_J: + input_fmt |= NTP8918_INPUT_FMT_GSA_MODE; + gsa_fmt |= NTP8918_GSA_RIGHT_J; + break; + case SND_SOC_DAIFMT_LEFT_J: + input_fmt |= NTP8918_INPUT_FMT_GSA_MODE; + break; + } + + ret = snd_soc_component_update_bits(component, NTP8918_INPUT_FMT, + NTP8918_INPUT_FMT_MASTER_MODE | + NTP8918_INPUT_FMT_GSA_MODE, + input_fmt); + + if (!(input_fmt & NTP8918_INPUT_FMT_GSA_MODE) || ret < 0) + return ret; + + switch (params_width(params)) { + case 24: + gsa_fmt |= NTP8918_GSA_BS(0); + break; + case 20: + gsa_fmt |= NTP8918_GSA_BS(1); + break; + case 18: + gsa_fmt |= NTP8918_GSA_BS(2); + break; + case 16: + gsa_fmt |= NTP8918_GSA_BS(3); + break; + default: + return -EINVAL; + } + + gsa_fmt_mask = NTP8918_GSA_BS_MASK | + NTP8918_GSA_RIGHT_J | + NTP8918_GSA_LSB; + return snd_soc_component_update_bits(component, NTP8918_GSA_FMT, + gsa_fmt_mask, gsa_fmt); +} + +static int ntp8918_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component); + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + ntp8918->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + break; + default: + return -EINVAL; + } + return 0; +} + +static int ntp8918_digital_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + unsigned int mute_mask = NTP8918_SOFT_MUTE_SM1 | + NTP8918_SOFT_MUTE_SM2; + + return snd_soc_component_update_bits(dai->component, NTP8918_SOFT_MUTE, + mute_mask, mute ? mute_mask : 0); +} + +static const struct snd_soc_dai_ops ntp8918_dai_ops = { + .hw_params = ntp8918_hw_params, + .set_fmt = ntp8918_set_fmt, + .mute_stream = ntp8918_digital_mute, +}; + +static struct snd_soc_dai_driver ntp8918_dai = { + .name = "ntp8918-amplifier", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = NTP8918_RATES, + .formats = NTP8918_FORMATS, + }, + .ops = &ntp8918_dai_ops, +}; + +static const struct regmap_config ntp8918_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_MAX, + .cache_type = REGCACHE_MAPLE, +}; + +static int ntp8918_i2c_probe(struct i2c_client *i2c) +{ + struct ntp8918_priv *ntp8918; + int ret; + struct regmap *regmap; + + ntp8918 = devm_kzalloc(&i2c->dev, sizeof(*ntp8918), GFP_KERNEL); + if (!ntp8918) + return -ENOMEM; + + ntp8918->i2c = i2c; + + ntp8918->reset = devm_reset_control_get_shared(&i2c->dev, NULL); + if (IS_ERR(ntp8918->reset)) + return dev_err_probe(&i2c->dev, PTR_ERR(ntp8918->reset), "Failed to get reset\n"); + + dev_set_drvdata(&i2c->dev, ntp8918); + + ntp8918_reset_gpio(ntp8918); + + regmap = devm_regmap_init_i2c(i2c, &ntp8918_regmap); + if (IS_ERR(regmap)) + return dev_err_probe(&i2c->dev, PTR_ERR(regmap), + "Failed to allocate regmap\n"); + + ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_ntp8918, + &ntp8918_dai, 1); + if (ret) + return dev_err_probe(&i2c->dev, ret, + "Failed to register component\n"); + + ntp8918->bck = devm_clk_get_enabled(&i2c->dev, "bck"); + if (IS_ERR(ntp8918->bck)) + return dev_err_probe(&i2c->dev, PTR_ERR(ntp8918->bck), "failed to get bck clock\n"); + + return 0; +} + +static const struct i2c_device_id ntp8918_i2c_id[] = { + { "ntp8918", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ntp8918_i2c_id); + +static const struct of_device_id ntp8918_of_match[] = { + {.compatible = "neofidelity,ntp8918"}, + {} +}; +MODULE_DEVICE_TABLE(of, ntp8918_of_match); + +static struct i2c_driver ntp8918_i2c_driver = { + .probe = ntp8918_i2c_probe, + .id_table = ntp8918_i2c_id, + .driver = { + .name = "ntp8918", + .of_match_table = ntp8918_of_match, + }, +}; +module_i2c_driver(ntp8918_i2c_driver); + +MODULE_AUTHOR("Igor Prusov "); +MODULE_DESCRIPTION("NTP8918 Audio Amplifier Driver"); +MODULE_LICENSE("GPL"); From 55120fb6745af9233588e0b0fc6af3a879237b2e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:00 +0100 Subject: [PATCH 004/256] ASoC: dt-bindings: Add NeoFidelity NTP8918 JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 64fbb6bdd45b8953fcad5c4ec648f74c96aec5f3 Author: Igor Prusov Date: Wed Sep 25 17:52:41 2024 +0300 ASoC: dt-bindings: Add NeoFidelity NTP8918 Add dt-bindings for NeoFidelity NTP8918 Amplifier Signed-off-by: Igor Prusov Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20240925-ntp-amps-8918-8835-v3-3-e2459a8191a6@salutedevices.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- .../bindings/sound/neofidelity,ntp8918.yaml | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/neofidelity,ntp8918.yaml diff --git a/Documentation/devicetree/bindings/sound/neofidelity,ntp8918.yaml b/Documentation/devicetree/bindings/sound/neofidelity,ntp8918.yaml new file mode 100644 index 000000000000..952768b35902 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/neofidelity,ntp8918.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/neofidelity,ntp8918.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NeoFidelity NTP8918 Amplifier + +maintainers: + - Igor Prusov + +description: + The NTP8918 is a single chip full digital audio amplifier + including power stage for stereo amplifier system. + The NTP8918 is integrated with versatile digital audio signal + processing functions, high-performance, high-fidelity fully + digital PWM modulator and two high-power full-bridge MOSFET + power stages. + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - neofidelity,ntp8918 + + reg: + enum: + - 0x2a + - 0x2b + - 0x2c + - 0x2d + + reset-gpios: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + + clocks: + maxItems: 3 + + clock-names: + items: + - const: wck + - const: scl + - const: bck + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + audio-codec@2a { + compatible = "neofidelity,ntp8918"; + #sound-dai-cells = <0>; + reg = <0x2a>; + clocks = <&clkc 150>, <&clkc 151>, <&clkc 152>; + clock-names = "wck", "scl", "bck"; + reset-gpios = <&gpio 5 GPIO_ACTIVE_LOW>; + }; + }; From 214b69bd1249b7c667077a157d8d6750732fd272 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:00 +0100 Subject: [PATCH 005/256] ASoC: dt-bindings: Add NeoFidelity NTP8835 JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 3e2aba5f0b0cafad44c2f635dc19d7bf3f54b978 Author: Igor Prusov Date: Wed Sep 25 17:52:43 2024 +0300 ASoC: dt-bindings: Add NeoFidelity NTP8835 Add dt-bindings for NeoFidelity NTP8835C/NTP8835C Amplifiers Signed-off-by: Igor Prusov Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20240925-ntp-amps-8918-8835-v3-5-e2459a8191a6@salutedevices.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- .../bindings/sound/neofidelity,ntp8835.yaml | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/neofidelity,ntp8835.yaml diff --git a/Documentation/devicetree/bindings/sound/neofidelity,ntp8835.yaml b/Documentation/devicetree/bindings/sound/neofidelity,ntp8835.yaml new file mode 100644 index 000000000000..44d72a2ddfc9 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/neofidelity,ntp8835.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/neofidelity,ntp8835.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NeoFidelity NTP8835/NTP8835C Amplifiers + +maintainers: + - Igor Prusov + +description: | + The NTP8835 is a single chip full digital audio amplifier + including power stages for stereo amplifier systems. + NTP8835 is integrated with versatile digital audio signal + processing functions, high-performance, high-fidelity fully + digital PWM modulator and two high-power full-bridge MOSFET + power stages. NTP8835C has identical programming interface, + but has different output signal characteristics. + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - neofidelity,ntp8835 + - neofidelity,ntp8835c + + reg: + enum: + - 0x2a + - 0x2b + - 0x2c + - 0x2d + + reset-gpios: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + + clocks: + maxItems: 4 + + clock-names: + items: + - const: wck + - const: bck + - const: scl + - const: mclk + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + audio-codec@2b { + compatible = "neofidelity,ntp8835"; + #sound-dai-cells = <0>; + reg = <0x2b>; + reset-gpios = <&gpio 5 GPIO_ACTIVE_LOW>; + clocks = <&clkc 551>, <&clkc 552>, <&clkc 553>, <&clkc 554>; + clock-names = "wck", "bck", "scl", "mclk"; + }; + }; From 3b2028a7ce5b2be449e13a6428fb335f1d1fae29 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:00 +0100 Subject: [PATCH 006/256] ASoC: codecs: Add NeoFidelity NTP8835 codec JIRA: https://issues.redhat.com/browse/RHEL-80681 commit dc9004ea273a9141c16b90a687da70b77f5a640a Author: Igor Prusov Date: Wed Sep 25 17:52:44 2024 +0300 ASoC: codecs: Add NeoFidelity NTP8835 codec The NeoFidelity NTP8835 adn NTP8835C are 2.1 channel amplifiers with mixer and biquad filters. Both amplifiers have identical programming interfaces but differ in output signal characteristics. Datasheet: https://www.cpbay.com/Uploads/20210225/6037116a3ea91.pdf Datasheet: https://www.cpbay.com/Uploads/20210918/61458b2f2631e.pdf Signed-off-by: Igor Prusov Link: https://patch.msgid.link/20240925-ntp-amps-8918-8835-v3-6-e2459a8191a6@salutedevices.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/ntp8835.c | 480 +++++++++++++++++++++++++++++++++++++ 3 files changed, 487 insertions(+) create mode 100644 sound/soc/codecs/ntp8835.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index c4d62bcc5532..ffbed0a4f096 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2500,6 +2500,11 @@ config SND_SOC_NTP8918 tristate "NeoFidelity NTP8918 amplifier" depends on I2C +config SND_SOC_NTP8835 + select SND_SOC_NTPFW + tristate "NeoFidelity NTP8835 and NTP8835C amplifiers" + depends on I2C + config SND_SOC_TPA6130A2 tristate "Texas Instruments TPA6130A2 headphone amplifier" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index fe7d7b5fb8ae..91f5dd1173f2 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -183,6 +183,7 @@ snd-soc-nau8821-y := nau8821.o snd-soc-nau8822-y := nau8822.o snd-soc-nau8824-y := nau8824.o snd-soc-nau8825-y := nau8825.o +snd-soc-ntp8835-y := ntp8835.o snd-soc-ntp8918-y := ntp8918.o snd-soc-ntpfw-y := ntpfw.o snd-soc-hdmi-codec-y := hdmi-codec.o @@ -579,6 +580,7 @@ obj-$(CONFIG_SND_SOC_NAU8821) += snd-soc-nau8821.o obj-$(CONFIG_SND_SOC_NAU8822) += snd-soc-nau8822.o obj-$(CONFIG_SND_SOC_NAU8824) += snd-soc-nau8824.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o +obj-$(CONFIG_SND_SOC_NTP8835) += snd-soc-ntp8835.o obj-$(CONFIG_SND_SOC_NTP8918) += snd-soc-ntp8918.o obj-$(CONFIG_SND_SOC_NTPFW) += snd-soc-ntpfw.o obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o diff --git a/sound/soc/codecs/ntp8835.c b/sound/soc/codecs/ntp8835.c new file mode 100644 index 000000000000..97056d8de2bb --- /dev/null +++ b/sound/soc/codecs/ntp8835.c @@ -0,0 +1,480 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for the NTP8835/NTP8835C Audio Amplifiers + * + * Copyright (c) 2024, SaluteDevices. All Rights Reserved. + * + * Author: Igor Prusov + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ntpfw.h" + +#define NTP8835_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define NTP8835_INPUT_FMT 0x0 +#define NTP8835_INPUT_FMT_MASTER_MODE BIT(0) +#define NTP8835_INPUT_FMT_GSA_MODE BIT(1) +#define NTP8835_GSA_FMT 0x1 +#define NTP8835_GSA_BS_MASK GENMASK(3, 2) +#define NTP8835_GSA_BS(x) ((x) << 2) +#define NTP8835_GSA_RIGHT_J BIT(0) +#define NTP8835_GSA_LSB BIT(1) +#define NTP8835_MCLK_FREQ_CTRL 0x2 +#define NTP8835_MCLK_FREQ_MCF GENMASK(1, 0) +#define NTP8835_SOFT_MUTE 0x26 +#define NTP8835_SOFT_MUTE_SM1 BIT(0) +#define NTP8835_SOFT_MUTE_SM2 BIT(1) +#define NTP8835_SOFT_MUTE_SM3 BIT(2) +#define NTP8835_PWM_SWITCH 0x27 +#define NTP8835_PWM_SWITCH_POF1 BIT(0) +#define NTP8835_PWM_SWITCH_POF2 BIT(1) +#define NTP8835_PWM_SWITCH_POF3 BIT(2) +#define NTP8835_PWM_MASK_CTRL0 0x28 +#define NTP8835_PWM_MASK_CTRL0_OUT_LOW BIT(1) +#define NTP8835_PWM_MASK_CTRL0_FPMLD BIT(2) +#define NTP8835_MASTER_VOL 0x2e +#define NTP8835_CHNL_A_VOL 0x2f +#define NTP8835_CHNL_B_VOL 0x30 +#define NTP8835_CHNL_C_VOL 0x31 +#define REG_MAX NTP8835_CHNL_C_VOL + +#define NTP8835_FW_NAME "eq_8835.bin" +#define NTP8835_FW_MAGIC 0x38383335 /* "8835" */ + +struct ntp8835_priv { + struct i2c_client *i2c; + struct reset_control *reset; + unsigned int format; + struct clk *mclk; + unsigned int mclk_rate; +}; + +static const DECLARE_TLV_DB_RANGE(ntp8835_vol_scale, + 0, 1, TLV_DB_SCALE_ITEM(-15000, 0, 0), + 2, 6, TLV_DB_SCALE_ITEM(-15000, 1000, 0), + 7, 0xff, TLV_DB_SCALE_ITEM(-10000, 50, 0), +); + +static int ntp8835_mute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->access = + (SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE); + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + uinfo->value.integer.step = 1; + + return 0; +} + +static int ntp8835_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + unsigned int val; + + val = snd_soc_component_read(component, NTP8835_SOFT_MUTE); + + ucontrol->value.integer.value[0] = val ? 0 : 1; + return 0; +} + +static int ntp8835_mute_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + unsigned int val; + + val = ucontrol->value.integer.value[0] ? 0 : 7; + + snd_soc_component_write(component, NTP8835_SOFT_MUTE, val); + + return 0; +} + +static const struct snd_kcontrol_new ntp8835_vol_control[] = { + SOC_SINGLE_TLV("Playback Volume", NTP8835_MASTER_VOL, 0, + 0xff, 0, ntp8835_vol_scale), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Playback Switch", + .info = ntp8835_mute_info, + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE, + .get = ntp8835_mute_get, + .put = ntp8835_mute_put, + }, +}; + +static void ntp8835_reset_gpio(struct ntp8835_priv *ntp8835) +{ + /* + * Proper initialization sequence for NTP835 amplifier requires driving + * /RESET signal low during power up for at least 0.1us. The sequence is, + * according to NTP8835 datasheet, 6.2 Timing Sequence (recommended): + * Deassert for T2 >= 1ms... + */ + reset_control_deassert(ntp8835->reset); + fsleep(1000); + + /* ...Assert for T3 >= 0.1us... */ + reset_control_assert(ntp8835->reset); + fsleep(1); + + /* ...Deassert, and wait for T4 >= 0.5ms before sound on sequence. */ + reset_control_deassert(ntp8835->reset); + fsleep(500); +} + +static const struct reg_sequence ntp8835_sound_on[] = { + { NTP8835_PWM_MASK_CTRL0, NTP8835_PWM_MASK_CTRL0_FPMLD }, + { NTP8835_PWM_SWITCH, 0x00 }, + { NTP8835_SOFT_MUTE, 0x00 }, +}; + +static const struct reg_sequence ntp8835_sound_off[] = { + { NTP8835_SOFT_MUTE, NTP8835_SOFT_MUTE_SM1 | + NTP8835_SOFT_MUTE_SM2 | + NTP8835_SOFT_MUTE_SM3 }, + + { NTP8835_PWM_SWITCH, NTP8835_PWM_SWITCH_POF1 | + NTP8835_PWM_SWITCH_POF2 | + NTP8835_PWM_SWITCH_POF3 }, + + { NTP8835_PWM_MASK_CTRL0, NTP8835_PWM_MASK_CTRL0_OUT_LOW | + NTP8835_PWM_MASK_CTRL0_FPMLD }, +}; + +static int ntp8835_load_firmware(struct ntp8835_priv *ntp8835) +{ + int ret; + + ret = ntpfw_load(ntp8835->i2c, NTP8835_FW_NAME, NTP8835_FW_MAGIC); + if (ret == -ENOENT) { + dev_warn_once(&ntp8835->i2c->dev, + "Could not find firmware %s\n", NTP8835_FW_NAME); + return 0; + } + + return ret; +} + +static int ntp8835_snd_suspend(struct snd_soc_component *component) +{ + struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(component->regmap, true); + + regmap_multi_reg_write_bypassed(component->regmap, + ntp8835_sound_off, + ARRAY_SIZE(ntp8835_sound_off)); + + /* + * According to NTP8835 datasheet, 6.2 Timing Sequence (recommended): + * wait after sound off for T6 >= 0.5ms + */ + fsleep(500); + reset_control_assert(ntp8835->reset); + + regcache_mark_dirty(component->regmap); + clk_disable_unprepare(ntp8835->mclk); + + return 0; +} + +static int ntp8835_snd_resume(struct snd_soc_component *component) +{ + struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component); + int ret; + + ntp8835_reset_gpio(ntp8835); + ret = clk_prepare_enable(ntp8835->mclk); + if (ret) + return ret; + + regmap_multi_reg_write_bypassed(component->regmap, + ntp8835_sound_on, + ARRAY_SIZE(ntp8835_sound_on)); + + ret = ntp8835_load_firmware(ntp8835); + if (ret) { + dev_err(&ntp8835->i2c->dev, "Failed to load firmware\n"); + return ret; + } + + regcache_cache_only(component->regmap, false); + snd_soc_component_cache_sync(component); + + return 0; +} + +static int ntp8835_probe(struct snd_soc_component *component) +{ + int ret; + struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component); + struct device *dev = component->dev; + + ret = snd_soc_add_component_controls(component, ntp8835_vol_control, + ARRAY_SIZE(ntp8835_vol_control)); + if (ret) + return dev_err_probe(dev, ret, "Failed to add controls\n"); + + ret = ntp8835_load_firmware(ntp8835); + if (ret) + return dev_err_probe(dev, ret, "Failed to load firmware\n"); + + return 0; +} + +static const struct snd_soc_dapm_widget ntp8835_dapm_widgets[] = { + SND_SOC_DAPM_DAC("AIFIN", "Playback", SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_OUTPUT("OUT1"), + SND_SOC_DAPM_OUTPUT("OUT2"), + SND_SOC_DAPM_OUTPUT("OUT3"), +}; + +static const struct snd_soc_dapm_route ntp8835_dapm_routes[] = { + { "OUT1", NULL, "AIFIN" }, + { "OUT2", NULL, "AIFIN" }, + { "OUT3", NULL, "AIFIN" }, +}; + +static int ntp8835_set_component_sysclk(struct snd_soc_component *component, + int clk_id, int source, + unsigned int freq, int dir) +{ + struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component); + + switch (freq) { + case 12288000: + case 24576000: + case 18432000: + ntp8835->mclk_rate = freq; + break; + default: + ntp8835->mclk_rate = 0; + dev_err(component->dev, "Unsupported MCLK value: %u", freq); + return -EINVAL; + }; + + return 0; +} + +static const struct snd_soc_component_driver soc_component_ntp8835 = { + .probe = ntp8835_probe, + .suspend = ntp8835_snd_suspend, + .resume = ntp8835_snd_resume, + .dapm_widgets = ntp8835_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ntp8835_dapm_widgets), + .dapm_routes = ntp8835_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ntp8835_dapm_routes), + .set_sysclk = ntp8835_set_component_sysclk, +}; + +static int ntp8835_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component); + unsigned int input_fmt = 0; + unsigned int gsa_fmt = 0; + unsigned int gsa_fmt_mask; + unsigned int mcf; + int ret; + + switch (ntp8835->mclk_rate) { + case 12288000: + mcf = 0; + break; + case 24576000: + mcf = 1; + break; + case 18432000: + mcf = 2; + break; + default: + return -EINVAL; + } + + ret = snd_soc_component_update_bits(component, NTP8835_MCLK_FREQ_CTRL, + NTP8835_MCLK_FREQ_MCF, mcf); + if (ret) + return ret; + + switch (ntp8835->format) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_RIGHT_J: + input_fmt |= NTP8835_INPUT_FMT_GSA_MODE; + gsa_fmt |= NTP8835_GSA_RIGHT_J; + break; + case SND_SOC_DAIFMT_LEFT_J: + input_fmt |= NTP8835_INPUT_FMT_GSA_MODE; + break; + } + + ret = snd_soc_component_update_bits(component, NTP8835_INPUT_FMT, + NTP8835_INPUT_FMT_MASTER_MODE | + NTP8835_INPUT_FMT_GSA_MODE, + input_fmt); + + if (!(input_fmt & NTP8835_INPUT_FMT_GSA_MODE) || ret < 0) + return ret; + + switch (params_width(params)) { + case 24: + gsa_fmt |= NTP8835_GSA_BS(0); + break; + case 20: + gsa_fmt |= NTP8835_GSA_BS(1); + break; + case 18: + gsa_fmt |= NTP8835_GSA_BS(2); + break; + case 16: + gsa_fmt |= NTP8835_GSA_BS(3); + break; + default: + return -EINVAL; + } + + gsa_fmt_mask = NTP8835_GSA_BS_MASK | + NTP8835_GSA_RIGHT_J | + NTP8835_GSA_LSB; + return snd_soc_component_update_bits(component, NTP8835_GSA_FMT, + gsa_fmt_mask, gsa_fmt); +} + +static int ntp8835_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component); + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + ntp8835->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + break; + default: + return -EINVAL; + } + return 0; +}; + +static const struct snd_soc_dai_ops ntp8835_dai_ops = { + .hw_params = ntp8835_hw_params, + .set_fmt = ntp8835_set_fmt, +}; + +static struct snd_soc_dai_driver ntp8835_dai = { + .name = "ntp8835-amplifier", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 3, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = NTP8835_FORMATS, + }, + .ops = &ntp8835_dai_ops, +}; + +static const struct regmap_config ntp8835_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_MAX, + .cache_type = REGCACHE_MAPLE, +}; + +static int ntp8835_i2c_probe(struct i2c_client *i2c) +{ + struct ntp8835_priv *ntp8835; + struct regmap *regmap; + int ret; + + ntp8835 = devm_kzalloc(&i2c->dev, sizeof(*ntp8835), GFP_KERNEL); + if (!ntp8835) + return -ENOMEM; + + ntp8835->i2c = i2c; + + ntp8835->reset = devm_reset_control_get_shared(&i2c->dev, NULL); + if (IS_ERR(ntp8835->reset)) + return dev_err_probe(&i2c->dev, PTR_ERR(ntp8835->reset), + "Failed to get reset\n"); + + ret = reset_control_deassert(ntp8835->reset); + if (ret) + return dev_err_probe(&i2c->dev, PTR_ERR(ntp8835->reset), + "Failed to deassert reset\n"); + + dev_set_drvdata(&i2c->dev, ntp8835); + + ntp8835_reset_gpio(ntp8835); + + regmap = devm_regmap_init_i2c(i2c, &ntp8835_regmap); + if (IS_ERR(regmap)) + return dev_err_probe(&i2c->dev, PTR_ERR(regmap), + "Failed to allocate regmap\n"); + + ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_ntp8835, + &ntp8835_dai, 1); + if (ret) + return dev_err_probe(&i2c->dev, ret, + "Failed to register component\n"); + + ntp8835->mclk = devm_clk_get_enabled(&i2c->dev, "mclk"); + if (IS_ERR(ntp8835->mclk)) + return dev_err_probe(&i2c->dev, PTR_ERR(ntp8835->mclk), "failed to get mclk\n"); + + return 0; +} + +static const struct i2c_device_id ntp8835_i2c_id[] = { + { "ntp8835", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ntp8835_i2c_id); + +static const struct of_device_id ntp8835_of_match[] = { + {.compatible = "neofidelity,ntp8835",}, + {} +}; +MODULE_DEVICE_TABLE(of, ntp8835_of_match); + +static struct i2c_driver ntp8835_i2c_driver = { + .probe = ntp8835_i2c_probe, + .id_table = ntp8835_i2c_id, + .driver = { + .name = "ntp8835", + .of_match_table = ntp8835_of_match, + }, +}; +module_i2c_driver(ntp8835_i2c_driver); + +MODULE_AUTHOR("Igor Prusov "); +MODULE_DESCRIPTION("NTP8835 Audio Amplifier Driver"); +MODULE_LICENSE("GPL"); From de4a51f7dff6e99d22b87aa9dce737dcd801b14f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:01 +0100 Subject: [PATCH 007/256] ASoC: atmel: atmel_ssc_dai: Add stream names JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 879c9151572317e8ddb6ab6c57a7689bf580efc9 Author: Codrin Ciubotariu Date: Mon Sep 16 16:19:09 2024 +0300 ASoC: atmel: atmel_ssc_dai: Add stream names Add required stream names for DPCM and future use-cases. [andrei.simion@microchip.com: Adjust commit title. Reword commit message.] Reviewed-by: Alexandre Belloni Signed-off-by: Codrin Ciubotariu Signed-off-by: Andrei Simion Link: https://patch.msgid.link/20240916131910.22680-2-andrei.simion@microchip.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/atmel/atmel_ssc_dai.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 3763454436c1..7047f17fe7a8 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -836,6 +836,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = { static struct snd_soc_dai_driver atmel_ssc_dai = { .playback = { + .stream_name = "Playback", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_CONTINUOUS, @@ -843,6 +844,7 @@ static struct snd_soc_dai_driver atmel_ssc_dai = { .rate_max = 384000, .formats = ATMEL_SSC_FORMATS,}, .capture = { + .stream_name = "Capture", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_CONTINUOUS, From aa6a5945bb08b5b1f4fc47b4dd43ec2d1fd91c40 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:01 +0100 Subject: [PATCH 008/256] ASoC: atmel: atmel_ssc_dai: Drop S24_LE support due to single channel limitation JIRA: https://issues.redhat.com/browse/RHEL-80681 commit ac8775d7de5a8ccac225a398cbce9fb9fffdbb9f Author: Codrin Ciubotariu Date: Mon Sep 16 16:19:10 2024 +0300 ASoC: atmel: atmel_ssc_dai: Drop S24_LE support due to single channel limitation Drop S24_LE format because it is not supported if more than 2 channels (of TDM slots) are used. This limitation makes it impractical for use cases requiring more than 2 TDM slots, leading to potential issues in multi-channel configurations. [andrei.simion@microchip.com: Reword the commit title and the commit message. Add code comment to explain the removed code.] Signed-off-by: Codrin Ciubotariu Signed-off-by: Andrei Simion Reviewed-by: Alexandre Belloni Link: https://patch.msgid.link/20240916131910.22680-3-andrei.simion@microchip.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/atmel/atmel_ssc_dai.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 7047f17fe7a8..89098f41679c 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -821,8 +821,9 @@ static int atmel_ssc_resume(struct snd_soc_component *component) return 0; } +/* S24_LE is not supported if more than 2 channels (of TDM slots) are used. */ #define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + SNDRV_PCM_FMTBIT_S32_LE) static const struct snd_soc_dai_ops atmel_ssc_dai_ops = { .startup = atmel_ssc_startup, From b6605892cf3a7d62dd4417cddac5dc8ed086ffa0 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:01 +0100 Subject: [PATCH 009/256] ASoC: atmel: mchp-spdifrx: Remove interface name from stream_name JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 3c44a715e389929b8243d6a0545992d78cff6cba Author: Codrin Ciubotariu Date: Mon Sep 16 12:10:57 2024 +0300 ASoC: atmel: mchp-spdifrx: Remove interface name from stream_name Remove the interface name from the stream_name. The interface name (and the index of the interface) can be set in DT using the sound-name-prefix string property. [andrei.simion@microchip.com: Adjust the commit title.] Signed-off-by: Codrin Ciubotariu Signed-off-by: Andrei Simion Link: https://patch.msgid.link/20240916091056.11910-3-andrei.simion@microchip.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/atmel/mchp-spdifrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c index ec0705cc40fa..c898f27477e7 100644 --- a/sound/soc/atmel/mchp-spdifrx.c +++ b/sound/soc/atmel/mchp-spdifrx.c @@ -839,7 +839,7 @@ static struct snd_soc_dai_driver mchp_spdifrx_dai = { .probe = mchp_spdifrx_dai_probe, .remove = mchp_spdifrx_dai_remove, .capture = { - .stream_name = "S/PDIF Capture", + .stream_name = "Capture", .channels_min = SPDIFRX_CHANNELS, .channels_max = SPDIFRX_CHANNELS, .rates = MCHP_SPDIF_RATES, From 153c935363d602d9d4132c5ad29f93a2179651eb Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:01 +0100 Subject: [PATCH 010/256] ASoC: atmel: mchp-spdiftx: Remove interface name from stream_name JIRA: https://issues.redhat.com/browse/RHEL-80681 commit a6ae5845f0231fb1b3e9bf591b237d99d1a077c0 Author: Codrin Ciubotariu Date: Mon Sep 16 12:10:56 2024 +0300 ASoC: atmel: mchp-spdiftx: Remove interface name from stream_name Remove the interface name from the stream_name. The interface name (and the index of the interface) can be set in DT using the sound-name-prefix string property. [andrei.simion@microchip.com: Adjust the commit title.] Signed-off-by: Codrin Ciubotariu Signed-off-by: Andrei Simion Link: https://patch.msgid.link/20240916091056.11910-2-andrei.simion@microchip.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/atmel/mchp-spdiftx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c index ab2d7a791f39..9ce91651d425 100644 --- a/sound/soc/atmel/mchp-spdiftx.c +++ b/sound/soc/atmel/mchp-spdiftx.c @@ -740,7 +740,7 @@ static struct snd_soc_dai_driver mchp_spdiftx_dai = { .probe = mchp_spdiftx_dai_probe, .remove = mchp_spdiftx_dai_remove, .playback = { - .stream_name = "S/PDIF Playback", + .stream_name = "Playback", .channels_min = 1, .channels_max = 2, .rates = MCHP_SPDIFTX_RATES, From 69d0301600b25cd0d034fe363d506f8368e07199 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:02 +0100 Subject: [PATCH 011/256] ASoC: improve macro definition on TWL4030_OUTPUT_PGA JIRA: https://issues.redhat.com/browse/RHEL-80681 commit ac9fc25f114aec07e7f5348606c9702f8377f44a Author: Hongbo Li Date: Wed Aug 21 15:08:11 2024 +0800 ASoC: improve macro definition on TWL4030_OUTPUT_PGA The @mask is not used in TWL4030_OUTPUT_PGA, so we can remove it and simplify its usage. Signed-off-by: Hongbo Li Link: https://patch.msgid.link/20240821070815.2326534-2-lihongbo22@huawei.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/twl4030.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 9c50ac356c89..e3782762139f 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -555,7 +555,7 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control = * On unmute: restore the register content from the reg_cache * Outputs handled in this way: Earpiece, PreDrivL/R, CarkitL/R */ -#define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \ +#define TWL4030_OUTPUT_PGA(pin_name, reg) \ static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ struct snd_kcontrol *kcontrol, int event) \ { \ @@ -575,11 +575,11 @@ static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ return 0; \ } -TWL4030_OUTPUT_PGA(earpiece, TWL4030_REG_EAR_CTL, TWL4030_EAR_GAIN); -TWL4030_OUTPUT_PGA(predrivel, TWL4030_REG_PREDL_CTL, TWL4030_PREDL_GAIN); -TWL4030_OUTPUT_PGA(predriver, TWL4030_REG_PREDR_CTL, TWL4030_PREDR_GAIN); -TWL4030_OUTPUT_PGA(carkitl, TWL4030_REG_PRECKL_CTL, TWL4030_PRECKL_GAIN); -TWL4030_OUTPUT_PGA(carkitr, TWL4030_REG_PRECKR_CTL, TWL4030_PRECKR_GAIN); +TWL4030_OUTPUT_PGA(earpiece, TWL4030_REG_EAR_CTL); +TWL4030_OUTPUT_PGA(predrivel, TWL4030_REG_PREDL_CTL); +TWL4030_OUTPUT_PGA(predriver, TWL4030_REG_PREDR_CTL); +TWL4030_OUTPUT_PGA(carkitl, TWL4030_REG_PRECKL_CTL); +TWL4030_OUTPUT_PGA(carkitr, TWL4030_REG_PRECKR_CTL); static void handsfree_ramp(struct snd_soc_component *component, int reg, int ramp) { From cdcbc9a1d7befabaf5de1b80cd27a4f7816c2024 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:02 +0100 Subject: [PATCH 012/256] ASoC: remove unused substream in macro soc_component_mark_pop JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 5687851e484bdb22fa565578e0b046a50d502941 Author: Hongbo Li Date: Wed Aug 21 15:08:12 2024 +0800 ASoC: remove unused substream in macro soc_component_mark_pop The soc_component_mark_pop don't need substream, and also substream is not used in this macro, so we can remove it. This is detected by macro_checker.py script. Signed-off-by: Hongbo Li Link: https://patch.msgid.link/20240821070815.2326534-3-lihongbo22@huawei.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/soc-component.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index b3d7bb91e294..b67ef78f405c 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -58,7 +58,7 @@ static inline int soc_component_field_shift(struct snd_soc_component *component, * In such case, we can update these macros. */ #define soc_component_mark_push(component, substream, tgt) ((component)->mark_##tgt = substream) -#define soc_component_mark_pop(component, substream, tgt) ((component)->mark_##tgt = NULL) +#define soc_component_mark_pop(component, tgt) ((component)->mark_##tgt = NULL) #define soc_component_mark_match(component, substream, tgt) ((component)->mark_##tgt == substream) void snd_soc_component_set_aux(struct snd_soc_component *component, @@ -339,7 +339,7 @@ void snd_soc_component_module_put(struct snd_soc_component *component, module_put(component->dev->driver->owner); /* remove the mark from module */ - soc_component_mark_pop(component, mark, module); + soc_component_mark_pop(component, module); } int snd_soc_component_open(struct snd_soc_component *component, @@ -370,7 +370,7 @@ int snd_soc_component_close(struct snd_soc_component *component, ret = component->driver->close(component, substream); /* remove marked substream */ - soc_component_mark_pop(component, substream, open); + soc_component_mark_pop(component, open); return soc_component_ret(component, ret); } @@ -515,7 +515,7 @@ void snd_soc_component_compr_free(struct snd_soc_component *component, component->driver->compress_ops->free(component, cstream); /* remove marked substream */ - soc_component_mark_pop(component, cstream, compr_open); + soc_component_mark_pop(component, compr_open); } EXPORT_SYMBOL_GPL(snd_soc_component_compr_free); @@ -1210,7 +1210,7 @@ void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, } /* remove marked substream */ - soc_component_mark_pop(component, substream, hw_params); + soc_component_mark_pop(component, hw_params); } } @@ -1254,7 +1254,7 @@ int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, r = soc_component_trigger(component, substream, cmd); if (r < 0) ret = r; /* use last ret */ - soc_component_mark_pop(component, substream, trigger); + soc_component_mark_pop(component, trigger); } } @@ -1294,7 +1294,7 @@ void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd, pm_runtime_put_autosuspend(component->dev); /* remove marked stream */ - soc_component_mark_pop(component, stream, pm); + soc_component_mark_pop(component, pm); } } From 9e3f451a73bdd3c81af4e583cf96ac0ecbac990f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:02 +0100 Subject: [PATCH 013/256] ASoC: remove unused substream in macro soc_link_mark_pop JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 2f12d0de77b99f0f35755d16efeb12e6f45e5710 Author: Hongbo Li Date: Wed Aug 21 15:08:14 2024 +0800 ASoC: remove unused substream in macro soc_link_mark_pop The soc_link_mark_pop don't need substream, therefore we can remove it. Signed-off-by: Hongbo Li Link: https://patch.msgid.link/20240821070815.2326534-5-lihongbo22@huawei.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/soc-link.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index fee4022708bc..7f1f1bc717e2 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -35,7 +35,7 @@ static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd, * In such case, we can update these macros. */ #define soc_link_mark_push(rtd, substream, tgt) ((rtd)->mark_##tgt = substream) -#define soc_link_mark_pop(rtd, substream, tgt) ((rtd)->mark_##tgt = NULL) +#define soc_link_mark_pop(rtd, tgt) ((rtd)->mark_##tgt = NULL) #define soc_link_mark_match(rtd, substream, tgt) ((rtd)->mark_##tgt == substream) int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) @@ -94,7 +94,7 @@ void snd_soc_link_shutdown(struct snd_pcm_substream *substream, rtd->dai_link->ops->shutdown(substream); /* remove marked substream */ - soc_link_mark_pop(rtd, substream, startup); + soc_link_mark_pop(rtd, startup); } int snd_soc_link_prepare(struct snd_pcm_substream *substream) @@ -138,7 +138,7 @@ void snd_soc_link_hw_free(struct snd_pcm_substream *substream, int rollback) rtd->dai_link->ops->hw_free(substream); /* remove marked substream */ - soc_link_mark_pop(rtd, substream, hw_params); + soc_link_mark_pop(rtd, hw_params); } static int soc_link_trigger(struct snd_pcm_substream *substream, int cmd) @@ -175,7 +175,7 @@ int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd, break; ret = soc_link_trigger(substream, cmd); - soc_link_mark_pop(rtd, substream, startup); + soc_link_mark_pop(rtd, startup); } return ret; @@ -209,7 +209,7 @@ void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream, rtd->dai_link->compr_ops->shutdown) rtd->dai_link->compr_ops->shutdown(cstream); - soc_link_mark_pop(rtd, cstream, compr_startup); + soc_link_mark_pop(rtd, compr_startup); } EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown); From 65551000333e9f880fecfbc30ee1266fcd5b206c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:02 +0100 Subject: [PATCH 014/256] ASoC: remove unused substream in macro soc_dai_mark_pop JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7215afbd8c090a3254f8cadabb550adf1c00547f Author: Hongbo Li Date: Wed Aug 21 15:08:13 2024 +0800 ASoC: remove unused substream in macro soc_dai_mark_pop The soc_dai_mark_pop don't need substream, and also substream is not used in this macro, so we can remove it. This is detected by macro_checker.py script. Signed-off-by: Hongbo Li Link: https://patch.msgid.link/20240821070815.2326534-4-lihongbo22@huawei.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/soc-dai.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 4e08892d24c6..4a1c85ad5a8d 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -37,7 +37,7 @@ static inline int _soc_dai_ret(const struct snd_soc_dai *dai, * In such case, we can update these macros. */ #define soc_dai_mark_push(dai, substream, tgt) ((dai)->mark_##tgt = substream) -#define soc_dai_mark_pop(dai, substream, tgt) ((dai)->mark_##tgt = NULL) +#define soc_dai_mark_pop(dai, tgt) ((dai)->mark_##tgt = NULL) #define soc_dai_mark_match(dai, substream, tgt) ((dai)->mark_##tgt == substream) /** @@ -416,7 +416,7 @@ void snd_soc_dai_hw_free(struct snd_soc_dai *dai, dai->driver->ops->hw_free(substream, dai); /* remove marked substream */ - soc_dai_mark_pop(dai, substream, hw_params); + soc_dai_mark_pop(dai, hw_params); } int snd_soc_dai_startup(struct snd_soc_dai *dai, @@ -453,7 +453,7 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, dai->driver->ops->shutdown(substream, dai); /* remove marked substream */ - soc_dai_mark_pop(dai, substream, startup); + soc_dai_mark_pop(dai, startup); } int snd_soc_dai_compress_new(struct snd_soc_dai *dai, @@ -640,7 +640,7 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, r = soc_dai_trigger(dai, substream, cmd); if (r < 0) ret = r; /* use last ret */ - soc_dai_mark_pop(dai, substream, trigger); + soc_dai_mark_pop(dai, trigger); } } @@ -704,7 +704,7 @@ void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, dai->driver->cops->shutdown(cstream, dai); /* remove marked cstream */ - soc_dai_mark_pop(dai, cstream, compr_startup); + soc_dai_mark_pop(dai, compr_startup); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown); From 2315bed2440c8d775d3bdf7d0e05d00c319e9883 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:02 +0100 Subject: [PATCH 015/256] ASoC: stm: fix macro definition on STM_SAI_HAS_EXT_SYNC JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7a01e17e42fe944982acde1dd40bdea177372173 Author: Hongbo Li Date: Wed Aug 21 15:08:15 2024 +0800 ASoC: stm: fix macro definition on STM_SAI_HAS_EXT_SYNC The macro STM_SAI_HAS_EXT_SYNC accepts a parameter x, but it was not used, rather the variable sai was directly used, which may be a local variable inside a function that calls the macros. Signed-off-by: Hongbo Li Link: https://patch.msgid.link/20240821070815.2326534-6-lihongbo22@huawei.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/stm/stm32_sai_sub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 2819e4e1d72f..d76d2ce4bdb4 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -53,7 +53,7 @@ #define STM_SAI_PROTOCOL_IS_SPDIF(ip) ((ip)->spdif) #define STM_SAI_HAS_SPDIF(x) ((x)->pdata->conf.has_spdif_pdm) #define STM_SAI_HAS_PDM(x) ((x)->pdata->conf.has_spdif_pdm) -#define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4(sai->pdata)) +#define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4((x)->pdata)) #define SAI_IEC60958_BLOCK_FRAMES 192 #define SAI_IEC60958_STATUS_BYTES 24 From c5eb1f558479326639eeb5d894977cbf79d86b61 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:02 +0100 Subject: [PATCH 016/256] ASoC: amd: acp: simplify platform conditional checks code JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 839a8b18dbd2e2345a261169fb68d950a1071862 Author: Vijendar Mukunda Date: Tue Sep 24 11:48:13 2024 +0530 ASoC: amd: acp: simplify platform conditional checks code Simplify code with switch statements for platform conditional checks. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20240924061821.1127054-2-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-mach-common.c | 36 +++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index e9ff4815c12c..d4c7a7b79177 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -1647,16 +1647,21 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) links[i].id = HEADSET_BE_ID; links[i].cpus = i2s_hs; links[i].num_cpus = ARRAY_SIZE(i2s_hs); - if (drv_data->platform == REMBRANDT) { + switch (drv_data->platform) { + case REMBRANDT: links[i].platforms = platform_rmb_component; links[i].num_platforms = ARRAY_SIZE(platform_rmb_component); - } else if (drv_data->platform == ACP63) { + break; + case ACP63: links[i].platforms = platform_acp63_component; links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); - } else { + break; + default: links[i].platforms = platform_component; links[i].num_platforms = ARRAY_SIZE(platform_component); + break; } + links[i].dpcm_playback = 1; links[i].dpcm_capture = 1; if (!drv_data->hs_codec_id) { @@ -1714,16 +1719,21 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) links[i].id = AMP_BE_ID; links[i].cpus = i2s_hs; links[i].num_cpus = ARRAY_SIZE(i2s_hs); - if (drv_data->platform == REMBRANDT) { + switch (drv_data->platform) { + case REMBRANDT: links[i].platforms = platform_rmb_component; links[i].num_platforms = ARRAY_SIZE(platform_rmb_component); - } else if (drv_data->platform == ACP63) { + break; + case ACP63: links[i].platforms = platform_acp63_component; links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); - } else { + break; + default: links[i].platforms = platform_component; links[i].num_platforms = ARRAY_SIZE(platform_component); + break; } + links[i].dpcm_playback = 1; if (!drv_data->amp_codec_id) { /* Use dummy codec if codec id not specified */ @@ -1760,18 +1770,24 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) } links[i].cpus = pdm_dmic; links[i].num_cpus = ARRAY_SIZE(pdm_dmic); - if (drv_data->platform == REMBRANDT) { + switch (drv_data->platform) { + case REMBRANDT: links[i].platforms = platform_rmb_component; links[i].num_platforms = ARRAY_SIZE(platform_rmb_component); - } else if (drv_data->platform == ACP63) { + break; + case ACP63: links[i].platforms = platform_acp63_component; links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); - } else if ((drv_data->platform == ACP70) || (drv_data->platform == ACP71)) { + break; + case ACP70: + case ACP71: links[i].platforms = platform_acp70_component; links[i].num_platforms = ARRAY_SIZE(platform_acp70_component); - } else { + break; + default: links[i].platforms = platform_component; links[i].num_platforms = ARRAY_SIZE(platform_component); + break; } links[i].ops = &acp_card_dmic_ops; links[i].dpcm_capture = 1; From 8283dc9d3fc1c99eb14f0ea0e61648dfe6ad59d8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:03 +0100 Subject: [PATCH 017/256] ASoC: amd: acp: use acp_rev for platform specific conditional checks JIRA: https://issues.redhat.com/browse/RHEL-80681 commit fca471b5d094dabd65f6d8777096e9ed1df1bef7 Author: Vijendar Mukunda Date: Tue Sep 24 11:48:14 2024 +0530 ASoC: amd: acp: use acp_rev for platform specific conditional checks Add 'acp_rev' as a member in machine driver private data structure to store acp pci revision id. Replace platform specific conditional checks by using 'acp_rev' variable. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20240924061821.1127054-3-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-legacy-mach.c | 2 ++ sound/soc/amd/acp/acp-mach-common.c | 24 ++++++++++++------------ sound/soc/amd/acp/acp-mach.h | 3 +++ sound/soc/amd/acp/acp-sof-mach.c | 2 ++ sound/soc/amd/acp/acp_common.h | 19 +++++++++++++++++++ 5 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 sound/soc/amd/acp/acp_common.h diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c index d104f7e8fdcd..2a59f7916e15 100644 --- a/sound/soc/amd/acp/acp-legacy-mach.c +++ b/sound/soc/amd/acp/acp-legacy-mach.c @@ -126,6 +126,7 @@ static int acp_asoc_probe(struct platform_device *pdev) { struct snd_soc_card *card = NULL; struct device *dev = &pdev->dev; + struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); const struct dmi_system_id *dmi_id; struct acp_card_drvdata *acp_card_drvdata; int ret; @@ -173,6 +174,7 @@ static int acp_asoc_probe(struct platform_device *pdev) if (!strcmp(pdev->name, "acp-pdm-mach")) acp_card_drvdata->platform = *((int *)dev->platform_data); + acp_card_drvdata->acp_rev = mach->mach_params.subsystem_rev; dmi_id = dmi_first_match(acp_quirk_table); if (dmi_id && dmi_id->driver_data) acp_card_drvdata->tdm_mode = dmi_id->driver_data; diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index d4c7a7b79177..2394aa061265 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -1471,7 +1471,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) if (drv_data->amp_cpu_id == I2S_SP) { links[i].name = "acp-amp-codec"; links[i].id = AMP_BE_ID; - if (drv_data->platform == RENOIR) { + if (drv_data->acp_rev == ACP_RN_PCI_ID) { links[i].cpus = sof_sp; links[i].num_cpus = ARRAY_SIZE(sof_sp); } else { @@ -1647,12 +1647,12 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) links[i].id = HEADSET_BE_ID; links[i].cpus = i2s_hs; links[i].num_cpus = ARRAY_SIZE(i2s_hs); - switch (drv_data->platform) { - case REMBRANDT: + switch (drv_data->acp_rev) { + case ACP_RMB_PCI_ID: links[i].platforms = platform_rmb_component; links[i].num_platforms = ARRAY_SIZE(platform_rmb_component); break; - case ACP63: + case ACP63_PCI_ID: links[i].platforms = platform_acp63_component; links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); break; @@ -1719,12 +1719,12 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) links[i].id = AMP_BE_ID; links[i].cpus = i2s_hs; links[i].num_cpus = ARRAY_SIZE(i2s_hs); - switch (drv_data->platform) { - case REMBRANDT: + switch (drv_data->acp_rev) { + case ACP_RMB_PCI_ID: links[i].platforms = platform_rmb_component; links[i].num_platforms = ARRAY_SIZE(platform_rmb_component); break; - case ACP63: + case ACP63_PCI_ID: links[i].platforms = platform_acp63_component; links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); break; @@ -1770,17 +1770,17 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) } links[i].cpus = pdm_dmic; links[i].num_cpus = ARRAY_SIZE(pdm_dmic); - switch (drv_data->platform) { - case REMBRANDT: + switch (drv_data->acp_rev) { + case ACP_RMB_PCI_ID: links[i].platforms = platform_rmb_component; links[i].num_platforms = ARRAY_SIZE(platform_rmb_component); break; - case ACP63: + case ACP63_PCI_ID: links[i].platforms = platform_acp63_component; links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); break; - case ACP70: - case ACP71: + case ACP70_PCI_ID: + case ACP71_PCI_ID: links[i].platforms = platform_acp70_component; links[i].num_platforms = ARRAY_SIZE(platform_acp70_component); break; diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h index 93d9e3886b7e..2b6b8b3e1b94 100644 --- a/sound/soc/amd/acp/acp-mach.h +++ b/sound/soc/amd/acp/acp-mach.h @@ -18,6 +18,8 @@ #include #include +#include "acp_common.h" + #define TDM_CHANNELS 8 #define ACP_OPS(priv, cb) ((priv)->ops.cb) @@ -78,6 +80,7 @@ struct acp_card_drvdata { unsigned int dmic_codec_id; unsigned int dai_fmt; unsigned int platform; + unsigned int acp_rev; struct clk *wclk; struct clk *bclk; struct acp_mach_ops ops; diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c index f36750167fa2..49aadbadb7e1 100644 --- a/sound/soc/amd/acp/acp-sof-mach.c +++ b/sound/soc/amd/acp/acp-sof-mach.c @@ -94,6 +94,7 @@ static int acp_sof_probe(struct platform_device *pdev) { struct snd_soc_card *card = NULL; struct device *dev = &pdev->dev; + struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); const struct dmi_system_id *dmi_id; struct acp_card_drvdata *acp_card_drvdata; int ret; @@ -116,6 +117,7 @@ static int acp_sof_probe(struct platform_device *pdev) if (dmi_id && dmi_id->driver_data) acp_card_drvdata->tdm_mode = dmi_id->driver_data; + acp_card_drvdata->acp_rev = mach->mach_params.subsystem_rev; ret = acp_sofdsp_dai_links_create(card); if (ret) return dev_err_probe(&pdev->dev, ret, "Failed to create DAI links\n"); diff --git a/sound/soc/amd/acp/acp_common.h b/sound/soc/amd/acp/acp_common.h new file mode 100644 index 000000000000..f1ae88013f62 --- /dev/null +++ b/sound/soc/amd/acp/acp_common.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved + */ + +/* + * acp_common.h - acp common header file + */ + +#ifndef __ACP_COMMON_H +#define __ACP_COMMON_H + +#define ACP_RN_PCI_ID 0x01 +#define ACP_VANGOGH_PCI_ID 0x50 +#define ACP_RMB_PCI_ID 0x6F +#define ACP63_PCI_ID 0x63 +#define ACP70_PCI_ID 0x70 +#define ACP71_PCI_ID 0x71 + +#endif From 37d3ee3a88701762ef7e4fe2721229adb056121d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:03 +0100 Subject: [PATCH 018/256] ASoC: amd: acp: use acp pci revision id for platform differntiation JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 5dbf8a19fe5d5a4c764ba88d171b06704354296a Author: Vijendar Mukunda Date: Tue Sep 24 11:48:15 2024 +0530 ASoC: amd: acp: use acp pci revision id for platform differntiation Store acp pci revision id value in 'acp_rev' variable. Use common ACP PCI revision id macros throughout the code for acp_rev check and remove unused macros for platform differentiation from common header file for acp platform driver. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20240924061821.1127054-4-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-i2s.c | 38 +++++++++++++-------------- sound/soc/amd/acp/acp-legacy-common.c | 24 ++++++++--------- sound/soc/amd/acp/acp-pci.c | 7 +---- sound/soc/amd/acp/acp-pdm.c | 2 +- sound/soc/amd/acp/acp-platform.c | 6 ++--- sound/soc/amd/acp/acp-rembrandt.c | 2 +- sound/soc/amd/acp/acp-renoir.c | 2 +- sound/soc/amd/acp/acp63.c | 2 +- sound/soc/amd/acp/acp70.c | 6 ++--- sound/soc/amd/acp/amd.h | 7 +---- 10 files changed, 43 insertions(+), 53 deletions(-) diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index 56ce9e4b6acc..515bf862deb5 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -59,9 +59,9 @@ static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id) val |= BIT(1); switch (chip->acp_rev) { - case ACP63_DEV: - case ACP70_DEV: - case ACP71_DEV: + case ACP63_PCI_ID: + case ACP70_PCI_ID: + case ACP71_PCI_ID: val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, adata->lrclk_div); val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, adata->bclk_div); break; @@ -121,8 +121,8 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas } switch (chip->acp_rev) { - case ACP3X_DEV: - case ACP6X_DEV: + case ACP_RN_PCI_ID: + case ACP_RMB_PCI_ID: switch (slots) { case 1 ... 7: no_of_slots = slots; @@ -135,9 +135,9 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas return -EINVAL; } break; - case ACP63_DEV: - case ACP70_DEV: - case ACP71_DEV: + case ACP63_PCI_ID: + case ACP70_PCI_ID: + case ACP71_PCI_ID: switch (slots) { case 1 ... 31: no_of_slots = slots; @@ -160,8 +160,8 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas spin_lock_irq(&adata->acp_lock); list_for_each_entry(stream, &adata->stream_list, list) { switch (chip->acp_rev) { - case ACP3X_DEV: - case ACP6X_DEV: + case ACP_RN_PCI_ID: + case ACP_RMB_PCI_ID: if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) adata->tdm_tx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 15) | (slot_len << 18); @@ -169,9 +169,9 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas adata->tdm_rx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 15) | (slot_len << 18); break; - case ACP63_DEV: - case ACP70_DEV: - case ACP71_DEV: + case ACP63_PCI_ID: + case ACP70_PCI_ID: + case ACP71_PCI_ID: if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) adata->tdm_tx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 13) | (slot_len << 18); @@ -534,7 +534,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata); reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata); - if (chip->acp_rev >= ACP70_DEV) + if (chip->acp_rev >= ACP70_PCI_ID) phy_addr = ACP7x_I2S_SP_TX_MEM_WINDOW_START; else phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; @@ -546,7 +546,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata); reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata); - if (chip->acp_rev >= ACP70_DEV) + if (chip->acp_rev >= ACP70_PCI_ID) phy_addr = ACP7x_I2S_SP_RX_MEM_WINDOW_START; else phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; @@ -561,7 +561,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata); reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata); - if (chip->acp_rev >= ACP70_DEV) + if (chip->acp_rev >= ACP70_PCI_ID) phy_addr = ACP7x_I2S_BT_TX_MEM_WINDOW_START; else phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; @@ -573,7 +573,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata); reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata); - if (chip->acp_rev >= ACP70_DEV) + if (chip->acp_rev >= ACP70_PCI_ID) phy_addr = ACP7x_I2S_BT_RX_MEM_WINDOW_START; else phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; @@ -588,7 +588,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_HS_TX_FIFOADDR; reg_fifo_size = ACP_HS_TX_FIFOSIZE; - if (chip->acp_rev >= ACP70_DEV) + if (chip->acp_rev >= ACP70_PCI_ID) phy_addr = ACP7x_I2S_HS_TX_MEM_WINDOW_START; else phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset; @@ -600,7 +600,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_HS_RX_FIFOADDR; reg_fifo_size = ACP_HS_RX_FIFOSIZE; - if (chip->acp_rev >= ACP70_DEV) + if (chip->acp_rev >= ACP70_PCI_ID) phy_addr = ACP7x_I2S_HS_RX_MEM_WINDOW_START; else phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset; diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index be01b178172e..3f76d1f0a9e7 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -257,20 +257,20 @@ static int acp_power_on(struct acp_chip_info *chip) base = chip->base; switch (chip->acp_rev) { - case ACP3X_DEV: + case ACP_RN_PCI_ID: acp_pgfsm_stat_reg = ACP_PGFSM_STATUS; acp_pgfsm_ctrl_reg = ACP_PGFSM_CONTROL; break; - case ACP6X_DEV: + case ACP_RMB_PCI_ID: acp_pgfsm_stat_reg = ACP6X_PGFSM_STATUS; acp_pgfsm_ctrl_reg = ACP6X_PGFSM_CONTROL; break; - case ACP63_DEV: + case ACP63_PCI_ID: acp_pgfsm_stat_reg = ACP63_PGFSM_STATUS; acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL; break; - case ACP70_DEV: - case ACP71_DEV: + case ACP70_PCI_ID: + case ACP71_PCI_ID: acp_pgfsm_stat_reg = ACP70_PGFSM_STATUS; acp_pgfsm_ctrl_reg = ACP70_PGFSM_CONTROL; break; @@ -322,7 +322,7 @@ int acp_init(struct acp_chip_info *chip) pr_err("ACP reset failed\n"); return ret; } - if (chip->acp_rev >= ACP70_DEV) + if (chip->acp_rev >= ACP70_PCI_ID) writel(0, chip->base + ACP_ZSC_DSP_CTRL); return 0; } @@ -337,7 +337,7 @@ int acp_deinit(struct acp_chip_info *chip) if (ret) return ret; - if (chip->acp_rev < ACP70_DEV) + if (chip->acp_rev < ACP70_PCI_ID) writel(0, chip->base + ACP_CONTROL); else writel(0x01, chip->base + ACP_ZSC_DSP_CTRL); @@ -448,20 +448,20 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) u32 pdm_addr; switch (chip->acp_rev) { - case ACP3X_DEV: + case ACP_RN_PCI_ID: pdm_addr = ACP_RENOIR_PDM_ADDR; check_acp3x_config(chip); break; - case ACP6X_DEV: + case ACP_RMB_PCI_ID: pdm_addr = ACP_REMBRANDT_PDM_ADDR; check_acp6x_config(chip); break; - case ACP63_DEV: + case ACP63_PCI_ID: pdm_addr = ACP63_PDM_ADDR; check_acp6x_config(chip); break; - case ACP70_DEV: - case ACP71_DEV: + case ACP70_PCI_ID: + case ACP71_PCI_ID: pdm_addr = ACP70_PDM_ADDR; check_acp70_config(chip); break; diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index f7450a5bd103..4b6ad7abc3ba 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -77,27 +77,22 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id res_acp = acp_res; num_res = ARRAY_SIZE(acp_res); - + chip->acp_rev = pci->revision; switch (pci->revision) { case 0x01: chip->name = "acp_asoc_renoir"; - chip->acp_rev = ACP3X_DEV; break; case 0x6f: chip->name = "acp_asoc_rembrandt"; - chip->acp_rev = ACP6X_DEV; break; case 0x63: chip->name = "acp_asoc_acp63"; - chip->acp_rev = ACP63_DEV; break; case 0x70: chip->name = "acp_asoc_acp70"; - chip->acp_rev = ACP70_DEV; break; case 0x71: chip->name = "acp_asoc_acp70"; - chip->acp_rev = ACP71_DEV; break; default: dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision); diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c index 22dd8988d005..48faafe724ed 100644 --- a/sound/soc/amd/acp/acp-pdm.c +++ b/sound/soc/amd/acp/acp-pdm.c @@ -47,7 +47,7 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream, size_dmic = frames_to_bytes(substream->runtime, substream->runtime->buffer_size); - if (chip->acp_rev >= ACP70_DEV) + if (chip->acp_rev >= ACP70_PCI_ID) physical_addr = ACP7x_DMIC_MEM_WINDOW_START; else physical_addr = stream->reg_offset + MEM_WINDOW_START; diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index 3a7a467b7063..c772520227c7 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -270,9 +270,9 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs stream->substream = substream; chip = dev_get_platdata(dev); switch (chip->acp_rev) { - case ACP63_DEV: - case ACP70_DEV: - case ACP71_DEV: + case ACP63_PCI_ID: + case ACP70_PCI_ID: + case ACP71_PCI_ID: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) runtime->hw = acp6x_pcm_hardware_playback; else diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index 294392e339b0..7cc24a26c94a 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -197,7 +197,7 @@ static int rembrandt_audio_probe(struct platform_device *pdev) return -ENODEV; } - if (chip->acp_rev != ACP6X_DEV) { + if (chip->acp_rev != ACP_RMB_PCI_ID) { dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); return -ENODEV; } diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index 2f401d5ae1a4..bdb8154d0d75 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -157,7 +157,7 @@ static int renoir_audio_probe(struct platform_device *pdev) return -ENODEV; } - if (chip->acp_rev != ACP3X_DEV) { + if (chip->acp_rev != ACP_RN_PCI_ID) { dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); return -ENODEV; } diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c index f340920b3289..8ba09651d984 100644 --- a/sound/soc/amd/acp/acp63.c +++ b/sound/soc/amd/acp/acp63.c @@ -207,7 +207,7 @@ static int acp63_audio_probe(struct platform_device *pdev) return -ENODEV; } - if (chip->acp_rev != ACP63_DEV) { + if (chip->acp_rev != ACP63_PCI_ID) { dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); return -ENODEV; } diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index 1b0b59a22924..e55698afbfc0 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -175,8 +175,8 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) } switch (chip->acp_rev) { - case ACP70_DEV: - case ACP71_DEV: + case ACP70_PCI_ID: + case ACP71_PCI_ID: break; default: dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); @@ -209,7 +209,7 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) adata->num_dai = ARRAY_SIZE(acp70_dai); adata->rsrc = &rsrc; adata->machines = snd_soc_acpi_amd_acp70_acp_machines; - if (chip->acp_rev == ACP70_DEV) + if (chip->acp_rev == ACP70_PCI_ID) adata->platform = ACP70; else adata->platform = ACP71; diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 854269fea875..c82e438a1712 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -16,14 +16,9 @@ #include #include +#include "acp_common.h" #include "chip_offset_byte.h" -#define ACP3X_DEV 3 -#define ACP6X_DEV 6 -#define ACP63_DEV 0x63 -#define ACP70_DEV 0x70 -#define ACP71_DEV 0x71 - #define DMIC_INSTANCE 0x00 #define I2S_SP_INSTANCE 0x01 #define I2S_BT_INSTANCE 0x02 From 8819930fdf64644fed89ea2035c1a0c2e36c2213 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:03 +0100 Subject: [PATCH 019/256] ASoC: amd: acp: store acp pci rev id in platform driver private structure JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 40412a298c77eaa4a22a1aa7030bcc0b2e02c618 Author: Vijendar Mukunda Date: Tue Sep 24 11:48:16 2024 +0530 ASoC: amd: acp: store acp pci rev id in platform driver private structure Store acp pci revision id in platform driver private structure for all acp varaints. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20240924061821.1127054-5-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-rembrandt.c | 1 + sound/soc/amd/acp/acp-renoir.c | 1 + sound/soc/amd/acp/acp63.c | 1 + sound/soc/amd/acp/acp70.c | 1 + sound/soc/amd/acp/amd.h | 1 + 5 files changed, 5 insertions(+) diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index 7cc24a26c94a..e59a8b8d9baf 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -228,6 +228,7 @@ static int rembrandt_audio_probe(struct platform_device *pdev) adata->num_dai = ARRAY_SIZE(acp_rmb_dai); adata->rsrc = &rsrc; adata->platform = REMBRANDT; + adata->acp_rev = chip->acp_rev; adata->flag = chip->flag; adata->is_i2s_config = chip->is_i2s_config; adata->machines = snd_soc_acpi_amd_rmb_acp_machines; diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index bdb8154d0d75..1742c585ec6c 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -186,6 +186,7 @@ static int renoir_audio_probe(struct platform_device *pdev) adata->num_dai = ARRAY_SIZE(acp_renoir_dai); adata->rsrc = &rsrc; adata->platform = RENOIR; + adata->acp_rev = chip->acp_rev; adata->flag = chip->flag; adata->machines = snd_soc_acpi_amd_acp_machines; diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c index 8ba09651d984..82c1e6e95a75 100644 --- a/sound/soc/amd/acp/acp63.c +++ b/sound/soc/amd/acp/acp63.c @@ -238,6 +238,7 @@ static int acp63_audio_probe(struct platform_device *pdev) adata->num_dai = ARRAY_SIZE(acp63_dai); adata->rsrc = &rsrc; adata->platform = ACP63; + adata->acp_rev = chip->acp_rev; adata->flag = chip->flag; adata->is_i2s_config = chip->is_i2s_config; adata->machines = snd_soc_acpi_amd_acp63_acp_machines; diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index e55698afbfc0..bbdedd1d49e9 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -209,6 +209,7 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) adata->num_dai = ARRAY_SIZE(acp70_dai); adata->rsrc = &rsrc; adata->machines = snd_soc_acpi_amd_acp70_acp_machines; + adata->acp_rev = chip->acp_rev; if (chip->acp_rev == ACP70_PCI_ID) adata->platform = ACP70; else diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index c82e438a1712..dcfc29b2f072 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -177,6 +177,7 @@ struct acp_dev_data { struct device *dev; void __iomem *acp_base; unsigned int i2s_irq; + unsigned int acp_rev; /* ACP Revision id */ bool tdm_mode; bool is_i2s_config; From 954853701777b6cb8a62d6c6f525382e5ae65cb0 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:03 +0100 Subject: [PATCH 020/256] ASoC: amd: acp: pass acp pci revision id as platform data JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0eae2c96b49d85b31ab635b9dc6f09b09d3c54de Author: Vijendar Mukunda Date: Tue Sep 24 11:48:17 2024 +0530 ASoC: amd: acp: pass acp pci revision id as platform data Pass acp pci revision id as platform data to machine driver instead of 'platform' variable when ACP PDM configuration is selected. 'acp_rev' should be retrieved from mach params revision id for other configuration. Modify the conditional check for the same. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20240924061821.1127054-6-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-legacy-mach.c | 5 +++-- sound/soc/amd/acp/acp-platform.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c index 2a59f7916e15..3526fbe2c84d 100644 --- a/sound/soc/amd/acp/acp-legacy-mach.c +++ b/sound/soc/amd/acp/acp-legacy-mach.c @@ -172,9 +172,10 @@ static int acp_asoc_probe(struct platform_device *pdev) goto out; } if (!strcmp(pdev->name, "acp-pdm-mach")) - acp_card_drvdata->platform = *((int *)dev->platform_data); + acp_card_drvdata->acp_rev = *((int *)dev->platform_data); + else + acp_card_drvdata->acp_rev = mach->mach_params.subsystem_rev; - acp_card_drvdata->acp_rev = mach->mach_params.subsystem_rev; dmi_id = dmi_first_match(acp_quirk_table); if (dmi_id && dmi_id->driver_data) acp_card_drvdata->tdm_mode = dmi_id->driver_data; diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index c772520227c7..a6e5cb263377 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -114,7 +114,7 @@ int acp_machine_select(struct acp_dev_data *adata) int size, platform; if (adata->flag == FLAG_AMD_LEGACY_ONLY_DMIC) { - platform = adata->platform; + platform = adata->acp_rev; adata->mach_dev = platform_device_register_data(adata->dev, "acp-pdm-mach", PLATFORM_DEVID_NONE, &platform, sizeof(platform)); From b28f3cb478753dd5dfa62273b426a25bbc490ad3 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:03 +0100 Subject: [PATCH 021/256] ASoC: amd: acp: update mach_params subsystem_rev field JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0a374a2dd0afa7ba431fab2749197374cf95fb67 Author: Vijendar Mukunda Date: Tue Sep 24 11:48:18 2024 +0530 ASoC: amd: acp: update mach_params subsystem_rev field Update mach_params subsystem_rev field in acp_machine_select() function with acp pci revision id value. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20240924061821.1127054-7-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index a6e5cb263377..78fcff6ea657 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -125,6 +125,7 @@ int acp_machine_select(struct acp_dev_data *adata) dev_err(adata->dev, "warning: No matching ASoC machine driver found\n"); return -EINVAL; } + mach->mach_params.subsystem_rev = adata->acp_rev; adata->mach_dev = platform_device_register_data(adata->dev, mach->drv_name, PLATFORM_DEVID_NONE, mach, size); } From 2504822b46eb7faeea159e600853c69ef246b7bf Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:03 +0100 Subject: [PATCH 022/256] ASoC: amd: acp: remove unused variable from acp_card_drvdata structure JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 2e609185e174a9ffd462ab125085ddfcbe9e2f4d Author: Vijendar Mukunda Date: Tue Sep 24 11:48:19 2024 +0530 ASoC: amd: acp: remove unused variable from acp_card_drvdata structure Remove unused 'platform' variable from acp_card_drvdata structure. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20240924061821.1127054-8-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-legacy-mach.c | 3 --- sound/soc/amd/acp/acp-mach.h | 1 - sound/soc/amd/acp/acp-sof-mach.c | 4 ---- 3 files changed, 8 deletions(-) diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c index 3526fbe2c84d..45613a865d2b 100644 --- a/sound/soc/amd/acp/acp-legacy-mach.c +++ b/sound/soc/amd/acp/acp-legacy-mach.c @@ -57,7 +57,6 @@ static struct acp_card_drvdata es83xx_rn_data = { .dmic_cpu_id = DMIC, .hs_codec_id = ES83XX, .dmic_codec_id = DMIC, - .platform = RENOIR, }; static struct acp_card_drvdata max_nau8825_data = { @@ -68,7 +67,6 @@ static struct acp_card_drvdata max_nau8825_data = { .amp_codec_id = MAX98360A, .dmic_codec_id = DMIC, .soc_mclk = true, - .platform = REMBRANDT, .tdm_mode = false, }; @@ -80,7 +78,6 @@ static struct acp_card_drvdata rt5682s_rt1019_rmb_data = { .amp_codec_id = RT1019, .dmic_codec_id = DMIC, .soc_mclk = true, - .platform = REMBRANDT, .tdm_mode = false, }; diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h index 2b6b8b3e1b94..414d0175988b 100644 --- a/sound/soc/amd/acp/acp-mach.h +++ b/sound/soc/amd/acp/acp-mach.h @@ -79,7 +79,6 @@ struct acp_card_drvdata { unsigned int bt_codec_id; unsigned int dmic_codec_id; unsigned int dai_fmt; - unsigned int platform; unsigned int acp_rev; struct clk *wclk; struct clk *bclk; diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c index 49aadbadb7e1..63a9621ede6d 100644 --- a/sound/soc/amd/acp/acp-sof-mach.c +++ b/sound/soc/amd/acp/acp-sof-mach.c @@ -46,7 +46,6 @@ static struct acp_card_drvdata sof_rt5682s_rt1019_data = { .hs_codec_id = RT5682S, .amp_codec_id = RT1019, .dmic_codec_id = DMIC, - .platform = RENOIR, }; static struct acp_card_drvdata sof_rt5682s_max_data = { @@ -56,7 +55,6 @@ static struct acp_card_drvdata sof_rt5682s_max_data = { .hs_codec_id = RT5682S, .amp_codec_id = MAX98360A, .dmic_codec_id = DMIC, - .platform = RENOIR, }; static struct acp_card_drvdata sof_nau8825_data = { @@ -66,7 +64,6 @@ static struct acp_card_drvdata sof_nau8825_data = { .hs_codec_id = NAU8825, .amp_codec_id = MAX98360A, .dmic_codec_id = DMIC, - .platform = REMBRANDT, .soc_mclk = true, }; @@ -77,7 +74,6 @@ static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = { .hs_codec_id = RT5682S, .amp_codec_id = RT1019, .dmic_codec_id = DMIC, - .platform = REMBRANDT, .soc_mclk = true, }; From fa2b8460ff603fda26cebf6234ef3385c2897504 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:04 +0100 Subject: [PATCH 023/256] ASoC: amd: acp: replace adata->platform conditional check JIRA: https://issues.redhat.com/browse/RHEL-80681 commit b33d93990e3774a24575517c6fcc2167036672d1 Author: Vijendar Mukunda Date: Tue Sep 24 11:48:20 2024 +0530 ASoC: amd: acp: replace adata->platform conditional check Replace adata->platform condition check with acp pci revision id variable in config_acp_dma() & acp70_i2s_master_clock_generate() functions. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20240924061821.1127054-9-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-platform.c | 6 +++--- sound/soc/amd/acp/acp70.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index 78fcff6ea657..7be9b4ff7923 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -205,9 +205,9 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s u32 low, high, val; u16 page_idx; - switch (adata->platform) { - case ACP70: - case ACP71: + switch (adata->acp_rev) { + case ACP70_PCI_ID: + case ACP71_PCI_ID: switch (stream->dai_id) { case I2S_SP_INSTANCE: if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index bbdedd1d49e9..5ad579098c68 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -142,9 +142,9 @@ static int acp70_i2s_master_clock_generate(struct acp_dev_data *adata) struct pci_dev *smn_dev; u32 device_id; - if (adata->platform == ACP70) + if (adata->acp_rev == ACP70_PCI_ID) device_id = 0x1507; - else if (adata->platform == ACP71) + else if (adata->acp_rev == ACP71_PCI_ID) device_id = 0x1122; else return -ENODEV; From f388e375825342018016d0b727dc3aca118a42b6 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:04 +0100 Subject: [PATCH 024/256] ASoC: amd: acp: remove unused variable from acp platform driver JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9864c8af89eb14a2e5334f8e24bb82086182e894 Author: Vijendar Mukunda Date: Tue Sep 24 11:48:21 2024 +0530 ASoC: amd: acp: remove unused variable from acp platform driver Remove 'platform' variable from acp platform driver private data structure. For platform differentiation, ACP pci revision id being used through out the code. As platform variable is no longer used in code, drop the code corresponding to 'platform' variable. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20240924061821.1127054-10-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-mach.h | 8 -------- sound/soc/amd/acp/acp-rembrandt.c | 1 - sound/soc/amd/acp/acp-renoir.c | 1 - sound/soc/amd/acp/acp63.c | 1 - sound/soc/amd/acp/acp70.c | 5 ----- sound/soc/amd/acp/amd.h | 1 - 6 files changed, 17 deletions(-) diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h index 414d0175988b..f94c30c20f20 100644 --- a/sound/soc/amd/acp/acp-mach.h +++ b/sound/soc/amd/acp/acp-mach.h @@ -53,14 +53,6 @@ enum codec_endpoints { ES83XX, }; -enum platform_end_point { - RENOIR = 0, - REMBRANDT, - ACP63, - ACP70, - ACP71, -}; - 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); diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index e59a8b8d9baf..5d4e26ac2336 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -227,7 +227,6 @@ static int rembrandt_audio_probe(struct platform_device *pdev) adata->dai_driver = acp_rmb_dai; adata->num_dai = ARRAY_SIZE(acp_rmb_dai); adata->rsrc = &rsrc; - adata->platform = REMBRANDT; adata->acp_rev = chip->acp_rev; adata->flag = chip->flag; adata->is_i2s_config = chip->is_i2s_config; diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index 1742c585ec6c..5b20a5216da3 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -185,7 +185,6 @@ static int renoir_audio_probe(struct platform_device *pdev) adata->dai_driver = acp_renoir_dai; adata->num_dai = ARRAY_SIZE(acp_renoir_dai); adata->rsrc = &rsrc; - adata->platform = RENOIR; adata->acp_rev = chip->acp_rev; adata->flag = chip->flag; diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c index 82c1e6e95a75..5508ef3bc742 100644 --- a/sound/soc/amd/acp/acp63.c +++ b/sound/soc/amd/acp/acp63.c @@ -237,7 +237,6 @@ static int acp63_audio_probe(struct platform_device *pdev) adata->dai_driver = acp63_dai; adata->num_dai = ARRAY_SIZE(acp63_dai); adata->rsrc = &rsrc; - adata->platform = ACP63; adata->acp_rev = chip->acp_rev; adata->flag = chip->flag; adata->is_i2s_config = chip->is_i2s_config; diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index 5ad579098c68..062ef38de674 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -210,11 +210,6 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) adata->rsrc = &rsrc; adata->machines = snd_soc_acpi_amd_acp70_acp_machines; adata->acp_rev = chip->acp_rev; - if (chip->acp_rev == ACP70_PCI_ID) - adata->platform = ACP70; - else - adata->platform = ACP71; - adata->flag = chip->flag; acp_machine_select(adata); diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index dcfc29b2f072..ee69dfb10cb8 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -201,7 +201,6 @@ struct acp_dev_data { u32 xfer_tx_resolution[3]; u32 xfer_rx_resolution[3]; unsigned int flag; - unsigned int platform; }; enum acp_config { From ad80ac67d88c1a6caf2ae942fb3fe3173d6d53db Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:04 +0100 Subject: [PATCH 025/256] ASoC: constify snd_soc_component_driver struct JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 8adff2ff73d8271c993549b106b26f301fa003cf Author: Javier Carrasco Date: Mon Jul 29 11:37:38 2024 +0200 ASoC: constify snd_soc_component_driver struct Declare `snd_soc_component_driver` as const to move it to a read-only section for the drivers that do not modify the struct after its declaration. The affected drivers only pass this struct to `devm_snd_soc_register_component()`, whose argument is const and therefore does not modify the content of the struct. Signed-off-by: Javier Carrasco Link: https://patch.msgid.link/20240729-const_snd_soc_component_driver-v2-2-1994f44f1ec2@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/au1x/dbdma2.c | 2 +- sound/soc/au1x/dma.c | 2 +- sound/soc/bcm/cygnus-pcm.c | 2 +- sound/soc/codecs/cpcap.c | 2 +- sound/soc/codecs/pcm186x.c | 4 ++-- sound/soc/codecs/pcm5102a.c | 2 +- sound/soc/codecs/spdif_receiver.c | 2 +- sound/soc/codecs/spdif_transmitter.c | 2 +- sound/soc/codecs/tas6424.c | 2 +- sound/soc/stm/stm32_adfsdm.c | 2 +- sound/soc/uniphier/evea.c | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 3d67e27fada9..aaf746a40b13 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -311,7 +311,7 @@ static int au1xpsc_pcm_new(struct snd_soc_component *component, } /* au1xpsc audio platform */ -static struct snd_soc_component_driver au1xpsc_soc_component = { +static const struct snd_soc_component_driver au1xpsc_soc_component = { .name = DRV_NAME, .open = au1xpsc_pcm_open, .close = au1xpsc_pcm_close, diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c index 7f5be90c9ed1..6418f78a116f 100644 --- a/sound/soc/au1x/dma.c +++ b/sound/soc/au1x/dma.c @@ -289,7 +289,7 @@ static int alchemy_pcm_new(struct snd_soc_component *component, return 0; } -static struct snd_soc_component_driver alchemy_pcm_soc_component = { +static const struct snd_soc_component_driver alchemy_pcm_soc_component = { .name = DRV_NAME, .open = alchemy_pcm_open, .close = alchemy_pcm_close, diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c index 2d1e241d8367..4cb2fe10bcdc 100644 --- a/sound/soc/bcm/cygnus-pcm.c +++ b/sound/soc/bcm/cygnus-pcm.c @@ -707,7 +707,7 @@ static int cygnus_dma_new(struct snd_soc_component *component, return 0; } -static struct snd_soc_component_driver cygnus_soc_platform = { +static const struct snd_soc_component_driver cygnus_soc_platform = { .open = cygnus_pcm_open, .close = cygnus_pcm_close, .prepare = cygnus_pcm_prepare, diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c index 4f9dabd9d78a..04304a7ad915 100644 --- a/sound/soc/codecs/cpcap.c +++ b/sound/soc/codecs/cpcap.c @@ -1649,7 +1649,7 @@ static int cpcap_soc_probe(struct snd_soc_component *component) return cpcap_audio_reset(component, false); } -static struct snd_soc_component_driver soc_codec_dev_cpcap = { +static const struct snd_soc_component_driver soc_codec_dev_cpcap = { .probe = cpcap_soc_probe, .controls = cpcap_snd_controls, .num_controls = ARRAY_SIZE(cpcap_snd_controls), diff --git a/sound/soc/codecs/pcm186x.c b/sound/soc/codecs/pcm186x.c index 451a8fd8fac5..13443f569ddb 100644 --- a/sound/soc/codecs/pcm186x.c +++ b/sound/soc/codecs/pcm186x.c @@ -566,7 +566,7 @@ static int pcm186x_set_bias_level(struct snd_soc_component *component, return 0; } -static struct snd_soc_component_driver soc_codec_dev_pcm1863 = { +static const struct snd_soc_component_driver soc_codec_dev_pcm1863 = { .set_bias_level = pcm186x_set_bias_level, .controls = pcm1863_snd_controls, .num_controls = ARRAY_SIZE(pcm1863_snd_controls), @@ -579,7 +579,7 @@ static struct snd_soc_component_driver soc_codec_dev_pcm1863 = { .endianness = 1, }; -static struct snd_soc_component_driver soc_codec_dev_pcm1865 = { +static const struct snd_soc_component_driver soc_codec_dev_pcm1865 = { .set_bias_level = pcm186x_set_bias_level, .controls = pcm1865_snd_controls, .num_controls = ARRAY_SIZE(pcm1865_snd_controls), diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c index 3401a25341e6..9bca53de2475 100644 --- a/sound/soc/codecs/pcm5102a.c +++ b/sound/soc/codecs/pcm5102a.c @@ -24,7 +24,7 @@ static struct snd_soc_dai_driver pcm5102a_dai = { }, }; -static struct snd_soc_component_driver soc_component_dev_pcm5102a = { +static const struct snd_soc_component_driver soc_component_dev_pcm5102a = { .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c index 310123d2bb5f..c9766979b1d7 100644 --- a/sound/soc/codecs/spdif_receiver.c +++ b/sound/soc/codecs/spdif_receiver.c @@ -36,7 +36,7 @@ static const struct snd_soc_dapm_route dir_routes[] = { SNDRV_PCM_FMTBIT_S32_LE | \ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) -static struct snd_soc_component_driver soc_codec_spdif_dir = { +static const struct snd_soc_component_driver soc_codec_spdif_dir = { .dapm_widgets = dir_widgets, .num_dapm_widgets = ARRAY_SIZE(dir_widgets), .dapm_routes = dir_routes, diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c index db51a46e689d..2409fd834f84 100644 --- a/sound/soc/codecs/spdif_transmitter.c +++ b/sound/soc/codecs/spdif_transmitter.c @@ -36,7 +36,7 @@ static const struct snd_soc_dapm_route dit_routes[] = { { "spdif-out", NULL, "Playback" }, }; -static struct snd_soc_component_driver soc_codec_spdif_dit = { +static const struct snd_soc_component_driver soc_codec_spdif_dit = { .dapm_widgets = dit_widgets, .num_dapm_widgets = ARRAY_SIZE(dit_widgets), .dapm_routes = dit_routes, diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c index ad8711be2a5f..482cbd540941 100644 --- a/sound/soc/codecs/tas6424.c +++ b/sound/soc/codecs/tas6424.c @@ -364,7 +364,7 @@ static int tas6424_set_bias_level(struct snd_soc_component *component, return 0; } -static struct snd_soc_component_driver soc_codec_dev_tas6424 = { +static const struct snd_soc_component_driver soc_codec_dev_tas6424 = { .set_bias_level = tas6424_set_bias_level, .controls = tas6424_snd_controls, .num_controls = ARRAY_SIZE(tas6424_snd_controls), diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index 837c1848d9bf..cc67dc5c5daf 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -309,7 +309,7 @@ static void stm32_adfsdm_cleanup(void *data) iio_channel_release_all_cb(data); } -static struct snd_soc_component_driver stm32_adfsdm_soc_platform = { +static const struct snd_soc_component_driver stm32_adfsdm_soc_platform = { .open = stm32_adfsdm_pcm_open, .close = stm32_adfsdm_pcm_close, .hw_params = stm32_adfsdm_pcm_hw_params, diff --git a/sound/soc/uniphier/evea.c b/sound/soc/uniphier/evea.c index 42403ae8e31b..cbcc4ec3b142 100644 --- a/sound/soc/uniphier/evea.c +++ b/sound/soc/uniphier/evea.c @@ -384,7 +384,7 @@ err_out_clock: return ret; } -static struct snd_soc_component_driver soc_codec_evea = { +static const struct snd_soc_component_driver soc_codec_evea = { .probe = evea_codec_probe, .suspend = evea_codec_suspend, .resume = evea_codec_resume, From 7b465fb293af7f2a14bd98b2787185d1c97f083a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:04 +0100 Subject: [PATCH 026/256] ASoC: SOF: ipc3: Use standard dev_dbg API JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 55c39835ee0ef94593a78f6ea808138d476f3b81 Author: Daniel Baluta Date: Thu Sep 26 12:02:52 2024 +0300 ASoC: SOF: ipc3: Use standard dev_dbg API Use standard dev_dbg API because it gives better debugging information and allows dynamic control of prints. Signed-off-by: Daniel Baluta Link: https://patch.msgid.link/20240926090252.106040-1-daniel.baluta@nxp.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c index 83c22d4a4830..7de5e3d285e7 100644 --- a/sound/soc/sof/ipc3.c +++ b/sound/soc/sof/ipc3.c @@ -226,7 +226,7 @@ static inline void ipc3_log_header(struct device *dev, u8 *text, u32 cmd) static void sof_ipc3_dump_payload(struct snd_sof_dev *sdev, void *ipc_data, size_t size) { - printk(KERN_DEBUG "Size of payload following the header: %zu\n", size); + dev_dbg(sdev->dev, "Size of payload following the header: %zu\n", size); print_hex_dump_debug("Message payload: ", DUMP_PREFIX_OFFSET, 16, 4, ipc_data, size, false); } From 50be5a4b6599a48fc084d42c2a61666e72c21460 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:28 +0100 Subject: [PATCH 027/256] ASoC: tas2781: Fix redundant parameter assignment JIRA: https://issues.redhat.com/browse/RHEL-80681 commit ecdaf9140528bc2ef37f2d663fbaf690a64bb125 Author: Tang Bin Date: Sat Sep 14 15:23:52 2024 +0800 ASoC: tas2781: Fix redundant parameter assignment In these functions, the variable 'rc' is redundant, thus remove it. Signed-off-by: Tang Bin Link: https://patch.msgid.link/20240914072352.2997-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/tas2781-i2c.c | 35 ++++++++-------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index 564a97a5635f..2fcb3bd254e3 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -650,7 +650,6 @@ static int tasdev_tf_data_get(struct snd_kcontrol *kcontrol, (struct soc_bytes_ext *) kcontrol->private_value; unsigned char *dst = ucontrol->value.bytes.data; unsigned int reg; - int rc = -1; if (tas_priv->chip_id == TAS2781) reg = TAS2781_RUNTIME_RE_REG_TF; @@ -659,9 +658,7 @@ static int tasdev_tf_data_get(struct snd_kcontrol *kcontrol, guard(mutex)(&tas_priv->codec_lock); dst[0] = bytes_ext->max; - rc = calib_data_get(tas_priv, reg, &dst[1]); - - return rc; + return calib_data_get(tas_priv, reg, &dst[1]); } static int tasdev_re_data_get(struct snd_kcontrol *kcontrol, @@ -673,7 +670,6 @@ static int tasdev_re_data_get(struct snd_kcontrol *kcontrol, (struct soc_bytes_ext *) kcontrol->private_value; unsigned char *dst = ucontrol->value.bytes.data; unsigned int reg; - int rc = -1; if (tas_priv->chip_id == TAS2781) reg = TAS2781_RUNTIME_RE_REG; @@ -681,9 +677,7 @@ static int tasdev_re_data_get(struct snd_kcontrol *kcontrol, reg = TAS2563_RUNTIME_RE_REG; guard(mutex)(&tas_priv->codec_lock); dst[0] = bytes_ext->max; - rc = calib_data_get(tas_priv, reg, &dst[1]); - - return rc; + return calib_data_get(tas_priv, reg, &dst[1]); } static int tasdev_r0_data_get(struct snd_kcontrol *kcontrol, @@ -696,7 +690,6 @@ static int tasdev_r0_data_get(struct snd_kcontrol *kcontrol, (struct soc_bytes_ext *) kcontrol->private_value; unsigned char *dst = ucontrol->value.bytes.data; unsigned int reg; - int rc = -1; guard(mutex)(&tas_priv->codec_lock); @@ -707,9 +700,7 @@ static int tasdev_r0_data_get(struct snd_kcontrol *kcontrol, else return -1; dst[0] = bytes_ext->max; - rc = calib_data_get(tas_priv, reg, &dst[1]); - - return rc; + return calib_data_get(tas_priv, reg, &dst[1]); } static int tasdev_XMA1_data_get(struct snd_kcontrol *kcontrol, @@ -721,13 +712,10 @@ static int tasdev_XMA1_data_get(struct snd_kcontrol *kcontrol, (struct soc_bytes_ext *) kcontrol->private_value; unsigned char *dst = ucontrol->value.bytes.data; unsigned int reg = TASDEVICE_XM_A1_REG; - int rc = -1; guard(mutex)(&tas_priv->codec_lock); dst[0] = bytes_ext->max; - rc = calib_data_get(tas_priv, reg, &dst[1]); - - return rc; + return calib_data_get(tas_priv, reg, &dst[1]); } static int tasdev_XMA2_data_get(struct snd_kcontrol *kcontrol, @@ -739,13 +727,10 @@ static int tasdev_XMA2_data_get(struct snd_kcontrol *kcontrol, (struct soc_bytes_ext *) kcontrol->private_value; unsigned char *dst = ucontrol->value.bytes.data; unsigned int reg = TASDEVICE_XM_A2_REG; - int rc = -1; guard(mutex)(&tas_priv->codec_lock); dst[0] = bytes_ext->max; - rc = calib_data_get(tas_priv, reg, &dst[1]); - - return rc; + return calib_data_get(tas_priv, reg, &dst[1]); } static int tasdev_nop_get( @@ -1115,14 +1100,12 @@ static int tasdevice_active_num_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); int dev_id = ucontrol->value.integer.value[0]; - int max = tas_priv->ndev - 1, rc; + int max = tas_priv->ndev - 1; dev_id = clamp(dev_id, 0, max); guard(mutex)(&tas_priv->codec_lock); - rc = tasdev_chn_switch(tas_priv, dev_id); - - return rc; + return tasdev_chn_switch(tas_priv, dev_id); } static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv) @@ -1339,10 +1322,8 @@ static int tasdevice_create_cali_ctrls(struct tasdevice_priv *priv) i++; } - rc = snd_soc_add_component_controls(priv->codec, cali_ctrls, + return snd_soc_add_component_controls(priv->codec, cali_ctrls, nctrls < i ? nctrls : i); - - return rc; } static void tasdevice_fw_ready(const struct firmware *fmw, From 037a68f89361ba545f8faac8fd4c9d26a9c7e4e7 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:28 +0100 Subject: [PATCH 028/256] ASoC: codecs: aw88395: Fix spelling mistake "unsupport" -> "unsupported" JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 87ad2133b805a6c18f159016a4282311a37c6bcb Author: Colin Ian King Date: Mon Sep 23 13:07:23 2024 +0100 ASoC: codecs: aw88395: Fix spelling mistake "unsupport" -> "unsupported" There is a spelling mistake in a dev_err message. Fix it. Signed-off-by: Colin Ian King Link: https://patch.msgid.link/20240923120723.837196-1-colin.i.king@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/aw88395/aw88395_device.c | 2 +- sound/soc/codecs/aw88395/aw88395_lib.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/aw88395/aw88395_device.c b/sound/soc/codecs/aw88395/aw88395_device.c index fd1f67d5f22f..6b333d1c6e94 100644 --- a/sound/soc/codecs/aw88395/aw88395_device.c +++ b/sound/soc/codecs/aw88395/aw88395_device.c @@ -703,7 +703,7 @@ static int aw_dev_set_vcalb(struct aw_device *aw_dev) AW88395_VSCAL_FACTOR_DAC, icalk, vcalk); break; default: - dev_err(aw_dev->dev, "unsupport vsense status"); + dev_err(aw_dev->dev, "unsupported vsense status"); return -EINVAL; } diff --git a/sound/soc/codecs/aw88395/aw88395_lib.c b/sound/soc/codecs/aw88395/aw88395_lib.c index 769ca32a5c8e..ceb7fc43d018 100644 --- a/sound/soc/codecs/aw88395/aw88395_lib.c +++ b/sound/soc/codecs/aw88395/aw88395_lib.c @@ -688,7 +688,7 @@ static int aw_dev_load_cfg_by_hdr(struct aw_device *aw_dev, ret = aw_dev_cfg_get_reg_valid_prof(aw_dev, all_prof_info); break; default: - dev_err(aw_dev->dev, "unsupport data type\n"); + dev_err(aw_dev->dev, "unsupported data type\n"); ret = -EINVAL; break; } From d88ffd5d4ec24d3610eb360a5ce0ba570d154319 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:28 +0100 Subject: [PATCH 029/256] ASoC: rt1320: reads patch code from firmware file JIRA: https://issues.redhat.com/browse/RHEL-80681 commit d72498fad93abf1817c4998d172a3d7f98f76bbe Author: Shuming Fan Date: Sat Sep 14 17:05:21 2024 +0800 ASoC: rt1320: reads patch code from firmware file This patch removes many lines of the patch code and reads the patch code from firmware files. Signed-off-by: Shuming Fan Link: https://patch.msgid.link/20240914090521.2224276-1-shumingf@realtek.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/rt1320-sdw.c | 3347 ++------------------------------- sound/soc/codecs/rt1320-sdw.h | 2 + 2 files changed, 107 insertions(+), 3242 deletions(-) diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c index f4e1ea29c265..2404de8ae03d 100644 --- a/sound/soc/codecs/rt1320-sdw.c +++ b/sound/soc/codecs/rt1320-sdw.c @@ -89,6 +89,23 @@ static const struct reg_sequence rt1320_blind_write[] = { { 0xc019, 0x10 }, { 0xd487, 0x3f }, { 0xd486, 0xc3 }, + { 0x3fc2bfc7, 0x00 }, + { 0x3fc2bfc6, 0x00 }, + { 0x3fc2bfc5, 0x00 }, + { 0x3fc2bfc4, 0x01 }, + { 0x0000d486, 0x43 }, + { 0x1000db00, 0x02 }, + { 0x1000db01, 0x00 }, + { 0x1000db02, 0x11 }, + { 0x1000db03, 0x00 }, + { 0x1000db04, 0x00 }, + { 0x1000db05, 0x82 }, + { 0x1000db06, 0x04 }, + { 0x1000db07, 0xf1 }, + { 0x1000db08, 0x00 }, + { 0x1000db09, 0x00 }, + { 0x1000db0a, 0x40 }, + { 0x0000d540, 0x01 }, }; static const struct reg_sequence rt1320_vc_blind_write[] = { @@ -148,6 +165,12 @@ static const struct reg_sequence rt1320_vc_blind_write[] = { { 0xd487, 0x3b }, { 0xd486, 0xc3 }, { 0xc598, 0x04 }, + { 0xdb03, 0xf0 }, + { 0xdb09, 0x00 }, + { 0xdb08, 0x7a }, + { 0xdb19, 0x02 }, + { 0xdb07, 0x5a }, + { 0xdb05, 0x45 }, { 0xd500, 0x00 }, { 0xd500, 0x17 }, { 0xd600, 0x01 }, @@ -164,1913 +187,6 @@ static const struct reg_sequence rt1320_vc_blind_write[] = { { 0xd610, 0x01 }, { 0xd608, 0x03 }, { 0xd609, 0x00 }, -}; - -static const struct reg_sequence rt1320_vc_patch_code_write[] = { - { 0x10007000, 0x37 }, - { 0x10007001, 0x77 }, - { 0x10007002, 0x00 }, - { 0x10007003, 0x10 }, - { 0x10007004, 0xb7 }, - { 0x10007005, 0xe7 }, - { 0x10007006, 0x00 }, - { 0x10007007, 0x10 }, - { 0x10007008, 0x13 }, - { 0x10007009, 0x07 }, - { 0x1000700a, 0x87 }, - { 0x1000700b, 0x48 }, - { 0x1000700c, 0x23 }, - { 0x1000700d, 0xa6 }, - { 0x1000700e, 0xe7 }, - { 0x1000700f, 0xee }, - { 0x10007010, 0x37 }, - { 0x10007011, 0x77 }, - { 0x10007012, 0x00 }, - { 0x10007013, 0x10 }, - { 0x10007014, 0x13 }, - { 0x10007015, 0x07 }, - { 0x10007016, 0x87 }, - { 0x10007017, 0x56 }, - { 0x10007018, 0x23 }, - { 0x10007019, 0xac }, - { 0x1000701a, 0xe7 }, - { 0x1000701b, 0xde }, - { 0x1000701c, 0x37 }, - { 0x1000701d, 0x77 }, - { 0x1000701e, 0x00 }, - { 0x1000701f, 0x10 }, - { 0x10007020, 0x13 }, - { 0x10007021, 0x07 }, - { 0x10007022, 0xc7 }, - { 0x10007023, 0x5f }, - { 0x10007024, 0x23 }, - { 0x10007025, 0xae }, - { 0x10007026, 0xe7 }, - { 0x10007027, 0xdc }, - { 0x10007028, 0x37 }, - { 0x10007029, 0x87 }, - { 0x1000702a, 0x00 }, - { 0x1000702b, 0x10 }, - { 0x1000702c, 0x13 }, - { 0x1000702d, 0x07 }, - { 0x1000702e, 0xc7 }, - { 0x1000702f, 0x86 }, - { 0x10007030, 0x23 }, - { 0x10007031, 0xae }, - { 0x10007032, 0xe7 }, - { 0x10007033, 0xe6 }, - { 0x10007034, 0x37 }, - { 0x10007035, 0x77 }, - { 0x10007036, 0x00 }, - { 0x10007037, 0x10 }, - { 0x10007038, 0x13 }, - { 0x10007039, 0x07 }, - { 0x1000703a, 0x07 }, - { 0x1000703b, 0x40 }, - { 0x1000703c, 0x23 }, - { 0x1000703d, 0xa6 }, - { 0x1000703e, 0xe7 }, - { 0x1000703f, 0xe8 }, - { 0x10007040, 0x37 }, - { 0x10007041, 0x77 }, - { 0x10007042, 0x00 }, - { 0x10007043, 0x10 }, - { 0x10007044, 0x13 }, - { 0x10007045, 0x07 }, - { 0x10007046, 0xc7 }, - { 0x10007047, 0x63 }, - { 0x10007048, 0x23 }, - { 0x10007049, 0xa2 }, - { 0x1000704a, 0xe7 }, - { 0x1000704b, 0xec }, - { 0x1000704c, 0x37 }, - { 0x1000704d, 0x77 }, - { 0x1000704e, 0x00 }, - { 0x1000704f, 0x10 }, - { 0x10007050, 0x13 }, - { 0x10007051, 0x07 }, - { 0x10007052, 0x47 }, - { 0x10007053, 0x6f }, - { 0x10007054, 0x23 }, - { 0x10007055, 0xa6 }, - { 0x10007056, 0xe7 }, - { 0x10007057, 0xec }, - { 0x10007058, 0x37 }, - { 0x10007059, 0x77 }, - { 0x1000705a, 0x00 }, - { 0x1000705b, 0x10 }, - { 0x1000705c, 0x13 }, - { 0x1000705d, 0x07 }, - { 0x1000705e, 0x07 }, - { 0x1000705f, 0x44 }, - { 0x10007060, 0x23 }, - { 0x10007061, 0xa8 }, - { 0x10007062, 0xe7 }, - { 0x10007063, 0xec }, - { 0x10007064, 0x37 }, - { 0x10007065, 0x87 }, - { 0x10007066, 0x00 }, - { 0x10007067, 0x10 }, - { 0x10007068, 0x13 }, - { 0x10007069, 0x07 }, - { 0x1000706a, 0x87 }, - { 0x1000706b, 0x84 }, - { 0x1000706c, 0x23 }, - { 0x1000706d, 0xa8 }, - { 0x1000706e, 0xe7 }, - { 0x1000706f, 0xee }, - { 0x10007070, 0x37 }, - { 0x10007071, 0x87 }, - { 0x10007072, 0x00 }, - { 0x10007073, 0x10 }, - { 0x10007074, 0x13 }, - { 0x10007075, 0x07 }, - { 0x10007076, 0x47 }, - { 0x10007077, 0x97 }, - { 0x10007078, 0x23 }, - { 0x10007079, 0xaa }, - { 0x1000707a, 0xe7 }, - { 0x1000707b, 0xee }, - { 0x1000707c, 0x67 }, - { 0x1000707d, 0x80 }, - { 0x1000707e, 0x00 }, - { 0x1000707f, 0x00 }, - { 0x10007400, 0xb7 }, - { 0x10007401, 0xd6 }, - { 0x10007402, 0x00 }, - { 0x10007403, 0x00 }, - { 0x10007404, 0x83 }, - { 0x10007405, 0xc7 }, - { 0x10007406, 0x06 }, - { 0x10007407, 0x47 }, - { 0x10007408, 0x93 }, - { 0x10007409, 0xf7 }, - { 0x1000740a, 0x87 }, - { 0x1000740b, 0x00 }, - { 0x1000740c, 0x63 }, - { 0x1000740d, 0x88 }, - { 0x1000740e, 0x07 }, - { 0x1000740f, 0x02 }, - { 0x10007410, 0x03 }, - { 0x10007411, 0xc7 }, - { 0x10007412, 0x31 }, - { 0x10007413, 0x43 }, - { 0x10007414, 0x63 }, - { 0x10007415, 0x14 }, - { 0x10007416, 0x07 }, - { 0x10007417, 0x02 }, - { 0x10007418, 0x13 }, - { 0x10007419, 0x07 }, - { 0x1000741a, 0x10 }, - { 0x1000741b, 0x00 }, - { 0x1000741c, 0xa3 }, - { 0x1000741d, 0x89 }, - { 0x1000741e, 0xe1 }, - { 0x1000741f, 0x42 }, - { 0x10007420, 0x37 }, - { 0x10007421, 0xc7 }, - { 0x10007422, 0x00 }, - { 0x10007423, 0x00 }, - { 0x10007424, 0x03 }, - { 0x10007425, 0x46 }, - { 0x10007426, 0x07 }, - { 0x10007427, 0x06 }, - { 0x10007428, 0x23 }, - { 0x10007429, 0x8a }, - { 0x1000742a, 0xc1 }, - { 0x1000742b, 0x42 }, - { 0x1000742c, 0x83 }, - { 0x1000742d, 0xc7 }, - { 0x1000742e, 0x46 }, - { 0x1000742f, 0x47 }, - { 0x10007430, 0x93 }, - { 0x10007431, 0xf7 }, - { 0x10007432, 0xf7 }, - { 0x10007433, 0x0f }, - { 0x10007434, 0x23 }, - { 0x10007435, 0x00 }, - { 0x10007436, 0xf7 }, - { 0x10007437, 0x06 }, - { 0x10007438, 0x23 }, - { 0x10007439, 0x89 }, - { 0x1000743a, 0x01 }, - { 0x1000743b, 0x42 }, - { 0x1000743c, 0x67 }, - { 0x1000743d, 0x80 }, - { 0x1000743e, 0x00 }, - { 0x1000743f, 0x00 }, - { 0x10007440, 0x37 }, - { 0x10007441, 0xc7 }, - { 0x10007442, 0x00 }, - { 0x10007443, 0x00 }, - { 0x10007444, 0x83 }, - { 0x10007445, 0x27 }, - { 0x10007446, 0xc7 }, - { 0x10007447, 0x5f }, - { 0x10007448, 0x13 }, - { 0x10007449, 0x05 }, - { 0x1000744a, 0x00 }, - { 0x1000744b, 0x00 }, - { 0x1000744c, 0x23 }, - { 0x1000744d, 0xa2 }, - { 0x1000744e, 0xf1 }, - { 0x1000744f, 0x42 }, - { 0x10007450, 0xb7 }, - { 0x10007451, 0x06 }, - { 0x10007452, 0x00 }, - { 0x10007453, 0x10 }, - { 0x10007454, 0xb3 }, - { 0x10007455, 0xf7 }, - { 0x10007456, 0xd7 }, - { 0x10007457, 0x00 }, - { 0x10007458, 0x63 }, - { 0x10007459, 0x86 }, - { 0x1000745a, 0x07 }, - { 0x1000745b, 0x02 }, - { 0x1000745c, 0x83 }, - { 0x1000745d, 0x47 }, - { 0x1000745e, 0x07 }, - { 0x1000745f, 0x56 }, - { 0x10007460, 0x93 }, - { 0x10007461, 0xf7 }, - { 0x10007462, 0x87 }, - { 0x10007463, 0x01 }, - { 0x10007464, 0x63 }, - { 0x10007465, 0x80 }, - { 0x10007466, 0x07 }, - { 0x10007467, 0x02 }, - { 0x10007468, 0x83 }, - { 0x10007469, 0x47 }, - { 0x1000746a, 0x17 }, - { 0x1000746b, 0x08 }, - { 0x1000746c, 0x93 }, - { 0x1000746d, 0xf7 }, - { 0x1000746e, 0x47 }, - { 0x1000746f, 0x00 }, - { 0x10007470, 0x63 }, - { 0x10007471, 0x8a }, - { 0x10007472, 0x07 }, - { 0x10007473, 0x00 }, - { 0x10007474, 0xb7 }, - { 0x10007475, 0xc7 }, - { 0x10007476, 0xc2 }, - { 0x10007477, 0x3f }, - { 0x10007478, 0x03 }, - { 0x10007479, 0xa5 }, - { 0x1000747a, 0x47 }, - { 0x1000747b, 0xfc }, - { 0x1000747c, 0x13 }, - { 0x1000747d, 0x55 }, - { 0x1000747e, 0x25 }, - { 0x1000747f, 0x00 }, - { 0x10007480, 0x13 }, - { 0x10007481, 0x75 }, - { 0x10007482, 0x15 }, - { 0x10007483, 0x00 }, - { 0x10007484, 0x67 }, - { 0x10007485, 0x80 }, - { 0x10007486, 0x00 }, - { 0x10007487, 0x00 }, - { 0x10007488, 0x03 }, - { 0x10007489, 0xa7 }, - { 0x1000748a, 0x81 }, - { 0x1000748b, 0x57 }, - { 0x1000748c, 0x13 }, - { 0x1000748d, 0x01 }, - { 0x1000748e, 0x01 }, - { 0x1000748f, 0xff }, - { 0x10007490, 0x23 }, - { 0x10007491, 0x26 }, - { 0x10007492, 0x11 }, - { 0x10007493, 0x00 }, - { 0x10007494, 0x23 }, - { 0x10007495, 0x24 }, - { 0x10007496, 0x81 }, - { 0x10007497, 0x00 }, - { 0x10007498, 0x23 }, - { 0x10007499, 0x22 }, - { 0x1000749a, 0x91 }, - { 0x1000749b, 0x00 }, - { 0x1000749c, 0x93 }, - { 0x1000749d, 0x07 }, - { 0x1000749e, 0xa0 }, - { 0x1000749f, 0x05 }, - { 0x100074a0, 0x63 }, - { 0x100074a1, 0x14 }, - { 0x100074a2, 0xf7 }, - { 0x100074a3, 0x04 }, - { 0x100074a4, 0x37 }, - { 0x100074a5, 0x07 }, - { 0x100074a6, 0x00 }, - { 0x100074a7, 0x11 }, - { 0x100074a8, 0x83 }, - { 0x100074a9, 0x47 }, - { 0x100074aa, 0x07 }, - { 0x100074ab, 0x01 }, - { 0x100074ac, 0x13 }, - { 0x100074ad, 0x06 }, - { 0x100074ae, 0x30 }, - { 0x100074af, 0x00 }, - { 0x100074b0, 0x93 }, - { 0x100074b1, 0xf7 }, - { 0x100074b2, 0xf7 }, - { 0x100074b3, 0x0f }, - { 0x100074b4, 0x63 }, - { 0x100074b5, 0x9a }, - { 0x100074b6, 0xc7 }, - { 0x100074b7, 0x02 }, - { 0x100074b8, 0x03 }, - { 0x100074b9, 0x47 }, - { 0x100074ba, 0x87 }, - { 0x100074bb, 0x01 }, - { 0x100074bc, 0x13 }, - { 0x100074bd, 0x77 }, - { 0x100074be, 0xf7 }, - { 0x100074bf, 0x0f }, - { 0x100074c0, 0x63 }, - { 0x100074c1, 0x14 }, - { 0x100074c2, 0xf7 }, - { 0x100074c3, 0x02 }, - { 0x100074c4, 0x37 }, - { 0x100074c5, 0xd7 }, - { 0x100074c6, 0x00 }, - { 0x100074c7, 0x00 }, - { 0x100074c8, 0x83 }, - { 0x100074c9, 0x47 }, - { 0x100074ca, 0x37 }, - { 0x100074cb, 0x54 }, - { 0x100074cc, 0x93 }, - { 0x100074cd, 0xf7 }, - { 0x100074ce, 0xf7 }, - { 0x100074cf, 0x0f }, - { 0x100074d0, 0x93 }, - { 0x100074d1, 0xe7 }, - { 0x100074d2, 0x07 }, - { 0x100074d3, 0x02 }, - { 0x100074d4, 0xa3 }, - { 0x100074d5, 0x01 }, - { 0x100074d6, 0xf7 }, - { 0x100074d7, 0x54 }, - { 0x100074d8, 0x83 }, - { 0x100074d9, 0x47 }, - { 0x100074da, 0x37 }, - { 0x100074db, 0x54 }, - { 0x100074dc, 0x93 }, - { 0x100074dd, 0xf7 }, - { 0x100074de, 0xf7 }, - { 0x100074df, 0x0d }, - { 0x100074e0, 0xa3 }, - { 0x100074e1, 0x01 }, - { 0x100074e2, 0xf7 }, - { 0x100074e3, 0x54 }, - { 0x100074e4, 0x23 }, - { 0x100074e5, 0xac }, - { 0x100074e6, 0x01 }, - { 0x100074e7, 0x56 }, - { 0x100074e8, 0x37 }, - { 0x100074e9, 0xd4 }, - { 0x100074ea, 0x00 }, - { 0x100074eb, 0x00 }, - { 0x100074ec, 0x83 }, - { 0x100074ed, 0x47 }, - { 0x100074ee, 0xd4 }, - { 0x100074ef, 0x47 }, - { 0x100074f0, 0x93 }, - { 0x100074f1, 0xf7 }, - { 0x100074f2, 0x17 }, - { 0x100074f3, 0x00 }, - { 0x100074f4, 0x63 }, - { 0x100074f5, 0x80 }, - { 0x100074f6, 0x07 }, - { 0x100074f7, 0x06 }, - { 0x100074f8, 0x37 }, - { 0x100074f9, 0xd7 }, - { 0x100074fa, 0x00 }, - { 0x100074fb, 0x10 }, - { 0x100074fc, 0x83 }, - { 0x100074fd, 0x47 }, - { 0x100074fe, 0x77 }, - { 0x100074ff, 0xd9 }, - { 0x10007500, 0x93 }, - { 0x10007501, 0x87 }, - { 0x10007502, 0x17 }, - { 0x10007503, 0x00 }, - { 0x10007504, 0x93 }, - { 0x10007505, 0xf7 }, - { 0x10007506, 0xf7 }, - { 0x10007507, 0x0f }, - { 0x10007508, 0xa3 }, - { 0x10007509, 0x0b }, - { 0x1000750a, 0xf7 }, - { 0x1000750b, 0xd8 }, - { 0x1000750c, 0x03 }, - { 0x1000750d, 0x47 }, - { 0x1000750e, 0x77 }, - { 0x1000750f, 0xd9 }, - { 0x10007510, 0x83 }, - { 0x10007511, 0x47 }, - { 0x10007512, 0xc4 }, - { 0x10007513, 0x47 }, - { 0x10007514, 0x13 }, - { 0x10007515, 0x77 }, - { 0x10007516, 0xf7 }, - { 0x10007517, 0x0f }, - { 0x10007518, 0x93 }, - { 0x10007519, 0xf7 }, - { 0x1000751a, 0xf7 }, - { 0x1000751b, 0x0f }, - { 0x1000751c, 0x63 }, - { 0x1000751d, 0x6c }, - { 0x1000751e, 0xf7 }, - { 0x1000751f, 0x02 }, - { 0x10007520, 0xb7 }, - { 0x10007521, 0xf4 }, - { 0x10007522, 0x00 }, - { 0x10007523, 0x00 }, - { 0x10007524, 0x93 }, - { 0x10007525, 0x05 }, - { 0x10007526, 0x00 }, - { 0x10007527, 0x01 }, - { 0x10007528, 0x13 }, - { 0x10007529, 0x85 }, - { 0x1000752a, 0x34 }, - { 0x1000752b, 0x52 }, - { 0x1000752c, 0xef }, - { 0x1000752d, 0xa0 }, - { 0x1000752e, 0x8f }, - { 0x1000752f, 0xc6 }, - { 0x10007530, 0x93 }, - { 0x10007531, 0x05 }, - { 0x10007532, 0x00 }, - { 0x10007533, 0x00 }, - { 0x10007534, 0x13 }, - { 0x10007535, 0x85 }, - { 0x10007536, 0x54 }, - { 0x10007537, 0x10 }, - { 0x10007538, 0xef }, - { 0x10007539, 0xa0 }, - { 0x1000753a, 0xcf }, - { 0x1000753b, 0xc5 }, - { 0x1000753c, 0x93 }, - { 0x1000753d, 0x05 }, - { 0x1000753e, 0x00 }, - { 0x1000753f, 0x00 }, - { 0x10007540, 0x13 }, - { 0x10007541, 0x85 }, - { 0x10007542, 0x74 }, - { 0x10007543, 0x10 }, - { 0x10007544, 0xef }, - { 0x10007545, 0xa0 }, - { 0x10007546, 0x0f }, - { 0x10007547, 0xc5 }, - { 0x10007548, 0x83 }, - { 0x10007549, 0x47 }, - { 0x1000754a, 0xd4 }, - { 0x1000754b, 0x47 }, - { 0x1000754c, 0x93 }, - { 0x1000754d, 0xf7 }, - { 0x1000754e, 0xe7 }, - { 0x1000754f, 0x0f }, - { 0x10007550, 0xa3 }, - { 0x10007551, 0x0e }, - { 0x10007552, 0xf4 }, - { 0x10007553, 0x46 }, - { 0x10007554, 0x83 }, - { 0x10007555, 0x20 }, - { 0x10007556, 0xc1 }, - { 0x10007557, 0x00 }, - { 0x10007558, 0x03 }, - { 0x10007559, 0x24 }, - { 0x1000755a, 0x81 }, - { 0x1000755b, 0x00 }, - { 0x1000755c, 0x83 }, - { 0x1000755d, 0x24 }, - { 0x1000755e, 0x41 }, - { 0x1000755f, 0x00 }, - { 0x10007560, 0x13 }, - { 0x10007561, 0x01 }, - { 0x10007562, 0x01 }, - { 0x10007563, 0x01 }, - { 0x10007564, 0x67 }, - { 0x10007565, 0x80 }, - { 0x10007566, 0x00 }, - { 0x10007567, 0x00 }, - { 0x10007568, 0x13 }, - { 0x10007569, 0x01 }, - { 0x1000756a, 0x01 }, - { 0x1000756b, 0xff }, - { 0x1000756c, 0x23 }, - { 0x1000756d, 0x24 }, - { 0x1000756e, 0x81 }, - { 0x1000756f, 0x00 }, - { 0x10007570, 0x23 }, - { 0x10007571, 0x26 }, - { 0x10007572, 0x11 }, - { 0x10007573, 0x00 }, - { 0x10007574, 0x23 }, - { 0x10007575, 0x22 }, - { 0x10007576, 0x91 }, - { 0x10007577, 0x00 }, - { 0x10007578, 0x37 }, - { 0x10007579, 0xd4 }, - { 0x1000757a, 0x00 }, - { 0x1000757b, 0x00 }, - { 0x1000757c, 0x83 }, - { 0x1000757d, 0x47 }, - { 0x1000757e, 0x04 }, - { 0x1000757f, 0x54 }, - { 0x10007580, 0x93 }, - { 0x10007581, 0x97 }, - { 0x10007582, 0x87 }, - { 0x10007583, 0x01 }, - { 0x10007584, 0x93 }, - { 0x10007585, 0xd7 }, - { 0x10007586, 0x87 }, - { 0x10007587, 0x41 }, - { 0x10007588, 0x63 }, - { 0x10007589, 0xd0 }, - { 0x1000758a, 0x07 }, - { 0x1000758b, 0x06 }, - { 0x1000758c, 0xb7 }, - { 0x1000758d, 0xf4 }, - { 0x1000758e, 0x00 }, - { 0x1000758f, 0x00 }, - { 0x10007590, 0x93 }, - { 0x10007591, 0x05 }, - { 0x10007592, 0x60 }, - { 0x10007593, 0x01 }, - { 0x10007594, 0x13 }, - { 0x10007595, 0x85 }, - { 0x10007596, 0x34 }, - { 0x10007597, 0x52 }, - { 0x10007598, 0xef }, - { 0x10007599, 0xa0 }, - { 0x1000759a, 0xcf }, - { 0x1000759b, 0xbf }, - { 0x1000759c, 0x93 }, - { 0x1000759d, 0x05 }, - { 0x1000759e, 0x00 }, - { 0x1000759f, 0x04 }, - { 0x100075a0, 0x13 }, - { 0x100075a1, 0x85 }, - { 0x100075a2, 0x54 }, - { 0x100075a3, 0x10 }, - { 0x100075a4, 0xef }, - { 0x100075a5, 0xa0 }, - { 0x100075a6, 0x0f }, - { 0x100075a7, 0xbf }, - { 0x100075a8, 0x93 }, - { 0x100075a9, 0x05 }, - { 0x100075aa, 0x00 }, - { 0x100075ab, 0x04 }, - { 0x100075ac, 0x13 }, - { 0x100075ad, 0x85 }, - { 0x100075ae, 0x74 }, - { 0x100075af, 0x10 }, - { 0x100075b0, 0xef }, - { 0x100075b1, 0xa0 }, - { 0x100075b2, 0x4f }, - { 0x100075b3, 0xbe }, - { 0x100075b4, 0x83 }, - { 0x100075b5, 0x47 }, - { 0x100075b6, 0xd4 }, - { 0x100075b7, 0x47 }, - { 0x100075b8, 0x37 }, - { 0x100075b9, 0xd7 }, - { 0x100075ba, 0x00 }, - { 0x100075bb, 0x10 }, - { 0x100075bc, 0x93 }, - { 0x100075bd, 0xf7 }, - { 0x100075be, 0xf7 }, - { 0x100075bf, 0x0f }, - { 0x100075c0, 0x93 }, - { 0x100075c1, 0xe7 }, - { 0x100075c2, 0x17 }, - { 0x100075c3, 0x00 }, - { 0x100075c4, 0xa3 }, - { 0x100075c5, 0x0e }, - { 0x100075c6, 0xf4 }, - { 0x100075c7, 0x46 }, - { 0x100075c8, 0xa3 }, - { 0x100075c9, 0x0b }, - { 0x100075ca, 0x07 }, - { 0x100075cb, 0xd8 }, - { 0x100075cc, 0x83 }, - { 0x100075cd, 0x47 }, - { 0x100075ce, 0x87 }, - { 0x100075cf, 0xd9 }, - { 0x100075d0, 0x93 }, - { 0x100075d1, 0x87 }, - { 0x100075d2, 0x17 }, - { 0x100075d3, 0x00 }, - { 0x100075d4, 0x93 }, - { 0x100075d5, 0xf7 }, - { 0x100075d6, 0xf7 }, - { 0x100075d7, 0x0f }, - { 0x100075d8, 0x23 }, - { 0x100075d9, 0x0c }, - { 0x100075da, 0xf7 }, - { 0x100075db, 0xd8 }, - { 0x100075dc, 0x83 }, - { 0x100075dd, 0x47 }, - { 0x100075de, 0x04 }, - { 0x100075df, 0x54 }, - { 0x100075e0, 0x93 }, - { 0x100075e1, 0xf7 }, - { 0x100075e2, 0xf7 }, - { 0x100075e3, 0x07 }, - { 0x100075e4, 0x23 }, - { 0x100075e5, 0x00 }, - { 0x100075e6, 0xf4 }, - { 0x100075e7, 0x54 }, - { 0x100075e8, 0x83 }, - { 0x100075e9, 0x20 }, - { 0x100075ea, 0xc1 }, - { 0x100075eb, 0x00 }, - { 0x100075ec, 0x03 }, - { 0x100075ed, 0x24 }, - { 0x100075ee, 0x81 }, - { 0x100075ef, 0x00 }, - { 0x100075f0, 0x83 }, - { 0x100075f1, 0x24 }, - { 0x100075f2, 0x41 }, - { 0x100075f3, 0x00 }, - { 0x100075f4, 0x13 }, - { 0x100075f5, 0x01 }, - { 0x100075f6, 0x01 }, - { 0x100075f7, 0x01 }, - { 0x100075f8, 0x67 }, - { 0x100075f9, 0x80 }, - { 0x100075fa, 0x00 }, - { 0x100075fb, 0x00 }, - { 0x100075fc, 0x13 }, - { 0x100075fd, 0x01 }, - { 0x100075fe, 0x01 }, - { 0x100075ff, 0xff }, - { 0x10007600, 0x23 }, - { 0x10007601, 0x24 }, - { 0x10007602, 0x81 }, - { 0x10007603, 0x00 }, - { 0x10007604, 0x37 }, - { 0x10007605, 0xd4 }, - { 0x10007606, 0x00 }, - { 0x10007607, 0x00 }, - { 0x10007608, 0x83 }, - { 0x10007609, 0x27 }, - { 0x1000760a, 0x04 }, - { 0x1000760b, 0x53 }, - { 0x1000760c, 0x23 }, - { 0x1000760d, 0x22 }, - { 0x1000760e, 0x91 }, - { 0x1000760f, 0x00 }, - { 0x10007610, 0xb7 }, - { 0x10007611, 0x04 }, - { 0x10007612, 0x00 }, - { 0x10007613, 0x40 }, - { 0x10007614, 0x23 }, - { 0x10007615, 0x26 }, - { 0x10007616, 0x11 }, - { 0x10007617, 0x00 }, - { 0x10007618, 0xb3 }, - { 0x10007619, 0xf7 }, - { 0x1000761a, 0x97 }, - { 0x1000761b, 0x00 }, - { 0x1000761c, 0x63 }, - { 0x1000761d, 0x86 }, - { 0x1000761e, 0x07 }, - { 0x1000761f, 0x00 }, - { 0x10007620, 0xef }, - { 0x10007621, 0xd0 }, - { 0x10007622, 0x5f }, - { 0x10007623, 0xc2 }, - { 0x10007624, 0x23 }, - { 0x10007625, 0x28 }, - { 0x10007626, 0x94 }, - { 0x10007627, 0x52 }, - { 0x10007628, 0x83 }, - { 0x10007629, 0x20 }, - { 0x1000762a, 0xc1 }, - { 0x1000762b, 0x00 }, - { 0x1000762c, 0x03 }, - { 0x1000762d, 0x24 }, - { 0x1000762e, 0x81 }, - { 0x1000762f, 0x00 }, - { 0x10007630, 0x83 }, - { 0x10007631, 0x24 }, - { 0x10007632, 0x41 }, - { 0x10007633, 0x00 }, - { 0x10007634, 0x13 }, - { 0x10007635, 0x01 }, - { 0x10007636, 0x01 }, - { 0x10007637, 0x01 }, - { 0x10007638, 0x67 }, - { 0x10007639, 0x80 }, - { 0x1000763a, 0x00 }, - { 0x1000763b, 0x00 }, - { 0x1000763c, 0x37 }, - { 0x1000763d, 0xc7 }, - { 0x1000763e, 0x00 }, - { 0x1000763f, 0x00 }, - { 0x10007640, 0x83 }, - { 0x10007641, 0x27 }, - { 0x10007642, 0xc7 }, - { 0x10007643, 0x5f }, - { 0x10007644, 0x23 }, - { 0x10007645, 0xa2 }, - { 0x10007646, 0xf1 }, - { 0x10007647, 0x42 }, - { 0x10007648, 0xb7 }, - { 0x10007649, 0x06 }, - { 0x1000764a, 0x00 }, - { 0x1000764b, 0x10 }, - { 0x1000764c, 0xb3 }, - { 0x1000764d, 0xf7 }, - { 0x1000764e, 0xd7 }, - { 0x1000764f, 0x00 }, - { 0x10007650, 0x63 }, - { 0x10007651, 0x80 }, - { 0x10007652, 0x07 }, - { 0x10007653, 0x0a }, - { 0x10007654, 0x83 }, - { 0x10007655, 0x47 }, - { 0x10007656, 0x07 }, - { 0x10007657, 0x56 }, - { 0x10007658, 0x93 }, - { 0x10007659, 0xf7 }, - { 0x1000765a, 0x87 }, - { 0x1000765b, 0x01 }, - { 0x1000765c, 0x63 }, - { 0x1000765d, 0x8a }, - { 0x1000765e, 0x07 }, - { 0x1000765f, 0x08 }, - { 0x10007660, 0x83 }, - { 0x10007661, 0x47 }, - { 0x10007662, 0x17 }, - { 0x10007663, 0x08 }, - { 0x10007664, 0x93 }, - { 0x10007665, 0xf7 }, - { 0x10007666, 0x47 }, - { 0x10007667, 0x00 }, - { 0x10007668, 0x63 }, - { 0x10007669, 0x84 }, - { 0x1000766a, 0x07 }, - { 0x1000766b, 0x08 }, - { 0x1000766c, 0x13 }, - { 0x1000766d, 0x01 }, - { 0x1000766e, 0x01 }, - { 0x1000766f, 0xff }, - { 0x10007670, 0x23 }, - { 0x10007671, 0x26 }, - { 0x10007672, 0x11 }, - { 0x10007673, 0x00 }, - { 0x10007674, 0xb7 }, - { 0x10007675, 0xc7 }, - { 0x10007676, 0xc2 }, - { 0x10007677, 0x3f }, - { 0x10007678, 0x03 }, - { 0x10007679, 0xa7 }, - { 0x1000767a, 0x07 }, - { 0x1000767b, 0xfc }, - { 0x1000767c, 0x63 }, - { 0x1000767d, 0x10 }, - { 0x1000767e, 0x05 }, - { 0x1000767f, 0x06 }, - { 0x10007680, 0x13 }, - { 0x10007681, 0x67 }, - { 0x10007682, 0x07 }, - { 0x10007683, 0x20 }, - { 0x10007684, 0x23 }, - { 0x10007685, 0xa0 }, - { 0x10007686, 0xe7 }, - { 0x10007687, 0xfc }, - { 0x10007688, 0x03 }, - { 0x10007689, 0xa7 }, - { 0x1000768a, 0x07 }, - { 0x1000768b, 0xfc }, - { 0x1000768c, 0x13 }, - { 0x1000768d, 0x67 }, - { 0x1000768e, 0x07 }, - { 0x1000768f, 0x40 }, - { 0x10007690, 0x23 }, - { 0x10007691, 0xa0 }, - { 0x10007692, 0xe7 }, - { 0x10007693, 0xfc }, - { 0x10007694, 0x37 }, - { 0x10007695, 0xc7 }, - { 0x10007696, 0xc2 }, - { 0x10007697, 0x3f }, - { 0x10007698, 0x83 }, - { 0x10007699, 0x27 }, - { 0x1000769a, 0x07 }, - { 0x1000769b, 0xfc }, - { 0x1000769c, 0x13 }, - { 0x1000769d, 0x75 }, - { 0x1000769e, 0x15 }, - { 0x1000769f, 0x00 }, - { 0x100076a0, 0x13 }, - { 0x100076a1, 0x15 }, - { 0x100076a2, 0x85 }, - { 0x100076a3, 0x00 }, - { 0x100076a4, 0x93 }, - { 0x100076a5, 0xf7 }, - { 0x100076a6, 0xf7 }, - { 0x100076a7, 0xef }, - { 0x100076a8, 0x33 }, - { 0x100076a9, 0xe5 }, - { 0x100076aa, 0xa7 }, - { 0x100076ab, 0x00 }, - { 0x100076ac, 0x23 }, - { 0x100076ad, 0x20 }, - { 0x100076ae, 0xa7 }, - { 0x100076af, 0xfc }, - { 0x100076b0, 0x93 }, - { 0x100076b1, 0x05 }, - { 0x100076b2, 0x00 }, - { 0x100076b3, 0x00 }, - { 0x100076b4, 0x13 }, - { 0x100076b5, 0x05 }, - { 0x100076b6, 0xa0 }, - { 0x100076b7, 0x00 }, - { 0x100076b8, 0xef }, - { 0x100076b9, 0xe0 }, - { 0x100076ba, 0xcf }, - { 0x100076bb, 0xb6 }, - { 0x100076bc, 0x37 }, - { 0x100076bd, 0xf7 }, - { 0x100076be, 0x00 }, - { 0x100076bf, 0x00 }, - { 0x100076c0, 0x83 }, - { 0x100076c1, 0x47 }, - { 0x100076c2, 0x57 }, - { 0x100076c3, 0x01 }, - { 0x100076c4, 0x93 }, - { 0x100076c5, 0xf7 }, - { 0x100076c6, 0xf7 }, - { 0x100076c7, 0x0f }, - { 0x100076c8, 0x93 }, - { 0x100076c9, 0xe7 }, - { 0x100076ca, 0x47 }, - { 0x100076cb, 0x00 }, - { 0x100076cc, 0xa3 }, - { 0x100076cd, 0x0a }, - { 0x100076ce, 0xf7 }, - { 0x100076cf, 0x00 }, - { 0x100076d0, 0x83 }, - { 0x100076d1, 0x20 }, - { 0x100076d2, 0xc1 }, - { 0x100076d3, 0x00 }, - { 0x100076d4, 0x13 }, - { 0x100076d5, 0x01 }, - { 0x100076d6, 0x01 }, - { 0x100076d7, 0x01 }, - { 0x100076d8, 0x67 }, - { 0x100076d9, 0x80 }, - { 0x100076da, 0x00 }, - { 0x100076db, 0x00 }, - { 0x100076dc, 0x13 }, - { 0x100076dd, 0x77 }, - { 0x100076de, 0xf7 }, - { 0x100076df, 0xdf }, - { 0x100076e0, 0x23 }, - { 0x100076e1, 0xa0 }, - { 0x100076e2, 0xe7 }, - { 0x100076e3, 0xfc }, - { 0x100076e4, 0x03 }, - { 0x100076e5, 0xa7 }, - { 0x100076e6, 0x07 }, - { 0x100076e7, 0xfc }, - { 0x100076e8, 0x13 }, - { 0x100076e9, 0x77 }, - { 0x100076ea, 0xf7 }, - { 0x100076eb, 0xbf }, - { 0x100076ec, 0x6f }, - { 0x100076ed, 0xf0 }, - { 0x100076ee, 0x5f }, - { 0x100076ef, 0xfa }, - { 0x100076f0, 0x67 }, - { 0x100076f1, 0x80 }, - { 0x100076f2, 0x00 }, - { 0x100076f3, 0x00 }, - { 0x100076f4, 0xb7 }, - { 0x100076f5, 0xc7 }, - { 0x100076f6, 0x00 }, - { 0x100076f7, 0x00 }, - { 0x100076f8, 0x03 }, - { 0x100076f9, 0xc7 }, - { 0x100076fa, 0x87 }, - { 0x100076fb, 0x59 }, - { 0x100076fc, 0x13 }, - { 0x100076fd, 0x77 }, - { 0x100076fe, 0xf7 }, - { 0x100076ff, 0x0f }, - { 0x10007700, 0x13 }, - { 0x10007701, 0x67 }, - { 0x10007702, 0x17 }, - { 0x10007703, 0x00 }, - { 0x10007704, 0x23 }, - { 0x10007705, 0x8c }, - { 0x10007706, 0xe7 }, - { 0x10007707, 0x58 }, - { 0x10007708, 0x03 }, - { 0x10007709, 0xc7 }, - { 0x1000770a, 0x77 }, - { 0x1000770b, 0x04 }, - { 0x1000770c, 0x13 }, - { 0x1000770d, 0x17 }, - { 0x1000770e, 0x87 }, - { 0x1000770f, 0x01 }, - { 0x10007710, 0x13 }, - { 0x10007711, 0x57 }, - { 0x10007712, 0x87 }, - { 0x10007713, 0x41 }, - { 0x10007714, 0x63 }, - { 0x10007715, 0x58 }, - { 0x10007716, 0x07 }, - { 0x10007717, 0x12 }, - { 0x10007718, 0x37 }, - { 0x10007719, 0xd7 }, - { 0x1000771a, 0x00 }, - { 0x1000771b, 0x00 }, - { 0x1000771c, 0x83 }, - { 0x1000771d, 0x26 }, - { 0x1000771e, 0x87 }, - { 0x1000771f, 0x53 }, - { 0x10007720, 0x37 }, - { 0x10007721, 0x06 }, - { 0x10007722, 0x00 }, - { 0x10007723, 0x40 }, - { 0x10007724, 0x93 }, - { 0x10007725, 0x05 }, - { 0x10007726, 0x80 }, - { 0x10007727, 0x01 }, - { 0x10007728, 0xb3 }, - { 0x10007729, 0xe6 }, - { 0x1000772a, 0xc6 }, - { 0x1000772b, 0x00 }, - { 0x1000772c, 0x23 }, - { 0x1000772d, 0x2c }, - { 0x1000772e, 0xd7 }, - { 0x1000772f, 0x52 }, - { 0x10007730, 0x83 }, - { 0x10007731, 0xc6 }, - { 0x10007732, 0x07 }, - { 0x10007733, 0x56 }, - { 0x10007734, 0x93 }, - { 0x10007735, 0xf6 }, - { 0x10007736, 0xf6 }, - { 0x10007737, 0x0f }, - { 0x10007738, 0x63 }, - { 0x10007739, 0x9c }, - { 0x1000773a, 0xb6 }, - { 0x1000773b, 0x0e }, - { 0x1000773c, 0x83 }, - { 0x1000773d, 0x27 }, - { 0x1000773e, 0x87 }, - { 0x1000773f, 0x53 }, - { 0x10007740, 0xb3 }, - { 0x10007741, 0xf7 }, - { 0x10007742, 0xc7 }, - { 0x10007743, 0x00 }, - { 0x10007744, 0x63 }, - { 0x10007745, 0x80 }, - { 0x10007746, 0x07 }, - { 0x10007747, 0x10 }, - { 0x10007748, 0x13 }, - { 0x10007749, 0x01 }, - { 0x1000774a, 0x01 }, - { 0x1000774b, 0xff }, - { 0x1000774c, 0x23 }, - { 0x1000774d, 0x24 }, - { 0x1000774e, 0x81 }, - { 0x1000774f, 0x00 }, - { 0x10007750, 0x83 }, - { 0x10007751, 0xa7 }, - { 0x10007752, 0x41 }, - { 0x10007753, 0x58 }, - { 0x10007754, 0x23 }, - { 0x10007755, 0x26 }, - { 0x10007756, 0x11 }, - { 0x10007757, 0x00 }, - { 0x10007758, 0x63 }, - { 0x10007759, 0x94 }, - { 0x1000775a, 0x07 }, - { 0x1000775b, 0x0c }, - { 0x1000775c, 0x83 }, - { 0x1000775d, 0x27 }, - { 0x1000775e, 0x07 }, - { 0x1000775f, 0x53 }, - { 0x10007760, 0x03 }, - { 0x10007761, 0xc6 }, - { 0x10007762, 0xb1 }, - { 0x10007763, 0x42 }, - { 0x10007764, 0x93 }, - { 0x10007765, 0xd7 }, - { 0x10007766, 0xe7 }, - { 0x10007767, 0x01 }, - { 0x10007768, 0x93 }, - { 0x10007769, 0xf7 }, - { 0x1000776a, 0x17 }, - { 0x1000776b, 0x00 }, - { 0x1000776c, 0x93 }, - { 0x1000776d, 0x06 }, - { 0x1000776e, 0x10 }, - { 0x1000776f, 0x00 }, - { 0x10007770, 0x63 }, - { 0x10007771, 0x14 }, - { 0x10007772, 0x06 }, - { 0x10007773, 0x00 }, - { 0x10007774, 0xb3 }, - { 0x10007775, 0x86 }, - { 0x10007776, 0xf6 }, - { 0x10007777, 0x40 }, - { 0x10007778, 0xa3 }, - { 0x10007779, 0x85 }, - { 0x1000777a, 0xd1 }, - { 0x1000777b, 0x42 }, - { 0x1000777c, 0x03 }, - { 0x1000777d, 0xc6 }, - { 0x1000777e, 0xa1 }, - { 0x1000777f, 0x42 }, - { 0x10007780, 0x93 }, - { 0x10007781, 0x06 }, - { 0x10007782, 0x10 }, - { 0x10007783, 0x00 }, - { 0x10007784, 0x63 }, - { 0x10007785, 0x14 }, - { 0x10007786, 0x06 }, - { 0x10007787, 0x00 }, - { 0x10007788, 0xb3 }, - { 0x10007789, 0x86 }, - { 0x1000778a, 0xf6 }, - { 0x1000778b, 0x40 }, - { 0x1000778c, 0x23 }, - { 0x1000778d, 0x85 }, - { 0x1000778e, 0xd1 }, - { 0x1000778f, 0x42 }, - { 0x10007790, 0x03 }, - { 0x10007791, 0xc6 }, - { 0x10007792, 0x91 }, - { 0x10007793, 0x42 }, - { 0x10007794, 0x93 }, - { 0x10007795, 0x06 }, - { 0x10007796, 0x10 }, - { 0x10007797, 0x00 }, - { 0x10007798, 0x63 }, - { 0x10007799, 0x14 }, - { 0x1000779a, 0x06 }, - { 0x1000779b, 0x00 }, - { 0x1000779c, 0xb3 }, - { 0x1000779d, 0x86 }, - { 0x1000779e, 0xf6 }, - { 0x1000779f, 0x40 }, - { 0x100077a0, 0xa3 }, - { 0x100077a1, 0x84 }, - { 0x100077a2, 0xd1 }, - { 0x100077a3, 0x42 }, - { 0x100077a4, 0x03 }, - { 0x100077a5, 0xc6 }, - { 0x100077a6, 0x81 }, - { 0x100077a7, 0x42 }, - { 0x100077a8, 0x93 }, - { 0x100077a9, 0x06 }, - { 0x100077aa, 0x10 }, - { 0x100077ab, 0x00 }, - { 0x100077ac, 0x63 }, - { 0x100077ad, 0x14 }, - { 0x100077ae, 0x06 }, - { 0x100077af, 0x00 }, - { 0x100077b0, 0xb3 }, - { 0x100077b1, 0x86 }, - { 0x100077b2, 0xf6 }, - { 0x100077b3, 0x40 }, - { 0x100077b4, 0x23 }, - { 0x100077b5, 0x84 }, - { 0x100077b6, 0xd1 }, - { 0x100077b7, 0x42 }, - { 0x100077b8, 0xb7 }, - { 0x100077b9, 0xd7 }, - { 0x100077ba, 0x00 }, - { 0x100077bb, 0x00 }, - { 0x100077bc, 0x83 }, - { 0x100077bd, 0xa7 }, - { 0x100077be, 0x07 }, - { 0x100077bf, 0x53 }, - { 0x100077c0, 0x37 }, - { 0x100077c1, 0x07 }, - { 0x100077c2, 0x00 }, - { 0x100077c3, 0x40 }, - { 0x100077c4, 0xb3 }, - { 0x100077c5, 0xf7 }, - { 0x100077c6, 0xe7 }, - { 0x100077c7, 0x00 }, - { 0x100077c8, 0x63 }, - { 0x100077c9, 0x8c }, - { 0x100077ca, 0x07 }, - { 0x100077cb, 0x04 }, - { 0x100077cc, 0xb7 }, - { 0x100077cd, 0x47 }, - { 0x100077ce, 0x0f }, - { 0x100077cf, 0x00 }, - { 0x100077d0, 0x93 }, - { 0x100077d1, 0x87 }, - { 0x100077d2, 0x17 }, - { 0x100077d3, 0x24 }, - { 0x100077d4, 0xb7 }, - { 0x100077d5, 0xf6 }, - { 0x100077d6, 0x00 }, - { 0x100077d7, 0x00 }, - { 0x100077d8, 0x03 }, - { 0x100077d9, 0xc7 }, - { 0x100077da, 0xf6 }, - { 0x100077db, 0x83 }, - { 0x100077dc, 0x13 }, - { 0x100077dd, 0x77 }, - { 0x100077de, 0x07 }, - { 0x100077df, 0x04 }, - { 0x100077e0, 0x63 }, - { 0x100077e1, 0x16 }, - { 0x100077e2, 0x07 }, - { 0x100077e3, 0x00 }, - { 0x100077e4, 0x93 }, - { 0x100077e5, 0x87 }, - { 0x100077e6, 0xf7 }, - { 0x100077e7, 0xff }, - { 0x100077e8, 0xe3 }, - { 0x100077e9, 0x98 }, - { 0x100077ea, 0x07 }, - { 0x100077eb, 0xfe }, - { 0x100077ec, 0x13 }, - { 0x100077ed, 0x05 }, - { 0x100077ee, 0x80 }, - { 0x100077ef, 0x3e }, - { 0x100077f0, 0x93 }, - { 0x100077f1, 0x05 }, - { 0x100077f2, 0x00 }, - { 0x100077f3, 0x00 }, - { 0x100077f4, 0xef }, - { 0x100077f5, 0xe0 }, - { 0x100077f6, 0x0f }, - { 0x100077f7, 0xa3 }, - { 0x100077f8, 0x37 }, - { 0x100077f9, 0xf7 }, - { 0x100077fa, 0x00 }, - { 0x100077fb, 0x00 }, - { 0x100077fc, 0x83 }, - { 0x100077fd, 0x47 }, - { 0x100077fe, 0xb7 }, - { 0x100077ff, 0x80 }, - { 0x10007800, 0x93 }, - { 0x10007801, 0xe7 }, - { 0x10007802, 0x07 }, - { 0x10007803, 0xf8 }, - { 0x10007804, 0x93 }, - { 0x10007805, 0xf7 }, - { 0x10007806, 0xf7 }, - { 0x10007807, 0x0f }, - { 0x10007808, 0xa3 }, - { 0x10007809, 0x05 }, - { 0x1000780a, 0xf7 }, - { 0x1000780b, 0x80 }, - { 0x1000780c, 0xb7 }, - { 0x1000780d, 0xd7 }, - { 0x1000780e, 0x00 }, - { 0x1000780f, 0x00 }, - { 0x10007810, 0x37 }, - { 0x10007811, 0x07 }, - { 0x10007812, 0x00 }, - { 0x10007813, 0x40 }, - { 0x10007814, 0x23 }, - { 0x10007815, 0xa8 }, - { 0x10007816, 0xe7 }, - { 0x10007817, 0x52 }, - { 0x10007818, 0x93 }, - { 0x10007819, 0x07 }, - { 0x1000781a, 0x10 }, - { 0x1000781b, 0x00 }, - { 0x1000781c, 0x23 }, - { 0x1000781d, 0xa2 }, - { 0x1000781e, 0xf1 }, - { 0x1000781f, 0x58 }, - { 0x10007820, 0x83 }, - { 0x10007821, 0x20 }, - { 0x10007822, 0xc1 }, - { 0x10007823, 0x00 }, - { 0x10007824, 0x03 }, - { 0x10007825, 0x24 }, - { 0x10007826, 0x81 }, - { 0x10007827, 0x00 }, - { 0x10007828, 0x13 }, - { 0x10007829, 0x01 }, - { 0x1000782a, 0x01 }, - { 0x1000782b, 0x01 }, - { 0x1000782c, 0x67 }, - { 0x1000782d, 0x80 }, - { 0x1000782e, 0x00 }, - { 0x1000782f, 0x00 }, - { 0x10007830, 0x83 }, - { 0x10007831, 0xc7 }, - { 0x10007832, 0x07 }, - { 0x10007833, 0x56 }, - { 0x10007834, 0x93 }, - { 0x10007835, 0xf7 }, - { 0x10007836, 0xf7 }, - { 0x10007837, 0x0f }, - { 0x10007838, 0x63 }, - { 0x10007839, 0x96 }, - { 0x1000783a, 0x07 }, - { 0x1000783b, 0x00 }, - { 0x1000783c, 0x23 }, - { 0x1000783d, 0xa2 }, - { 0x1000783e, 0x01 }, - { 0x1000783f, 0x58 }, - { 0x10007840, 0x67 }, - { 0x10007841, 0x80 }, - { 0x10007842, 0x00 }, - { 0x10007843, 0x00 }, - { 0x10007844, 0x67 }, - { 0x10007845, 0x80 }, - { 0x10007846, 0x00 }, - { 0x10007847, 0x00 }, - { 0x10007848, 0xb7 }, - { 0x10007849, 0xc7 }, - { 0x1000784a, 0x00 }, - { 0x1000784b, 0x00 }, - { 0x1000784c, 0x83 }, - { 0x1000784d, 0xc7 }, - { 0x1000784e, 0x07 }, - { 0x1000784f, 0x56 }, - { 0x10007850, 0x13 }, - { 0x10007851, 0x07 }, - { 0x10007852, 0x80 }, - { 0x10007853, 0x01 }, - { 0x10007854, 0x93 }, - { 0x10007855, 0xf7 }, - { 0x10007856, 0xf7 }, - { 0x10007857, 0x0f }, - { 0x10007858, 0x63 }, - { 0x10007859, 0x98 }, - { 0x1000785a, 0xe7 }, - { 0x1000785b, 0x00 }, - { 0x1000785c, 0x13 }, - { 0x1000785d, 0x05 }, - { 0x1000785e, 0x00 }, - { 0x1000785f, 0x7d }, - { 0x10007860, 0x93 }, - { 0x10007861, 0x05 }, - { 0x10007862, 0x00 }, - { 0x10007863, 0x00 }, - { 0x10007864, 0x6f }, - { 0x10007865, 0xe0 }, - { 0x10007866, 0x0f }, - { 0x10007867, 0x9c }, - { 0x10007868, 0x67 }, - { 0x10007869, 0x80 }, - { 0x1000786a, 0x00 }, - { 0x1000786b, 0x00 }, - { 0x1000786c, 0x13 }, - { 0x1000786d, 0x01 }, - { 0x1000786e, 0x01 }, - { 0x1000786f, 0xff }, - { 0x10007870, 0x23 }, - { 0x10007871, 0x26 }, - { 0x10007872, 0x11 }, - { 0x10007873, 0x00 }, - { 0x10007874, 0x23 }, - { 0x10007875, 0x24 }, - { 0x10007876, 0x81 }, - { 0x10007877, 0x00 }, - { 0x10007878, 0xef }, - { 0x10007879, 0xd0 }, - { 0x1000787a, 0x4f }, - { 0x1000787b, 0x91 }, - { 0x1000787c, 0x83 }, - { 0x1000787d, 0xc7 }, - { 0x1000787e, 0x81 }, - { 0x1000787f, 0x41 }, - { 0x10007880, 0x63 }, - { 0x10007881, 0x84 }, - { 0x10007882, 0x07 }, - { 0x10007883, 0x08 }, - { 0x10007884, 0xb7 }, - { 0x10007885, 0xd7 }, - { 0x10007886, 0x00 }, - { 0x10007887, 0x00 }, - { 0x10007888, 0x83 }, - { 0x10007889, 0xc7 }, - { 0x1000788a, 0x07 }, - { 0x1000788b, 0x47 }, - { 0x1000788c, 0x93 }, - { 0x1000788d, 0xf7 }, - { 0x1000788e, 0x07 }, - { 0x1000788f, 0x02 }, - { 0x10007890, 0x63 }, - { 0x10007891, 0x8a }, - { 0x10007892, 0x07 }, - { 0x10007893, 0x04 }, - { 0x10007894, 0x83 }, - { 0x10007895, 0xc7 }, - { 0x10007896, 0x11 }, - { 0x10007897, 0x44 }, - { 0x10007898, 0x93 }, - { 0x10007899, 0xf7 }, - { 0x1000789a, 0xd7 }, - { 0x1000789b, 0x0f }, - { 0x1000789c, 0x63 }, - { 0x1000789d, 0x90 }, - { 0x1000789e, 0x07 }, - { 0x1000789f, 0x02 }, - { 0x100078a0, 0x03 }, - { 0x100078a1, 0xc7 }, - { 0x100078a2, 0xd1 }, - { 0x100078a3, 0x58 }, - { 0x100078a4, 0xb7 }, - { 0x100078a5, 0x07 }, - { 0x100078a6, 0x00 }, - { 0x100078a7, 0x11 }, - { 0x100078a8, 0x23 }, - { 0x100078a9, 0x88 }, - { 0x100078aa, 0xe7 }, - { 0x100078ab, 0x00 }, - { 0x100078ac, 0x23 }, - { 0x100078ad, 0x88 }, - { 0x100078ae, 0xe7 }, - { 0x100078af, 0x20 }, - { 0x100078b0, 0x03 }, - { 0x100078b1, 0xc7 }, - { 0x100078b2, 0xc1 }, - { 0x100078b3, 0x58 }, - { 0x100078b4, 0x23 }, - { 0x100078b5, 0x8c }, - { 0x100078b6, 0xe7 }, - { 0x100078b7, 0x00 }, - { 0x100078b8, 0x6f }, - { 0x100078b9, 0x00 }, - { 0x100078ba, 0x80 }, - { 0x100078bb, 0x04 }, - { 0x100078bc, 0xb7 }, - { 0x100078bd, 0x07 }, - { 0x100078be, 0x00 }, - { 0x100078bf, 0x11 }, - { 0x100078c0, 0x23 }, - { 0x100078c1, 0x88 }, - { 0x100078c2, 0x07 }, - { 0x100078c3, 0x00 }, - { 0x100078c4, 0x23 }, - { 0x100078c5, 0x88 }, - { 0x100078c6, 0x07 }, - { 0x100078c7, 0x20 }, - { 0x100078c8, 0x23 }, - { 0x100078c9, 0x8c }, - { 0x100078ca, 0x07 }, - { 0x100078cb, 0x00 }, - { 0x100078cc, 0x23 }, - { 0x100078cd, 0x8c }, - { 0x100078ce, 0x07 }, - { 0x100078cf, 0x20 }, - { 0x100078d0, 0xef }, - { 0x100078d1, 0xb0 }, - { 0x100078d2, 0xcf }, - { 0x100078d3, 0xc4 }, - { 0x100078d4, 0x03 }, - { 0x100078d5, 0x24 }, - { 0x100078d6, 0x81 }, - { 0x100078d7, 0x00 }, - { 0x100078d8, 0x83 }, - { 0x100078d9, 0x20 }, - { 0x100078da, 0xc1 }, - { 0x100078db, 0x00 }, - { 0x100078dc, 0x13 }, - { 0x100078dd, 0x01 }, - { 0x100078de, 0x01 }, - { 0x100078df, 0x01 }, - { 0x100078e0, 0x6f }, - { 0x100078e1, 0xb0 }, - { 0x100078e2, 0xcf }, - { 0x100078e3, 0xcd }, - { 0x100078e4, 0x03 }, - { 0x100078e5, 0xc7 }, - { 0x100078e6, 0xd1 }, - { 0x100078e7, 0x58 }, - { 0x100078e8, 0xb7 }, - { 0x100078e9, 0x07 }, - { 0x100078ea, 0x00 }, - { 0x100078eb, 0x11 }, - { 0x100078ec, 0x23 }, - { 0x100078ed, 0x88 }, - { 0x100078ee, 0xe7 }, - { 0x100078ef, 0x00 }, - { 0x100078f0, 0x83 }, - { 0x100078f1, 0xc6 }, - { 0x100078f2, 0xc1 }, - { 0x100078f3, 0x58 }, - { 0x100078f4, 0x23 }, - { 0x100078f5, 0x88 }, - { 0x100078f6, 0xd7 }, - { 0x100078f7, 0x20 }, - { 0x100078f8, 0x23 }, - { 0x100078f9, 0x8c }, - { 0x100078fa, 0xd7 }, - { 0x100078fb, 0x00 }, - { 0x100078fc, 0x03 }, - { 0x100078fd, 0xc7 }, - { 0x100078fe, 0xc1 }, - { 0x100078ff, 0x58 }, - { 0x10007900, 0x23 }, - { 0x10007901, 0x8c }, - { 0x10007902, 0xe7 }, - { 0x10007903, 0x20 }, - { 0x10007904, 0x6f }, - { 0x10007905, 0xf0 }, - { 0x10007906, 0xdf }, - { 0x10007907, 0xfc }, - { 0x10007908, 0xb7 }, - { 0x10007909, 0x06 }, - { 0x1000790a, 0x00 }, - { 0x1000790b, 0x11 }, - { 0x1000790c, 0x03 }, - { 0x1000790d, 0xc7 }, - { 0x1000790e, 0x06 }, - { 0x1000790f, 0x21 }, - { 0x10007910, 0x03 }, - { 0x10007911, 0xc6 }, - { 0x10007912, 0xd1 }, - { 0x10007913, 0x58 }, - { 0x10007914, 0x13 }, - { 0x10007915, 0x84 }, - { 0x10007916, 0x07 }, - { 0x10007917, 0x00 }, - { 0x10007918, 0x13 }, - { 0x10007919, 0x77 }, - { 0x1000791a, 0xf7 }, - { 0x1000791b, 0x0f }, - { 0x1000791c, 0x63 }, - { 0x1000791d, 0x1a }, - { 0x1000791e, 0xe6 }, - { 0x1000791f, 0x00 }, - { 0x10007920, 0x83 }, - { 0x10007921, 0xc7 }, - { 0x10007922, 0x86 }, - { 0x10007923, 0x21 }, - { 0x10007924, 0x03 }, - { 0x10007925, 0xc7 }, - { 0x10007926, 0xc1 }, - { 0x10007927, 0x58 }, - { 0x10007928, 0x93 }, - { 0x10007929, 0xf7 }, - { 0x1000792a, 0xf7 }, - { 0x1000792b, 0x0f }, - { 0x1000792c, 0xe3 }, - { 0x1000792d, 0x02 }, - { 0x1000792e, 0xf7 }, - { 0x1000792f, 0xfa }, - { 0x10007930, 0xb7 }, - { 0x10007931, 0xc7 }, - { 0x10007932, 0x00 }, - { 0x10007933, 0x00 }, - { 0x10007934, 0x83 }, - { 0x10007935, 0xc7 }, - { 0x10007936, 0x07 }, - { 0x10007937, 0x56 }, - { 0x10007938, 0x13 }, - { 0x10007939, 0x07 }, - { 0x1000793a, 0xf0 }, - { 0x1000793b, 0x00 }, - { 0x1000793c, 0x93 }, - { 0x1000793d, 0xf7 }, - { 0x1000793e, 0xf7 }, - { 0x1000793f, 0x0f }, - { 0x10007940, 0xe3 }, - { 0x10007941, 0x78 }, - { 0x10007942, 0xf7 }, - { 0x10007943, 0xf8 }, - { 0x10007944, 0xb7 }, - { 0x10007945, 0xd7 }, - { 0x10007946, 0x00 }, - { 0x10007947, 0x00 }, - { 0x10007948, 0x83 }, - { 0x10007949, 0xc5 }, - { 0x1000794a, 0xa7 }, - { 0x1000794b, 0x47 }, - { 0x1000794c, 0x93 }, - { 0x1000794d, 0xf7 }, - { 0x1000794e, 0xf5 }, - { 0x1000794f, 0x0f }, - { 0x10007950, 0x93 }, - { 0x10007951, 0x95 }, - { 0x10007952, 0x57 }, - { 0x10007953, 0x00 }, - { 0x10007954, 0xb3 }, - { 0x10007955, 0x85 }, - { 0x10007956, 0xf5 }, - { 0x10007957, 0x40 }, - { 0x10007958, 0x93 }, - { 0x10007959, 0x95 }, - { 0x1000795a, 0x25 }, - { 0x1000795b, 0x00 }, - { 0x1000795c, 0xb3 }, - { 0x1000795d, 0x85 }, - { 0x1000795e, 0xf5 }, - { 0x1000795f, 0x00 }, - { 0x10007960, 0x13 }, - { 0x10007961, 0x95 }, - { 0x10007962, 0x35 }, - { 0x10007963, 0x00 }, - { 0x10007964, 0x93 }, - { 0x10007965, 0xd5 }, - { 0x10007966, 0xf5 }, - { 0x10007967, 0x41 }, - { 0x10007968, 0xef }, - { 0x10007969, 0xe0 }, - { 0x1000796a, 0xcf }, - { 0x1000796b, 0x8b }, - { 0x1000796c, 0x03 }, - { 0x1000796d, 0xc7 }, - { 0x1000796e, 0xd1 }, - { 0x1000796f, 0x58 }, - { 0x10007970, 0x6f }, - { 0x10007971, 0xf0 }, - { 0x10007972, 0x5f }, - { 0x10007973, 0xf3 }, - { 0x10007974, 0x13 }, - { 0x10007975, 0x01 }, - { 0x10007976, 0x01 }, - { 0x10007977, 0xfe }, - { 0x10007978, 0x23 }, - { 0x10007979, 0x2c }, - { 0x1000797a, 0x81 }, - { 0x1000797b, 0x00 }, - { 0x1000797c, 0x83 }, - { 0x1000797d, 0xc7 }, - { 0x1000797e, 0x21 }, - { 0x1000797f, 0x41 }, - { 0x10007980, 0x23 }, - { 0x10007981, 0x2e }, - { 0x10007982, 0x11 }, - { 0x10007983, 0x00 }, - { 0x10007984, 0x23 }, - { 0x10007985, 0x2a }, - { 0x10007986, 0x91 }, - { 0x10007987, 0x00 }, - { 0x10007988, 0x23 }, - { 0x10007989, 0x28 }, - { 0x1000798a, 0x21 }, - { 0x1000798b, 0x01 }, - { 0x1000798c, 0x23 }, - { 0x1000798d, 0x26 }, - { 0x1000798e, 0x31 }, - { 0x1000798f, 0x01 }, - { 0x10007990, 0x13 }, - { 0x10007991, 0x07 }, - { 0x10007992, 0x10 }, - { 0x10007993, 0x00 }, - { 0x10007994, 0x63 }, - { 0x10007995, 0x92 }, - { 0x10007996, 0xe7 }, - { 0x10007997, 0x02 }, - { 0x10007998, 0xa3 }, - { 0x10007999, 0x81 }, - { 0x1000799a, 0xf1 }, - { 0x1000799b, 0x40 }, - { 0x1000799c, 0x83 }, - { 0x1000799d, 0x20 }, - { 0x1000799e, 0xc1 }, - { 0x1000799f, 0x01 }, - { 0x100079a0, 0x03 }, - { 0x100079a1, 0x24 }, - { 0x100079a2, 0x81 }, - { 0x100079a3, 0x01 }, - { 0x100079a4, 0x83 }, - { 0x100079a5, 0x24 }, - { 0x100079a6, 0x41 }, - { 0x100079a7, 0x01 }, - { 0x100079a8, 0x03 }, - { 0x100079a9, 0x29 }, - { 0x100079aa, 0x01 }, - { 0x100079ab, 0x01 }, - { 0x100079ac, 0x83 }, - { 0x100079ad, 0x29 }, - { 0x100079ae, 0xc1 }, - { 0x100079af, 0x00 }, - { 0x100079b0, 0x13 }, - { 0x100079b1, 0x01 }, - { 0x100079b2, 0x01 }, - { 0x100079b3, 0x02 }, - { 0x100079b4, 0x67 }, - { 0x100079b5, 0x80 }, - { 0x100079b6, 0x00 }, - { 0x100079b7, 0x00 }, - { 0x100079b8, 0xe3 }, - { 0x100079b9, 0x92 }, - { 0x100079ba, 0x07 }, - { 0x100079bb, 0xfe }, - { 0x100079bc, 0x37 }, - { 0x100079bd, 0xc9 }, - { 0x100079be, 0x00 }, - { 0x100079bf, 0x00 }, - { 0x100079c0, 0x83 }, - { 0x100079c1, 0x47 }, - { 0x100079c2, 0x09 }, - { 0x100079c3, 0x56 }, - { 0x100079c4, 0x13 }, - { 0x100079c5, 0x07 }, - { 0x100079c6, 0x80 }, - { 0x100079c7, 0x01 }, - { 0x100079c8, 0x93 }, - { 0x100079c9, 0xf7 }, - { 0x100079ca, 0xf7 }, - { 0x100079cb, 0x0f }, - { 0x100079cc, 0xe3 }, - { 0x100079cd, 0x78 }, - { 0x100079ce, 0xf7 }, - { 0x100079cf, 0xfc }, - { 0x100079d0, 0x83 }, - { 0x100079d1, 0xc7 }, - { 0x100079d2, 0x31 }, - { 0x100079d3, 0x40 }, - { 0x100079d4, 0xe3 }, - { 0x100079d5, 0x84 }, - { 0x100079d6, 0x07 }, - { 0x100079d7, 0xfc }, - { 0x100079d8, 0xb7 }, - { 0x100079d9, 0xd4 }, - { 0x100079da, 0x00 }, - { 0x100079db, 0x00 }, - { 0x100079dc, 0x03 }, - { 0x100079dd, 0xc5 }, - { 0x100079de, 0x94 }, - { 0x100079df, 0x47 }, - { 0x100079e0, 0xb7 }, - { 0x100079e1, 0x15 }, - { 0x100079e2, 0x00 }, - { 0x100079e3, 0x00 }, - { 0x100079e4, 0x93 }, - { 0x100079e5, 0x85 }, - { 0x100079e6, 0x85 }, - { 0x100079e7, 0x38 }, - { 0x100079e8, 0x13 }, - { 0x100079e9, 0x75 }, - { 0x100079ea, 0xf5 }, - { 0x100079eb, 0x0f }, - { 0x100079ec, 0xef }, - { 0x100079ed, 0xe0 }, - { 0x100079ee, 0x5f }, - { 0x100079ef, 0xe0 }, - { 0x100079f0, 0x93 }, - { 0x100079f1, 0x55 }, - { 0x100079f2, 0xf5 }, - { 0x100079f3, 0x41 }, - { 0x100079f4, 0xef }, - { 0x100079f5, 0xe0 }, - { 0x100079f6, 0x0f }, - { 0x100079f7, 0x83 }, - { 0x100079f8, 0xa3 }, - { 0x100079f9, 0x81 }, - { 0x100079fa, 0x01 }, - { 0x100079fb, 0x40 }, - { 0x100079fc, 0x83 }, - { 0x100079fd, 0x27 }, - { 0x100079fe, 0xc9 }, - { 0x100079ff, 0x5f }, - { 0x10007a00, 0x37 }, - { 0x10007a01, 0x07 }, - { 0x10007a02, 0x00 }, - { 0x10007a03, 0x02 }, - { 0x10007a04, 0xb3 }, - { 0x10007a05, 0xf7 }, - { 0x10007a06, 0xe7 }, - { 0x10007a07, 0x00 }, - { 0x10007a08, 0xe3 }, - { 0x10007a09, 0x8a }, - { 0x10007a0a, 0x07 }, - { 0x10007a0b, 0xf8 }, - { 0x10007a0c, 0x03 }, - { 0x10007a0d, 0xc7 }, - { 0x10007a0e, 0x04 }, - { 0x10007a0f, 0x90 }, - { 0x10007a10, 0x93 }, - { 0x10007a11, 0x07 }, - { 0x10007a12, 0x10 }, - { 0x10007a13, 0x00 }, - { 0x10007a14, 0x13 }, - { 0x10007a15, 0x77 }, - { 0x10007a16, 0x17 }, - { 0x10007a17, 0x00 }, - { 0x10007a18, 0x63 }, - { 0x10007a19, 0x1c }, - { 0x10007a1a, 0x07 }, - { 0x10007a1b, 0x00 }, - { 0x10007a1c, 0x83 }, - { 0x10007a1d, 0xc7 }, - { 0x10007a1e, 0x34 }, - { 0x10007a1f, 0x54 }, - { 0x10007a20, 0x93 }, - { 0x10007a21, 0xf7 }, - { 0x10007a22, 0xf7 }, - { 0x10007a23, 0x0f }, - { 0x10007a24, 0x93 }, - { 0x10007a25, 0xd7 }, - { 0x10007a26, 0x17 }, - { 0x10007a27, 0x00 }, - { 0x10007a28, 0x93 }, - { 0x10007a29, 0xc7 }, - { 0x10007a2a, 0x17 }, - { 0x10007a2b, 0x00 }, - { 0x10007a2c, 0x93 }, - { 0x10007a2d, 0xf7 }, - { 0x10007a2e, 0x17 }, - { 0x10007a2f, 0x00 }, - { 0x10007a30, 0xa3 }, - { 0x10007a31, 0x85 }, - { 0x10007a32, 0xf1 }, - { 0x10007a33, 0x42 }, - { 0x10007a34, 0x37 }, - { 0x10007a35, 0xd6 }, - { 0x10007a36, 0x00 }, - { 0x10007a37, 0x00 }, - { 0x10007a38, 0x03 }, - { 0x10007a39, 0x47 }, - { 0x10007a3a, 0x06 }, - { 0x10007a3b, 0x90 }, - { 0x10007a3c, 0x93 }, - { 0x10007a3d, 0x06 }, - { 0x10007a3e, 0x10 }, - { 0x10007a3f, 0x00 }, - { 0x10007a40, 0x13 }, - { 0x10007a41, 0x77 }, - { 0x10007a42, 0x27 }, - { 0x10007a43, 0x00 }, - { 0x10007a44, 0x63 }, - { 0x10007a45, 0x18 }, - { 0x10007a46, 0x07 }, - { 0x10007a47, 0x00 }, - { 0x10007a48, 0x03 }, - { 0x10007a49, 0x47 }, - { 0x10007a4a, 0x36 }, - { 0x10007a4b, 0x54 }, - { 0x10007a4c, 0x13 }, - { 0x10007a4d, 0x77 }, - { 0x10007a4e, 0x17 }, - { 0x10007a4f, 0x00 }, - { 0x10007a50, 0xb3 }, - { 0x10007a51, 0x86 }, - { 0x10007a52, 0xe6 }, - { 0x10007a53, 0x40 }, - { 0x10007a54, 0x23 }, - { 0x10007a55, 0x85 }, - { 0x10007a56, 0xd1 }, - { 0x10007a57, 0x42 }, - { 0x10007a58, 0xb7 }, - { 0x10007a59, 0xd5 }, - { 0x10007a5a, 0x00 }, - { 0x10007a5b, 0x00 }, - { 0x10007a5c, 0x03 }, - { 0x10007a5d, 0xc6 }, - { 0x10007a5e, 0x05 }, - { 0x10007a5f, 0x92 }, - { 0x10007a60, 0x13 }, - { 0x10007a61, 0x07 }, - { 0x10007a62, 0x10 }, - { 0x10007a63, 0x00 }, - { 0x10007a64, 0x13 }, - { 0x10007a65, 0x76 }, - { 0x10007a66, 0x16 }, - { 0x10007a67, 0x00 }, - { 0x10007a68, 0x63 }, - { 0x10007a69, 0x1c }, - { 0x10007a6a, 0x06 }, - { 0x10007a6b, 0x00 }, - { 0x10007a6c, 0x03 }, - { 0x10007a6d, 0xc7 }, - { 0x10007a6e, 0x35 }, - { 0x10007a6f, 0x54 }, - { 0x10007a70, 0x13 }, - { 0x10007a71, 0x77 }, - { 0x10007a72, 0xf7 }, - { 0x10007a73, 0x0f }, - { 0x10007a74, 0x13 }, - { 0x10007a75, 0x57 }, - { 0x10007a76, 0x37 }, - { 0x10007a77, 0x00 }, - { 0x10007a78, 0x13 }, - { 0x10007a79, 0x47 }, - { 0x10007a7a, 0x17 }, - { 0x10007a7b, 0x00 }, - { 0x10007a7c, 0x13 }, - { 0x10007a7d, 0x77 }, - { 0x10007a7e, 0x17 }, - { 0x10007a7f, 0x00 }, - { 0x10007a80, 0xa3 }, - { 0x10007a81, 0x84 }, - { 0x10007a82, 0xe1 }, - { 0x10007a83, 0x42 }, - { 0x10007a84, 0xb7 }, - { 0x10007a85, 0xd5 }, - { 0x10007a86, 0x00 }, - { 0x10007a87, 0x00 }, - { 0x10007a88, 0x03 }, - { 0x10007a89, 0xc6 }, - { 0x10007a8a, 0x05 }, - { 0x10007a8b, 0x92 }, - { 0x10007a8c, 0x13 }, - { 0x10007a8d, 0x07 }, - { 0x10007a8e, 0x10 }, - { 0x10007a8f, 0x00 }, - { 0x10007a90, 0x13 }, - { 0x10007a91, 0x76 }, - { 0x10007a92, 0x26 }, - { 0x10007a93, 0x00 }, - { 0x10007a94, 0x63 }, - { 0x10007a95, 0x1c }, - { 0x10007a96, 0x06 }, - { 0x10007a97, 0x00 }, - { 0x10007a98, 0x03 }, - { 0x10007a99, 0xc7 }, - { 0x10007a9a, 0x35 }, - { 0x10007a9b, 0x54 }, - { 0x10007a9c, 0x13 }, - { 0x10007a9d, 0x77 }, - { 0x10007a9e, 0xf7 }, - { 0x10007a9f, 0x0f }, - { 0x10007aa0, 0x13 }, - { 0x10007aa1, 0x57 }, - { 0x10007aa2, 0x27 }, - { 0x10007aa3, 0x00 }, - { 0x10007aa4, 0x13 }, - { 0x10007aa5, 0x47 }, - { 0x10007aa6, 0x17 }, - { 0x10007aa7, 0x00 }, - { 0x10007aa8, 0x13 }, - { 0x10007aa9, 0x77 }, - { 0x10007aaa, 0x17 }, - { 0x10007aab, 0x00 }, - { 0x10007aac, 0x23 }, - { 0x10007aad, 0x84 }, - { 0x10007aae, 0xe1 }, - { 0x10007aaf, 0x42 }, - { 0x10007ab0, 0x63 }, - { 0x10007ab1, 0x84 }, - { 0x10007ab2, 0x07 }, - { 0x10007ab3, 0x00 }, - { 0x10007ab4, 0xe3 }, - { 0x10007ab5, 0x94 }, - { 0x10007ab6, 0x06 }, - { 0x10007ab7, 0xee }, - { 0x10007ab8, 0xef }, - { 0x10007ab9, 0x90 }, - { 0x10007aba, 0x0f }, - { 0x10007abb, 0x86 }, - { 0x10007abc, 0xef }, - { 0x10007abd, 0xd0 }, - { 0x10007abe, 0x0f }, - { 0x10007abf, 0x97 }, - { 0x10007ac0, 0x37 }, - { 0x10007ac1, 0x15 }, - { 0x10007ac2, 0x00 }, - { 0x10007ac3, 0x00 }, - { 0x10007ac4, 0x13 }, - { 0x10007ac5, 0x05 }, - { 0x10007ac6, 0x85 }, - { 0x10007ac7, 0xbb }, - { 0x10007ac8, 0x93 }, - { 0x10007ac9, 0x05 }, - { 0x10007aca, 0x00 }, - { 0x10007acb, 0x00 }, - { 0x10007acc, 0xef }, - { 0x10007acd, 0xd0 }, - { 0x10007ace, 0x9f }, - { 0x10007acf, 0xf5 }, - { 0x10007ad0, 0xb7 }, - { 0x10007ad1, 0xd7 }, - { 0x10007ad2, 0x00 }, - { 0x10007ad3, 0x00 }, - { 0x10007ad4, 0x83 }, - { 0x10007ad5, 0xc7 }, - { 0x10007ad6, 0x07 }, - { 0x10007ad7, 0x47 }, - { 0x10007ad8, 0x93 }, - { 0x10007ad9, 0xf7 }, - { 0x10007ada, 0x47 }, - { 0x10007adb, 0x00 }, - { 0x10007adc, 0xe3 }, - { 0x10007add, 0x80 }, - { 0x10007ade, 0x07 }, - { 0x10007adf, 0xec }, - { 0x10007ae0, 0xef }, - { 0x10007ae1, 0x80 }, - { 0x10007ae2, 0xdf }, - { 0x10007ae3, 0xf4 }, - { 0x10007ae4, 0x23 }, - { 0x10007ae5, 0x89 }, - { 0x10007ae6, 0xa1 }, - { 0x10007ae7, 0x40 }, - { 0x10007ae8, 0x6f }, - { 0x10007ae9, 0xf0 }, - { 0x10007aea, 0x5f }, - { 0x10007aeb, 0xeb }, - { 0x10007aec, 0x00 }, - { 0x10007aed, 0x00 }, - { 0x10007aee, 0x00 }, - { 0x10007aef, 0x00 }, { 0x3fc2bf83, 0x00 }, { 0x3fc2bf82, 0x00 }, { 0x3fc2bf81, 0x00 }, @@ -2112,1330 +228,6 @@ static const struct reg_sequence rt1320_vc_patch_code_write[] = { { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, }; -/* - * The 'patch code' is written to the patch code area. - * The patch code area is used for SDCA register expansion flexibility. - */ -static const struct reg_sequence rt1320_patch_code_write[] = { - { 0x10007000, 0x37 }, - { 0x10007001, 0x77 }, - { 0x10007002, 0x00 }, - { 0x10007003, 0x10 }, - { 0x10007004, 0xb7 }, - { 0x10007005, 0xe7 }, - { 0x10007006, 0x00 }, - { 0x10007007, 0x10 }, - { 0x10007008, 0x13 }, - { 0x10007009, 0x07 }, - { 0x1000700a, 0x07 }, - { 0x1000700b, 0x40 }, - { 0x1000700c, 0x23 }, - { 0x1000700d, 0xae }, - { 0x1000700e, 0xe7 }, - { 0x1000700f, 0xda }, - { 0x10007010, 0x37 }, - { 0x10007011, 0x77 }, - { 0x10007012, 0x00 }, - { 0x10007013, 0x10 }, - { 0x10007014, 0x13 }, - { 0x10007015, 0x07 }, - { 0x10007016, 0x47 }, - { 0x10007017, 0x61 }, - { 0x10007018, 0x23 }, - { 0x10007019, 0xa4 }, - { 0x1000701a, 0xe7 }, - { 0x1000701b, 0xde }, - { 0x1000701c, 0x37 }, - { 0x1000701d, 0x77 }, - { 0x1000701e, 0x00 }, - { 0x1000701f, 0x10 }, - { 0x10007020, 0x13 }, - { 0x10007021, 0x07 }, - { 0x10007022, 0x07 }, - { 0x10007023, 0x52 }, - { 0x10007024, 0x23 }, - { 0x10007025, 0xae }, - { 0x10007026, 0xe7 }, - { 0x10007027, 0xde }, - { 0x10007028, 0x37 }, - { 0x10007029, 0x77 }, - { 0x1000702a, 0x00 }, - { 0x1000702b, 0x10 }, - { 0x1000702c, 0x13 }, - { 0x1000702d, 0x07 }, - { 0x1000702e, 0x47 }, - { 0x1000702f, 0x54 }, - { 0x10007030, 0x23 }, - { 0x10007031, 0xaa }, - { 0x10007032, 0xe7 }, - { 0x10007033, 0xe4 }, - { 0x10007034, 0x37 }, - { 0x10007035, 0x87 }, - { 0x10007036, 0x00 }, - { 0x10007037, 0x10 }, - { 0x10007038, 0x13 }, - { 0x10007039, 0x07 }, - { 0x1000703a, 0x47 }, - { 0x1000703b, 0x81 }, - { 0x1000703c, 0x23 }, - { 0x1000703d, 0xa2 }, - { 0x1000703e, 0xe7 }, - { 0x1000703f, 0xe8 }, - { 0x10007040, 0x23 }, - { 0x10007041, 0xa4 }, - { 0x10007042, 0xe7 }, - { 0x10007043, 0xe8 }, - { 0x10007044, 0x37 }, - { 0x10007045, 0x77 }, - { 0x10007046, 0x00 }, - { 0x10007047, 0x10 }, - { 0x10007048, 0x13 }, - { 0x10007049, 0x07 }, - { 0x1000704a, 0x07 }, - { 0x1000704b, 0x59 }, - { 0x1000704c, 0x23 }, - { 0x1000704d, 0xa8 }, - { 0x1000704e, 0xe7 }, - { 0x1000704f, 0xea }, - { 0x10007050, 0x37 }, - { 0x10007051, 0x77 }, - { 0x10007052, 0x00 }, - { 0x10007053, 0x10 }, - { 0x10007054, 0x13 }, - { 0x10007055, 0x07 }, - { 0x10007056, 0x07 }, - { 0x10007057, 0x78 }, - { 0x10007058, 0x23 }, - { 0x10007059, 0xa6 }, - { 0x1000705a, 0xe7 }, - { 0x1000705b, 0xec }, - { 0x1000705c, 0x67 }, - { 0x1000705d, 0x80 }, - { 0x1000705e, 0x00 }, - { 0x1000705f, 0x00 }, - { 0x10007400, 0x37 }, - { 0x10007401, 0xd7 }, - { 0x10007402, 0x00 }, - { 0x10007403, 0x00 }, - { 0x10007404, 0x83 }, - { 0x10007405, 0x27 }, - { 0x10007406, 0x47 }, - { 0x10007407, 0x56 }, - { 0x10007408, 0xb7 }, - { 0x10007409, 0x06 }, - { 0x1000740a, 0x00 }, - { 0x1000740b, 0x02 }, - { 0x1000740c, 0xb3 }, - { 0x1000740d, 0xf7 }, - { 0x1000740e, 0xd7 }, - { 0x1000740f, 0x00 }, - { 0x10007410, 0x63 }, - { 0x10007411, 0x8a }, - { 0x10007412, 0x07 }, - { 0x10007413, 0x00 }, - { 0x10007414, 0x93 }, - { 0x10007415, 0x06 }, - { 0x10007416, 0x10 }, - { 0x10007417, 0x00 }, - { 0x10007418, 0x23 }, - { 0x10007419, 0x83 }, - { 0x1000741a, 0xd1 }, - { 0x1000741b, 0x44 }, - { 0x1000741c, 0x93 }, - { 0x1000741d, 0x07 }, - { 0x1000741e, 0xf0 }, - { 0x1000741f, 0xff }, - { 0x10007420, 0x23 }, - { 0x10007421, 0x22 }, - { 0x10007422, 0xf7 }, - { 0x10007423, 0x56 }, - { 0x10007424, 0x37 }, - { 0x10007425, 0xd7 }, - { 0x10007426, 0x00 }, - { 0x10007427, 0x00 }, - { 0x10007428, 0x83 }, - { 0x10007429, 0x27 }, - { 0x1000742a, 0x47 }, - { 0x1000742b, 0x58 }, - { 0x1000742c, 0x93 }, - { 0x1000742d, 0xf7 }, - { 0x1000742e, 0x17 }, - { 0x1000742f, 0x00 }, - { 0x10007430, 0x63 }, - { 0x10007431, 0x86 }, - { 0x10007432, 0x07 }, - { 0x10007433, 0x00 }, - { 0x10007434, 0x93 }, - { 0x10007435, 0x07 }, - { 0x10007436, 0x10 }, - { 0x10007437, 0x00 }, - { 0x10007438, 0x23 }, - { 0x10007439, 0x22 }, - { 0x1000743a, 0xf7 }, - { 0x1000743b, 0x58 }, - { 0x1000743c, 0xb7 }, - { 0x1000743d, 0xd7 }, - { 0x1000743e, 0x00 }, - { 0x1000743f, 0x00 }, - { 0x10007440, 0x03 }, - { 0x10007441, 0xa7 }, - { 0x10007442, 0x47 }, - { 0x10007443, 0x58 }, - { 0x10007444, 0xb7 }, - { 0x10007445, 0x07 }, - { 0x10007446, 0x00 }, - { 0x10007447, 0x04 }, - { 0x10007448, 0x33 }, - { 0x10007449, 0x77 }, - { 0x1000744a, 0xf7 }, - { 0x1000744b, 0x00 }, - { 0x1000744c, 0x93 }, - { 0x1000744d, 0x07 }, - { 0x1000744e, 0x00 }, - { 0x1000744f, 0x00 }, - { 0x10007450, 0x63 }, - { 0x10007451, 0x0e }, - { 0x10007452, 0x07 }, - { 0x10007453, 0x04 }, - { 0x10007454, 0x37 }, - { 0x10007455, 0x07 }, - { 0x10007456, 0x00 }, - { 0x10007457, 0x11 }, - { 0x10007458, 0x03 }, - { 0x10007459, 0x47 }, - { 0x1000745a, 0x87 }, - { 0x1000745b, 0x0e }, - { 0x1000745c, 0x93 }, - { 0x1000745d, 0x06 }, - { 0x1000745e, 0x40 }, - { 0x1000745f, 0x00 }, - { 0x10007460, 0x13 }, - { 0x10007461, 0x77 }, - { 0x10007462, 0xf7 }, - { 0x10007463, 0x0f }, - { 0x10007464, 0x63 }, - { 0x10007465, 0x02 }, - { 0x10007466, 0xd7 }, - { 0x10007467, 0x0a }, - { 0x10007468, 0x93 }, - { 0x10007469, 0x06 }, - { 0x1000746a, 0x70 }, - { 0x1000746b, 0x00 }, - { 0x1000746c, 0x63 }, - { 0x1000746d, 0x10 }, - { 0x1000746e, 0xd7 }, - { 0x1000746f, 0x04 }, - { 0x10007470, 0x93 }, - { 0x10007471, 0x07 }, - { 0x10007472, 0x60 }, - { 0x10007473, 0x06 }, - { 0x10007474, 0x37 }, - { 0x10007475, 0xd7 }, - { 0x10007476, 0x00 }, - { 0x10007477, 0x00 }, - { 0x10007478, 0x83 }, - { 0x10007479, 0x46 }, - { 0x1000747a, 0x77 }, - { 0x1000747b, 0xa6 }, - { 0x1000747c, 0x93 }, - { 0x1000747d, 0xe6 }, - { 0x1000747e, 0x06 }, - { 0x1000747f, 0xf8 }, - { 0x10007480, 0x93 }, - { 0x10007481, 0xf6 }, - { 0x10007482, 0xf6 }, - { 0x10007483, 0x0f }, - { 0x10007484, 0xa3 }, - { 0x10007485, 0x03 }, - { 0x10007486, 0xd7 }, - { 0x10007487, 0xa6 }, - { 0x10007488, 0x83 }, - { 0x10007489, 0x46 }, - { 0x1000748a, 0x77 }, - { 0x1000748b, 0xa8 }, - { 0x1000748c, 0x93 }, - { 0x1000748d, 0xe6 }, - { 0x1000748e, 0x06 }, - { 0x1000748f, 0xf8 }, - { 0x10007490, 0x93 }, - { 0x10007491, 0xf6 }, - { 0x10007492, 0xf6 }, - { 0x10007493, 0x0f }, - { 0x10007494, 0xa3 }, - { 0x10007495, 0x03 }, - { 0x10007496, 0xd7 }, - { 0x10007497, 0xa8 }, - { 0x10007498, 0xb7 }, - { 0x10007499, 0xc6 }, - { 0x1000749a, 0x00 }, - { 0x1000749b, 0x00 }, - { 0x1000749c, 0x23 }, - { 0x1000749d, 0x84 }, - { 0x1000749e, 0xf6 }, - { 0x1000749f, 0x06 }, - { 0x100074a0, 0xa3 }, - { 0x100074a1, 0x84 }, - { 0x100074a2, 0xf6 }, - { 0x100074a3, 0x06 }, - { 0x100074a4, 0xb7 }, - { 0x100074a5, 0x06 }, - { 0x100074a6, 0x00 }, - { 0x100074a7, 0x04 }, - { 0x100074a8, 0x23 }, - { 0x100074a9, 0x22 }, - { 0x100074aa, 0xd7 }, - { 0x100074ab, 0x58 }, - { 0x100074ac, 0x37 }, - { 0x100074ad, 0xd7 }, - { 0x100074ae, 0x00 }, - { 0x100074af, 0x00 }, - { 0x100074b0, 0x03 }, - { 0x100074b1, 0x27 }, - { 0x100074b2, 0x47 }, - { 0x100074b3, 0x58 }, - { 0x100074b4, 0xb7 }, - { 0x100074b5, 0x06 }, - { 0x100074b6, 0x00 }, - { 0x100074b7, 0x08 }, - { 0x100074b8, 0x33 }, - { 0x100074b9, 0x77 }, - { 0x100074ba, 0xd7 }, - { 0x100074bb, 0x00 }, - { 0x100074bc, 0x63 }, - { 0x100074bd, 0x04 }, - { 0x100074be, 0x07 }, - { 0x100074bf, 0x04 }, - { 0x100074c0, 0x37 }, - { 0x100074c1, 0x07 }, - { 0x100074c2, 0x00 }, - { 0x100074c3, 0x11 }, - { 0x100074c4, 0x03 }, - { 0x100074c5, 0x47 }, - { 0x100074c6, 0xc7 }, - { 0x100074c7, 0x0e }, - { 0x100074c8, 0x93 }, - { 0x100074c9, 0x06 }, - { 0x100074ca, 0x40 }, - { 0x100074cb, 0x00 }, - { 0x100074cc, 0x13 }, - { 0x100074cd, 0x77 }, - { 0x100074ce, 0xf7 }, - { 0x100074cf, 0x0f }, - { 0x100074d0, 0x63 }, - { 0x100074d1, 0x00 }, - { 0x100074d2, 0xd7 }, - { 0x100074d3, 0x04 }, - { 0x100074d4, 0x93 }, - { 0x100074d5, 0x06 }, - { 0x100074d6, 0x70 }, - { 0x100074d7, 0x00 }, - { 0x100074d8, 0x63 }, - { 0x100074d9, 0x00 }, - { 0x100074da, 0xd7 }, - { 0x100074db, 0x04 }, - { 0x100074dc, 0x63 }, - { 0x100074dd, 0x84 }, - { 0x100074de, 0x07 }, - { 0x100074df, 0x02 }, - { 0x100074e0, 0xb7 }, - { 0x100074e1, 0xd6 }, - { 0x100074e2, 0x00 }, - { 0x100074e3, 0x00 }, - { 0x100074e4, 0x03 }, - { 0x100074e5, 0xc7 }, - { 0x100074e6, 0x56 }, - { 0x100074e7, 0xa4 }, - { 0x100074e8, 0x13 }, - { 0x100074e9, 0x67 }, - { 0x100074ea, 0x07 }, - { 0x100074eb, 0xf8 }, - { 0x100074ec, 0x13 }, - { 0x100074ed, 0x77 }, - { 0x100074ee, 0xf7 }, - { 0x100074ef, 0x0f }, - { 0x100074f0, 0xa3 }, - { 0x100074f1, 0x82 }, - { 0x100074f2, 0xe6 }, - { 0x100074f3, 0xa4 }, - { 0x100074f4, 0x37 }, - { 0x100074f5, 0xc7 }, - { 0x100074f6, 0x00 }, - { 0x100074f7, 0x00 }, - { 0x100074f8, 0x23 }, - { 0x100074f9, 0x02 }, - { 0x100074fa, 0xf7 }, - { 0x100074fb, 0x06 }, - { 0x100074fc, 0xb7 }, - { 0x100074fd, 0x07 }, - { 0x100074fe, 0x00 }, - { 0x100074ff, 0x08 }, - { 0x10007500, 0x23 }, - { 0x10007501, 0xa2 }, - { 0x10007502, 0xf6 }, - { 0x10007503, 0x58 }, - { 0x10007504, 0x67 }, - { 0x10007505, 0x80 }, - { 0x10007506, 0x00 }, - { 0x10007507, 0x00 }, - { 0x10007508, 0x93 }, - { 0x10007509, 0x07 }, - { 0x1000750a, 0x80 }, - { 0x1000750b, 0x08 }, - { 0x1000750c, 0x6f }, - { 0x1000750d, 0xf0 }, - { 0x1000750e, 0x9f }, - { 0x1000750f, 0xf6 }, - { 0x10007510, 0x93 }, - { 0x10007511, 0x07 }, - { 0x10007512, 0x80 }, - { 0x10007513, 0x08 }, - { 0x10007514, 0x6f }, - { 0x10007515, 0xf0 }, - { 0x10007516, 0xdf }, - { 0x10007517, 0xfc }, - { 0x10007518, 0x93 }, - { 0x10007519, 0x07 }, - { 0x1000751a, 0x60 }, - { 0x1000751b, 0x06 }, - { 0x1000751c, 0x6f }, - { 0x1000751d, 0xf0 }, - { 0x1000751e, 0x5f }, - { 0x1000751f, 0xfc }, - { 0x10007520, 0x37 }, - { 0x10007521, 0xd7 }, - { 0x10007522, 0x00 }, - { 0x10007523, 0x00 }, - { 0x10007524, 0x83 }, - { 0x10007525, 0x27 }, - { 0x10007526, 0x07 }, - { 0x10007527, 0x53 }, - { 0x10007528, 0xb7 }, - { 0x10007529, 0x06 }, - { 0x1000752a, 0x02 }, - { 0x1000752b, 0x00 }, - { 0x1000752c, 0xb3 }, - { 0x1000752d, 0xf7 }, - { 0x1000752e, 0xd7 }, - { 0x1000752f, 0x00 }, - { 0x10007530, 0x63 }, - { 0x10007531, 0x88 }, - { 0x10007532, 0x07 }, - { 0x10007533, 0x00 }, - { 0x10007534, 0x13 }, - { 0x10007535, 0x06 }, - { 0x10007536, 0xa0 }, - { 0x10007537, 0x05 }, - { 0x10007538, 0x23 }, - { 0x10007539, 0xa8 }, - { 0x1000753a, 0xc1 }, - { 0x1000753b, 0x56 }, - { 0x1000753c, 0x23 }, - { 0x1000753d, 0x28 }, - { 0x1000753e, 0xd7 }, - { 0x1000753f, 0x52 }, - { 0x10007540, 0x67 }, - { 0x10007541, 0x80 }, - { 0x10007542, 0x00 }, - { 0x10007543, 0x00 }, - { 0x10007544, 0x37 }, - { 0x10007545, 0xd7 }, - { 0x10007546, 0x00 }, - { 0x10007547, 0x10 }, - { 0x10007548, 0x83 }, - { 0x10007549, 0x47 }, - { 0x1000754a, 0x07 }, - { 0x1000754b, 0xd9 }, - { 0x1000754c, 0x93 }, - { 0x1000754d, 0x06 }, - { 0x1000754e, 0x20 }, - { 0x1000754f, 0x00 }, - { 0x10007550, 0x93 }, - { 0x10007551, 0xf7 }, - { 0x10007552, 0xf7 }, - { 0x10007553, 0x0f }, - { 0x10007554, 0x63 }, - { 0x10007555, 0x9c }, - { 0x10007556, 0xd7 }, - { 0x10007557, 0x02 }, - { 0x10007558, 0xb7 }, - { 0x10007559, 0xc6 }, - { 0x1000755a, 0x00 }, - { 0x1000755b, 0x00 }, - { 0x1000755c, 0x83 }, - { 0x1000755d, 0xc7 }, - { 0x1000755e, 0x26 }, - { 0x1000755f, 0x04 }, - { 0x10007560, 0x93 }, - { 0x10007561, 0xf7 }, - { 0x10007562, 0xf7 }, - { 0x10007563, 0x07 }, - { 0x10007564, 0x23 }, - { 0x10007565, 0x81 }, - { 0x10007566, 0xf6 }, - { 0x10007567, 0x04 }, - { 0x10007568, 0xb7 }, - { 0x10007569, 0xd6 }, - { 0x1000756a, 0x00 }, - { 0x1000756b, 0x00 }, - { 0x1000756c, 0x83 }, - { 0x1000756d, 0xc7 }, - { 0x1000756e, 0xa6 }, - { 0x1000756f, 0xe1 }, - { 0x10007570, 0x93 }, - { 0x10007571, 0xf7 }, - { 0x10007572, 0xf7 }, - { 0x10007573, 0x07 }, - { 0x10007574, 0x23 }, - { 0x10007575, 0x8d }, - { 0x10007576, 0xf6 }, - { 0x10007577, 0xe0 }, - { 0x10007578, 0x23 }, - { 0x10007579, 0x08 }, - { 0x1000757a, 0x07 }, - { 0x1000757b, 0xd8 }, - { 0x1000757c, 0x83 }, - { 0x1000757d, 0x47 }, - { 0x1000757e, 0x47 }, - { 0x1000757f, 0xd9 }, - { 0x10007580, 0x93 }, - { 0x10007581, 0x87 }, - { 0x10007582, 0x17 }, - { 0x10007583, 0x00 }, - { 0x10007584, 0x93 }, - { 0x10007585, 0xf7 }, - { 0x10007586, 0xf7 }, - { 0x10007587, 0x0f }, - { 0x10007588, 0x23 }, - { 0x10007589, 0x0a }, - { 0x1000758a, 0xf7 }, - { 0x1000758b, 0xd8 }, - { 0x1000758c, 0x67 }, - { 0x1000758d, 0x80 }, - { 0x1000758e, 0x00 }, - { 0x1000758f, 0x00 }, - { 0x10007590, 0xb7 }, - { 0x10007591, 0xd7 }, - { 0x10007592, 0x00 }, - { 0x10007593, 0x00 }, - { 0x10007594, 0x83 }, - { 0x10007595, 0xc7 }, - { 0x10007596, 0x07 }, - { 0x10007597, 0x47 }, - { 0x10007598, 0x93 }, - { 0x10007599, 0xf7 }, - { 0x1000759a, 0x07 }, - { 0x1000759b, 0x01 }, - { 0x1000759c, 0x63 }, - { 0x1000759d, 0x8a }, - { 0x1000759e, 0x07 }, - { 0x1000759f, 0x06 }, - { 0x100075a0, 0x63 }, - { 0x100075a1, 0x02 }, - { 0x100075a2, 0x05 }, - { 0x100075a3, 0x06 }, - { 0x100075a4, 0x37 }, - { 0x100075a5, 0xc7 }, - { 0x100075a6, 0x00 }, - { 0x100075a7, 0x00 }, - { 0x100075a8, 0x83 }, - { 0x100075a9, 0x27 }, - { 0x100075aa, 0xc7 }, - { 0x100075ab, 0x5f }, - { 0x100075ac, 0x23 }, - { 0x100075ad, 0xae }, - { 0x100075ae, 0xf1 }, - { 0x100075af, 0x40 }, - { 0x100075b0, 0xb7 }, - { 0x100075b1, 0x06 }, - { 0x100075b2, 0x00 }, - { 0x100075b3, 0x10 }, - { 0x100075b4, 0xb3 }, - { 0x100075b5, 0xf7 }, - { 0x100075b6, 0xd7 }, - { 0x100075b7, 0x00 }, - { 0x100075b8, 0x63 }, - { 0x100075b9, 0x8c }, - { 0x100075ba, 0x07 }, - { 0x100075bb, 0x04 }, - { 0x100075bc, 0x83 }, - { 0x100075bd, 0x47 }, - { 0x100075be, 0x07 }, - { 0x100075bf, 0x56 }, - { 0x100075c0, 0x93 }, - { 0x100075c1, 0xf7 }, - { 0x100075c2, 0x87 }, - { 0x100075c3, 0x01 }, - { 0x100075c4, 0x63 }, - { 0x100075c5, 0x86 }, - { 0x100075c6, 0x07 }, - { 0x100075c7, 0x04 }, - { 0x100075c8, 0x83 }, - { 0x100075c9, 0x47 }, - { 0x100075ca, 0x17 }, - { 0x100075cb, 0x08 }, - { 0x100075cc, 0x93 }, - { 0x100075cd, 0xf7 }, - { 0x100075ce, 0x47 }, - { 0x100075cf, 0x00 }, - { 0x100075d0, 0x63 }, - { 0x100075d1, 0x80 }, - { 0x100075d2, 0x07 }, - { 0x100075d3, 0x04 }, - { 0x100075d4, 0xb7 }, - { 0x100075d5, 0xc7 }, - { 0x100075d6, 0xc2 }, - { 0x100075d7, 0x3f }, - { 0x100075d8, 0x93 }, - { 0x100075d9, 0x87 }, - { 0x100075da, 0x07 }, - { 0x100075db, 0xfc }, - { 0x100075dc, 0x83 }, - { 0x100075dd, 0xa7 }, - { 0x100075de, 0x47 }, - { 0x100075df, 0x00 }, - { 0x100075e0, 0x93 }, - { 0x100075e1, 0xd7 }, - { 0x100075e2, 0x17 }, - { 0x100075e3, 0x00 }, - { 0x100075e4, 0x93 }, - { 0x100075e5, 0xf7 }, - { 0x100075e6, 0x17 }, - { 0x100075e7, 0x00 }, - { 0x100075e8, 0x63 }, - { 0x100075e9, 0x84 }, - { 0x100075ea, 0x07 }, - { 0x100075eb, 0x02 }, - { 0x100075ec, 0x23 }, - { 0x100075ed, 0x8a }, - { 0x100075ee, 0xf1 }, - { 0x100075ef, 0x40 }, - { 0x100075f0, 0xb7 }, - { 0x100075f1, 0x07 }, - { 0x100075f2, 0x00 }, - { 0x100075f3, 0xc0 }, - { 0x100075f4, 0x37 }, - { 0x100075f5, 0xf7 }, - { 0x100075f6, 0x00 }, - { 0x100075f7, 0x00 }, - { 0x100075f8, 0x93 }, - { 0x100075f9, 0x87 }, - { 0x100075fa, 0xf7 }, - { 0x100075fb, 0xff }, - { 0x100075fc, 0x23 }, - { 0x100075fd, 0x2c }, - { 0x100075fe, 0xf7 }, - { 0x100075ff, 0x06 }, - { 0x10007600, 0x67 }, - { 0x10007601, 0x80 }, - { 0x10007602, 0x00 }, - { 0x10007603, 0x00 }, - { 0x10007604, 0x23 }, - { 0x10007605, 0x8a }, - { 0x10007606, 0x01 }, - { 0x10007607, 0x40 }, - { 0x10007608, 0xb7 }, - { 0x10007609, 0xf7 }, - { 0x1000760a, 0x00 }, - { 0x1000760b, 0x00 }, - { 0x1000760c, 0x23 }, - { 0x1000760d, 0xac }, - { 0x1000760e, 0x07 }, - { 0x1000760f, 0x06 }, - { 0x10007610, 0x67 }, - { 0x10007611, 0x80 }, - { 0x10007612, 0x00 }, - { 0x10007613, 0x00 }, - { 0x10007614, 0x13 }, - { 0x10007615, 0x01 }, - { 0x10007616, 0x01 }, - { 0x10007617, 0xff }, - { 0x10007618, 0x23 }, - { 0x10007619, 0x26 }, - { 0x1000761a, 0x11 }, - { 0x1000761b, 0x00 }, - { 0x1000761c, 0x23 }, - { 0x1000761d, 0x24 }, - { 0x1000761e, 0x81 }, - { 0x1000761f, 0x00 }, - { 0x10007620, 0x37 }, - { 0x10007621, 0xc7 }, - { 0x10007622, 0x00 }, - { 0x10007623, 0x00 }, - { 0x10007624, 0x83 }, - { 0x10007625, 0x47 }, - { 0x10007626, 0x07 }, - { 0x10007627, 0x56 }, - { 0x10007628, 0x93 }, - { 0x10007629, 0xf7 }, - { 0x1000762a, 0x17 }, - { 0x1000762b, 0x00 }, - { 0x1000762c, 0x63 }, - { 0x1000762d, 0x98 }, - { 0x1000762e, 0x07 }, - { 0x1000762f, 0x00 }, - { 0x10007630, 0x83 }, - { 0x10007631, 0x47 }, - { 0x10007632, 0x07 }, - { 0x10007633, 0x56 }, - { 0x10007634, 0x93 }, - { 0x10007635, 0xf7 }, - { 0x10007636, 0x27 }, - { 0x10007637, 0x00 }, - { 0x10007638, 0x63 }, - { 0x10007639, 0x82 }, - { 0x1000763a, 0x07 }, - { 0x1000763b, 0x08 }, - { 0x1000763c, 0x37 }, - { 0x1000763d, 0xd4 }, - { 0x1000763e, 0x00 }, - { 0x1000763f, 0x00 }, - { 0x10007640, 0x83 }, - { 0x10007641, 0x47 }, - { 0x10007642, 0x14 }, - { 0x10007643, 0x47 }, - { 0x10007644, 0x93 }, - { 0x10007645, 0xf7 }, - { 0x10007646, 0x27 }, - { 0x10007647, 0x00 }, - { 0x10007648, 0x63 }, - { 0x10007649, 0x8a }, - { 0x1000764a, 0x07 }, - { 0x1000764b, 0x06 }, - { 0x1000764c, 0x93 }, - { 0x1000764d, 0x05 }, - { 0x1000764e, 0x10 }, - { 0x1000764f, 0x00 }, - { 0x10007650, 0x13 }, - { 0x10007651, 0x05 }, - { 0x10007652, 0x20 }, - { 0x10007653, 0x10 }, - { 0x10007654, 0xef }, - { 0x10007655, 0xa0 }, - { 0x10007656, 0x8f }, - { 0x10007657, 0x9a }, - { 0x10007658, 0x37 }, - { 0x10007659, 0x05 }, - { 0x1000765a, 0x01 }, - { 0x1000765b, 0x00 }, - { 0x1000765c, 0x93 }, - { 0x1000765d, 0x05 }, - { 0x1000765e, 0x00 }, - { 0x1000765f, 0x01 }, - { 0x10007660, 0x13 }, - { 0x10007661, 0x05 }, - { 0x10007662, 0xb5 }, - { 0x10007663, 0xa0 }, - { 0x10007664, 0xef }, - { 0x10007665, 0xa0 }, - { 0x10007666, 0x8f }, - { 0x10007667, 0x99 }, - { 0x10007668, 0x83 }, - { 0x10007669, 0x47 }, - { 0x1000766a, 0x24 }, - { 0x1000766b, 0xe0 }, - { 0x1000766c, 0x13 }, - { 0x1000766d, 0x05 }, - { 0x1000766e, 0x80 }, - { 0x1000766f, 0x3e }, - { 0x10007670, 0x93 }, - { 0x10007671, 0x05 }, - { 0x10007672, 0x00 }, - { 0x10007673, 0x00 }, - { 0x10007674, 0x93 }, - { 0x10007675, 0xe7 }, - { 0x10007676, 0x07 }, - { 0x10007677, 0xf8 }, - { 0x10007678, 0x93 }, - { 0x10007679, 0xf7 }, - { 0x1000767a, 0xf7 }, - { 0x1000767b, 0x0f }, - { 0x1000767c, 0x23 }, - { 0x1000767d, 0x01 }, - { 0x1000767e, 0xf4 }, - { 0x1000767f, 0xe0 }, - { 0x10007680, 0x83 }, - { 0x10007681, 0x47 }, - { 0x10007682, 0x24 }, - { 0x10007683, 0xe0 }, - { 0x10007684, 0x93 }, - { 0x10007685, 0xf7 }, - { 0x10007686, 0xf7 }, - { 0x10007687, 0x0f }, - { 0x10007688, 0x93 }, - { 0x10007689, 0xe7 }, - { 0x1000768a, 0x07 }, - { 0x1000768b, 0x04 }, - { 0x1000768c, 0x23 }, - { 0x1000768d, 0x01 }, - { 0x1000768e, 0xf4 }, - { 0x1000768f, 0xe0 }, - { 0x10007690, 0xef }, - { 0x10007691, 0xe0 }, - { 0x10007692, 0x8f }, - { 0x10007693, 0xb9 }, - { 0x10007694, 0x83 }, - { 0x10007695, 0x47 }, - { 0x10007696, 0x34 }, - { 0x10007697, 0xe0 }, - { 0x10007698, 0x93 }, - { 0x10007699, 0xf7 }, - { 0x1000769a, 0x07 }, - { 0x1000769b, 0x02 }, - { 0x1000769c, 0xe3 }, - { 0x1000769d, 0x9c }, - { 0x1000769e, 0x07 }, - { 0x1000769f, 0xfe }, - { 0x100076a0, 0x37 }, - { 0x100076a1, 0x05 }, - { 0x100076a2, 0x01 }, - { 0x100076a3, 0x00 }, - { 0x100076a4, 0x93 }, - { 0x100076a5, 0x05 }, - { 0x100076a6, 0x00 }, - { 0x100076a7, 0x00 }, - { 0x100076a8, 0x13 }, - { 0x100076a9, 0x05 }, - { 0x100076aa, 0xb5 }, - { 0x100076ab, 0xa0 }, - { 0x100076ac, 0xef }, - { 0x100076ad, 0xa0 }, - { 0x100076ae, 0x0f }, - { 0x100076af, 0x95 }, - { 0x100076b0, 0x83 }, - { 0x100076b1, 0x47 }, - { 0x100076b2, 0x14 }, - { 0x100076b3, 0x47 }, - { 0x100076b4, 0x93 }, - { 0x100076b5, 0xf7 }, - { 0x100076b6, 0xd7 }, - { 0x100076b7, 0x0f }, - { 0x100076b8, 0xa3 }, - { 0x100076b9, 0x08 }, - { 0x100076ba, 0xf4 }, - { 0x100076bb, 0x46 }, - { 0x100076bc, 0x03 }, - { 0x100076bd, 0xa7 }, - { 0x100076be, 0x01 }, - { 0x100076bf, 0x57 }, - { 0x100076c0, 0x93 }, - { 0x100076c1, 0x07 }, - { 0x100076c2, 0xa0 }, - { 0x100076c3, 0x05 }, - { 0x100076c4, 0x63 }, - { 0x100076c5, 0x14 }, - { 0x100076c6, 0xf7 }, - { 0x100076c7, 0x04 }, - { 0x100076c8, 0x37 }, - { 0x100076c9, 0x07 }, - { 0x100076ca, 0x00 }, - { 0x100076cb, 0x11 }, - { 0x100076cc, 0x83 }, - { 0x100076cd, 0x47 }, - { 0x100076ce, 0x07 }, - { 0x100076cf, 0x01 }, - { 0x100076d0, 0x13 }, - { 0x100076d1, 0x06 }, - { 0x100076d2, 0x30 }, - { 0x100076d3, 0x00 }, - { 0x100076d4, 0x93 }, - { 0x100076d5, 0xf7 }, - { 0x100076d6, 0xf7 }, - { 0x100076d7, 0x0f }, - { 0x100076d8, 0x63 }, - { 0x100076d9, 0x9a }, - { 0x100076da, 0xc7 }, - { 0x100076db, 0x02 }, - { 0x100076dc, 0x03 }, - { 0x100076dd, 0x47 }, - { 0x100076de, 0x87 }, - { 0x100076df, 0x01 }, - { 0x100076e0, 0x13 }, - { 0x100076e1, 0x77 }, - { 0x100076e2, 0xf7 }, - { 0x100076e3, 0x0f }, - { 0x100076e4, 0x63 }, - { 0x100076e5, 0x14 }, - { 0x100076e6, 0xf7 }, - { 0x100076e7, 0x02 }, - { 0x100076e8, 0x37 }, - { 0x100076e9, 0xd7 }, - { 0x100076ea, 0x00 }, - { 0x100076eb, 0x00 }, - { 0x100076ec, 0x83 }, - { 0x100076ed, 0x47 }, - { 0x100076ee, 0x37 }, - { 0x100076ef, 0x54 }, - { 0x100076f0, 0x93 }, - { 0x100076f1, 0xf7 }, - { 0x100076f2, 0xf7 }, - { 0x100076f3, 0x0f }, - { 0x100076f4, 0x93 }, - { 0x100076f5, 0xe7 }, - { 0x100076f6, 0x07 }, - { 0x100076f7, 0x02 }, - { 0x100076f8, 0xa3 }, - { 0x100076f9, 0x01 }, - { 0x100076fa, 0xf7 }, - { 0x100076fb, 0x54 }, - { 0x100076fc, 0x83 }, - { 0x100076fd, 0x47 }, - { 0x100076fe, 0x37 }, - { 0x100076ff, 0x54 }, - { 0x10007700, 0x93 }, - { 0x10007701, 0xf7 }, - { 0x10007702, 0xf7 }, - { 0x10007703, 0x0d }, - { 0x10007704, 0xa3 }, - { 0x10007705, 0x01 }, - { 0x10007706, 0xf7 }, - { 0x10007707, 0x54 }, - { 0x10007708, 0x23 }, - { 0x10007709, 0xa8 }, - { 0x1000770a, 0x01 }, - { 0x1000770b, 0x56 }, - { 0x1000770c, 0xb7 }, - { 0x1000770d, 0xd7 }, - { 0x1000770e, 0x00 }, - { 0x1000770f, 0x10 }, - { 0x10007710, 0x03 }, - { 0x10007711, 0xc7 }, - { 0x10007712, 0x07 }, - { 0x10007713, 0xd9 }, - { 0x10007714, 0x93 }, - { 0x10007715, 0x06 }, - { 0x10007716, 0x10 }, - { 0x10007717, 0x00 }, - { 0x10007718, 0x13 }, - { 0x10007719, 0x77 }, - { 0x1000771a, 0xf7 }, - { 0x1000771b, 0x0f }, - { 0x1000771c, 0x63 }, - { 0x1000771d, 0x1a }, - { 0x1000771e, 0xd7 }, - { 0x1000771f, 0x04 }, - { 0x10007720, 0x03 }, - { 0x10007721, 0xc7 }, - { 0x10007722, 0x27 }, - { 0x10007723, 0xd9 }, - { 0x10007724, 0x13 }, - { 0x10007725, 0x07 }, - { 0x10007726, 0x17 }, - { 0x10007727, 0x00 }, - { 0x10007728, 0x13 }, - { 0x10007729, 0x77 }, - { 0x1000772a, 0xf7 }, - { 0x1000772b, 0x0f }, - { 0x1000772c, 0x23 }, - { 0x1000772d, 0x89 }, - { 0x1000772e, 0xe7 }, - { 0x1000772f, 0xd8 }, - { 0x10007730, 0x83 }, - { 0x10007731, 0xc6 }, - { 0x10007732, 0x27 }, - { 0x10007733, 0xd9 }, - { 0x10007734, 0x03 }, - { 0x10007735, 0xc7 }, - { 0x10007736, 0x17 }, - { 0x10007737, 0xd9 }, - { 0x10007738, 0x93 }, - { 0x10007739, 0xf6 }, - { 0x1000773a, 0xf6 }, - { 0x1000773b, 0x0f }, - { 0x1000773c, 0x13 }, - { 0x1000773d, 0x77 }, - { 0x1000773e, 0xf7 }, - { 0x1000773f, 0x0f }, - { 0x10007740, 0x63 }, - { 0x10007741, 0xe8 }, - { 0x10007742, 0xe6 }, - { 0x10007743, 0x02 }, - { 0x10007744, 0xb7 }, - { 0x10007745, 0xd6 }, - { 0x10007746, 0x00 }, - { 0x10007747, 0x00 }, - { 0x10007748, 0x03 }, - { 0x10007749, 0xc7 }, - { 0x1000774a, 0xa6 }, - { 0x1000774b, 0xe1 }, - { 0x1000774c, 0x13 }, - { 0x1000774d, 0x67 }, - { 0x1000774e, 0x07 }, - { 0x1000774f, 0xf8 }, - { 0x10007750, 0x13 }, - { 0x10007751, 0x77 }, - { 0x10007752, 0xf7 }, - { 0x10007753, 0x0f }, - { 0x10007754, 0x23 }, - { 0x10007755, 0x8d }, - { 0x10007756, 0xe6 }, - { 0x10007757, 0xe0 }, - { 0x10007758, 0x03 }, - { 0x10007759, 0xc7 }, - { 0x1000775a, 0x37 }, - { 0x1000775b, 0xd9 }, - { 0x1000775c, 0x13 }, - { 0x1000775d, 0x07 }, - { 0x1000775e, 0x17 }, - { 0x1000775f, 0x00 }, - { 0x10007760, 0x13 }, - { 0x10007761, 0x77 }, - { 0x10007762, 0xf7 }, - { 0x10007763, 0x0f }, - { 0x10007764, 0xa3 }, - { 0x10007765, 0x89 }, - { 0x10007766, 0xe7 }, - { 0x10007767, 0xd8 }, - { 0x10007768, 0x13 }, - { 0x10007769, 0x07 }, - { 0x1000776a, 0x20 }, - { 0x1000776b, 0x00 }, - { 0x1000776c, 0x23 }, - { 0x1000776d, 0x88 }, - { 0x1000776e, 0xe7 }, - { 0x1000776f, 0xd8 }, - { 0x10007770, 0x83 }, - { 0x10007771, 0x20 }, - { 0x10007772, 0xc1 }, - { 0x10007773, 0x00 }, - { 0x10007774, 0x03 }, - { 0x10007775, 0x24 }, - { 0x10007776, 0x81 }, - { 0x10007777, 0x00 }, - { 0x10007778, 0x13 }, - { 0x10007779, 0x01 }, - { 0x1000777a, 0x01 }, - { 0x1000777b, 0x01 }, - { 0x1000777c, 0x67 }, - { 0x1000777d, 0x80 }, - { 0x1000777e, 0x00 }, - { 0x1000777f, 0x00 }, - { 0x10007780, 0x03 }, - { 0x10007781, 0xc7 }, - { 0x10007782, 0xa1 }, - { 0x10007783, 0x40 }, - { 0x10007784, 0x93 }, - { 0x10007785, 0x06 }, - { 0x10007786, 0x10 }, - { 0x10007787, 0x00 }, - { 0x10007788, 0x63 }, - { 0x10007789, 0x16 }, - { 0x1000778a, 0xd7 }, - { 0x1000778b, 0x00 }, - { 0x1000778c, 0xb7 }, - { 0x1000778d, 0xd6 }, - { 0x1000778e, 0x00 }, - { 0x1000778f, 0x10 }, - { 0x10007790, 0xa3 }, - { 0x10007791, 0x8a }, - { 0x10007792, 0xe6 }, - { 0x10007793, 0xd8 }, - { 0x10007794, 0x83 }, - { 0x10007795, 0xc7 }, - { 0x10007796, 0xa1 }, - { 0x10007797, 0x40 }, - { 0x10007798, 0x63 }, - { 0x10007799, 0x9c }, - { 0x1000779a, 0x07 }, - { 0x1000779b, 0x06 }, - { 0x1000779c, 0x13 }, - { 0x1000779d, 0x01 }, - { 0x1000779e, 0x01 }, - { 0x1000779f, 0xff }, - { 0x100077a0, 0x23 }, - { 0x100077a1, 0x22 }, - { 0x100077a2, 0x91 }, - { 0x100077a3, 0x00 }, - { 0x100077a4, 0x23 }, - { 0x100077a5, 0x26 }, - { 0x100077a6, 0x11 }, - { 0x100077a7, 0x00 }, - { 0x100077a8, 0x23 }, - { 0x100077a9, 0x24 }, - { 0x100077aa, 0x81 }, - { 0x100077ab, 0x00 }, - { 0x100077ac, 0xb7 }, - { 0x100077ad, 0xc4 }, - { 0x100077ae, 0x00 }, - { 0x100077af, 0x00 }, - { 0x100077b0, 0x83 }, - { 0x100077b1, 0xc7 }, - { 0x100077b2, 0x04 }, - { 0x100077b3, 0x56 }, - { 0x100077b4, 0x13 }, - { 0x100077b5, 0x07 }, - { 0x100077b6, 0x80 }, - { 0x100077b7, 0x01 }, - { 0x100077b8, 0x93 }, - { 0x100077b9, 0xf7 }, - { 0x100077ba, 0xf7 }, - { 0x100077bb, 0x0f }, - { 0x100077bc, 0x63 }, - { 0x100077bd, 0x70 }, - { 0x100077be, 0xf7 }, - { 0x100077bf, 0x04 }, - { 0x100077c0, 0x37 }, - { 0x100077c1, 0xd4 }, - { 0x100077c2, 0x00 }, - { 0x100077c3, 0x10 }, - { 0x100077c4, 0x83 }, - { 0x100077c5, 0x47 }, - { 0x100077c6, 0x54 }, - { 0x100077c7, 0xd9 }, - { 0x100077c8, 0x93 }, - { 0x100077c9, 0xf7 }, - { 0x100077ca, 0xf7 }, - { 0x100077cb, 0x0f }, - { 0x100077cc, 0x63 }, - { 0x100077cd, 0x88 }, - { 0x100077ce, 0x07 }, - { 0x100077cf, 0x02 }, - { 0x100077d0, 0x93 }, - { 0x100077d1, 0x07 }, - { 0x100077d2, 0x10 }, - { 0x100077d3, 0x00 }, - { 0x100077d4, 0x23 }, - { 0x100077d5, 0x82 }, - { 0x100077d6, 0xf4 }, - { 0x100077d7, 0x58 }, - { 0x100077d8, 0x03 }, - { 0x100077d9, 0x45 }, - { 0x100077da, 0x64 }, - { 0x100077db, 0xd9 }, - { 0x100077dc, 0xb7 }, - { 0x100077dd, 0x15 }, - { 0x100077de, 0x00 }, - { 0x100077df, 0x00 }, - { 0x100077e0, 0x93 }, - { 0x100077e1, 0x85 }, - { 0x100077e2, 0x85 }, - { 0x100077e3, 0x38 }, - { 0x100077e4, 0x13 }, - { 0x100077e5, 0x75 }, - { 0x100077e6, 0xf5 }, - { 0x100077e7, 0x0f }, - { 0x100077e8, 0xef }, - { 0x100077e9, 0xe0 }, - { 0x100077ea, 0x9f }, - { 0x100077eb, 0xd0 }, - { 0x100077ec, 0x93 }, - { 0x100077ed, 0x55 }, - { 0x100077ee, 0xf5 }, - { 0x100077ef, 0x41 }, - { 0x100077f0, 0xef }, - { 0x100077f1, 0xe0 }, - { 0x100077f2, 0x8f }, - { 0x100077f3, 0xa3 }, - { 0x100077f4, 0x23 }, - { 0x100077f5, 0x82 }, - { 0x100077f6, 0x04 }, - { 0x100077f7, 0x58 }, - { 0x100077f8, 0xa3 }, - { 0x100077f9, 0x0a }, - { 0x100077fa, 0x04 }, - { 0x100077fb, 0xd8 }, - { 0x100077fc, 0x83 }, - { 0x100077fd, 0x20 }, - { 0x100077fe, 0xc1 }, - { 0x100077ff, 0x00 }, - { 0x10007800, 0x03 }, - { 0x10007801, 0x24 }, - { 0x10007802, 0x81 }, - { 0x10007803, 0x00 }, - { 0x10007804, 0x83 }, - { 0x10007805, 0x24 }, - { 0x10007806, 0x41 }, - { 0x10007807, 0x00 }, - { 0x10007808, 0x13 }, - { 0x10007809, 0x01 }, - { 0x1000780a, 0x01 }, - { 0x1000780b, 0x01 }, - { 0x1000780c, 0x67 }, - { 0x1000780d, 0x80 }, - { 0x1000780e, 0x00 }, - { 0x1000780f, 0x00 }, - { 0x10007810, 0x67 }, - { 0x10007811, 0x80 }, - { 0x10007812, 0x00 }, - { 0x10007813, 0x00 }, - { 0x10007814, 0x13 }, - { 0x10007815, 0x01 }, - { 0x10007816, 0x01 }, - { 0x10007817, 0xff }, - { 0x10007818, 0x23 }, - { 0x10007819, 0x26 }, - { 0x1000781a, 0x11 }, - { 0x1000781b, 0x00 }, - { 0x1000781c, 0xef }, - { 0x1000781d, 0xd0 }, - { 0x1000781e, 0x8f }, - { 0x1000781f, 0x86 }, - { 0x10007820, 0x83 }, - { 0x10007821, 0xc7 }, - { 0x10007822, 0x11 }, - { 0x10007823, 0x42 }, - { 0x10007824, 0x63 }, - { 0x10007825, 0x86 }, - { 0x10007826, 0x07 }, - { 0x10007827, 0x00 }, - { 0x10007828, 0x03 }, - { 0x10007829, 0xc7 }, - { 0x1000782a, 0x01 }, - { 0x1000782b, 0x42 }, - { 0x1000782c, 0x63 }, - { 0x1000782d, 0x10 }, - { 0x1000782e, 0x07 }, - { 0x1000782f, 0x02 }, - { 0x10007830, 0x83 }, - { 0x10007831, 0xc6 }, - { 0x10007832, 0x21 }, - { 0x10007833, 0x41 }, - { 0x10007834, 0x13 }, - { 0x10007835, 0x07 }, - { 0x10007836, 0xf0 }, - { 0x10007837, 0x01 }, - { 0x10007838, 0x13 }, - { 0x10007839, 0x05 }, - { 0x1000783a, 0xf0 }, - { 0x1000783b, 0x01 }, - { 0x1000783c, 0x63 }, - { 0x1000783d, 0x98 }, - { 0x1000783e, 0xe6 }, - { 0x1000783f, 0x02 }, - { 0x10007840, 0x63 }, - { 0x10007841, 0x8a }, - { 0x10007842, 0x07 }, - { 0x10007843, 0x02 }, - { 0x10007844, 0x83 }, - { 0x10007845, 0xc7 }, - { 0x10007846, 0x01 }, - { 0x10007847, 0x42 }, - { 0x10007848, 0x63 }, - { 0x10007849, 0x86 }, - { 0x1000784a, 0x07 }, - { 0x1000784b, 0x02 }, - { 0x1000784c, 0x83 }, - { 0x1000784d, 0xc7 }, - { 0x1000784e, 0x31 }, - { 0x1000784f, 0x42 }, - { 0x10007850, 0x63 }, - { 0x10007851, 0x86 }, - { 0x10007852, 0x07 }, - { 0x10007853, 0x00 }, - { 0x10007854, 0x83 }, - { 0x10007855, 0xc7 }, - { 0x10007856, 0x21 }, - { 0x10007857, 0x42 }, - { 0x10007858, 0x63 }, - { 0x10007859, 0x9e }, - { 0x1000785a, 0x07 }, - { 0x1000785b, 0x00 }, - { 0x1000785c, 0x03 }, - { 0x1000785d, 0xc7 }, - { 0x1000785e, 0x21 }, - { 0x1000785f, 0x41 }, - { 0x10007860, 0x93 }, - { 0x10007861, 0x07 }, - { 0x10007862, 0xb0 }, - { 0x10007863, 0x01 }, - { 0x10007864, 0x63 }, - { 0x10007865, 0x08 }, - { 0x10007866, 0xf7 }, - { 0x10007867, 0x00 }, - { 0x10007868, 0x13 }, - { 0x10007869, 0x05 }, - { 0x1000786a, 0xb0 }, - { 0x1000786b, 0x01 }, - { 0x1000786c, 0xef }, - { 0x1000786d, 0xd0 }, - { 0x1000786e, 0x0f }, - { 0x1000786f, 0xcf }, - { 0x10007870, 0xef }, - { 0x10007871, 0xd0 }, - { 0x10007872, 0x8f }, - { 0x10007873, 0xa4 }, - { 0x10007874, 0x93 }, - { 0x10007875, 0x06 }, - { 0x10007876, 0x10 }, - { 0x10007877, 0x00 }, - { 0x10007878, 0xa3 }, - { 0x10007879, 0x89 }, - { 0x1000787a, 0xd1 }, - { 0x1000787b, 0x40 }, - { 0x1000787c, 0x37 }, - { 0x1000787d, 0xd7 }, - { 0x1000787e, 0x00 }, - { 0x1000787f, 0x10 }, - { 0x10007880, 0x83 }, - { 0x10007881, 0x47 }, - { 0x10007882, 0x07 }, - { 0x10007883, 0xd9 }, - { 0x10007884, 0x93 }, - { 0x10007885, 0xf7 }, - { 0x10007886, 0xf7 }, - { 0x10007887, 0x0f }, - { 0x10007888, 0x63 }, - { 0x10007889, 0x90 }, - { 0x1000788a, 0x07 }, - { 0x1000788b, 0x02 }, - { 0x1000788c, 0x37 }, - { 0x1000788d, 0xc6 }, - { 0x1000788e, 0x00 }, - { 0x1000788f, 0x00 }, - { 0x10007890, 0x83 }, - { 0x10007891, 0x47 }, - { 0x10007892, 0x26 }, - { 0x10007893, 0x04 }, - { 0x10007894, 0x93 }, - { 0x10007895, 0xe7 }, - { 0x10007896, 0x07 }, - { 0x10007897, 0xf8 }, - { 0x10007898, 0x93 }, - { 0x10007899, 0xf7 }, - { 0x1000789a, 0xf7 }, - { 0x1000789b, 0x0f }, - { 0x1000789c, 0x23 }, - { 0x1000789d, 0x01 }, - { 0x1000789e, 0xf6 }, - { 0x1000789f, 0x04 }, - { 0x100078a0, 0x23 }, - { 0x100078a1, 0x08 }, - { 0x100078a2, 0xd7 }, - { 0x100078a3, 0xd8 }, - { 0x100078a4, 0x23 }, - { 0x100078a5, 0x09 }, - { 0x100078a6, 0x07 }, - { 0x100078a7, 0xd8 }, - { 0x100078a8, 0x83 }, - { 0x100078a9, 0x20 }, - { 0x100078aa, 0xc1 }, - { 0x100078ab, 0x00 }, - { 0x100078ac, 0x13 }, - { 0x100078ad, 0x01 }, - { 0x100078ae, 0x01 }, - { 0x100078af, 0x01 }, - { 0x100078b0, 0x67 }, - { 0x100078b1, 0x80 }, - { 0x100078b2, 0x00 }, - { 0x100078b3, 0x00 }, - { 0x3fc2bfc7, 0x00 }, - { 0x3fc2bfc6, 0x00 }, - { 0x3fc2bfc5, 0x00 }, - { 0x3fc2bfc4, 0x01 }, - { 0x0000d486, 0x43 }, - { 0x1000db00, 0x02 }, - { 0x1000db01, 0x00 }, - { 0x1000db02, 0x11 }, - { 0x1000db03, 0x00 }, - { 0x1000db04, 0x00 }, - { 0x1000db05, 0x82 }, - { 0x1000db06, 0x04 }, - { 0x1000db07, 0xf1 }, - { 0x1000db08, 0x00 }, - { 0x1000db09, 0x00 }, - { 0x1000db0a, 0x40 }, - { 0x0000d540, 0x01 }, -}; - static const struct reg_default rt1320_reg_defaults[] = { { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, @@ -3733,17 +525,88 @@ static int rt1320_pde_transition_delay(struct rt1320_sdw_priv *rt1320, unsigned return 0; } +/* + * The 'patch code' is written to the patch code area. + * The patch code area is used for SDCA register expansion flexibility. + */ +static void rt1320_load_mcu_patch(struct rt1320_sdw_priv *rt1320) +{ + struct sdw_slave *slave = rt1320->sdw_slave; + const struct firmware *patch; + const char *filename; + unsigned int addr, val; + const unsigned char *ptr; + int ret, i; + + if (rt1320->version_id <= RT1320_VB) + filename = RT1320_VAB_MCU_PATCH; + else + filename = RT1320_VC_MCU_PATCH; + + /* load the patch code here */ + ret = request_firmware(&patch, filename, &slave->dev); + if (ret) { + dev_err(&slave->dev, "%s: Failed to load %s firmware", __func__, filename); + regmap_write(rt1320->regmap, 0xc598, 0x00); + regmap_write(rt1320->regmap, 0x10007000, 0x67); + regmap_write(rt1320->regmap, 0x10007001, 0x80); + regmap_write(rt1320->regmap, 0x10007002, 0x00); + regmap_write(rt1320->regmap, 0x10007003, 0x00); + } else { + ptr = (const unsigned char *)patch->data; + if ((patch->size % 8) == 0) { + for (i = 0; i < patch->size; i += 8) { + addr = (ptr[i] & 0xff) | (ptr[i + 1] & 0xff) << 8 | + (ptr[i + 2] & 0xff) << 16 | (ptr[i + 3] & 0xff) << 24; + val = (ptr[i + 4] & 0xff) | (ptr[i + 5] & 0xff) << 8 | + (ptr[i + 6] & 0xff) << 16 | (ptr[i + 7] & 0xff) << 24; + + if (addr > 0x10007ffff || addr < 0x10007000) { + dev_err(&slave->dev, "%s: the address 0x%x is wrong", __func__, addr); + goto _exit_; + } + if (val > 0xff) { + dev_err(&slave->dev, "%s: the value 0x%x is wrong", __func__, val); + goto _exit_; + } + regmap_write(rt1320->regmap, addr, val); + } + } +_exit_: + release_firmware(patch); + } +} + +static void rt1320_vab_preset(struct rt1320_sdw_priv *rt1320) +{ + unsigned int i, reg, val, delay; + + for (i = 0; i < ARRAY_SIZE(rt1320_blind_write); i++) { + reg = rt1320_blind_write[i].reg; + val = rt1320_blind_write[i].def; + delay = rt1320_blind_write[i].delay_us; + + if (reg == 0x3fc2bfc7) + rt1320_load_mcu_patch(rt1320); + + regmap_write(rt1320->regmap, reg, val); + if (delay) + usleep_range(delay, delay + 1000); + } +} + static void rt1320_vc_preset(struct rt1320_sdw_priv *rt1320) { struct sdw_slave *slave = rt1320->sdw_slave; unsigned int i, reg, val, delay, retry, tmp; - regmap_multi_reg_write(rt1320->regmap, rt1320_vc_blind_write, ARRAY_SIZE(rt1320_vc_blind_write)); + for (i = 0; i < ARRAY_SIZE(rt1320_vc_blind_write); i++) { + reg = rt1320_vc_blind_write[i].reg; + val = rt1320_vc_blind_write[i].def; + delay = rt1320_vc_blind_write[i].delay_us; - for (i = 0; i < ARRAY_SIZE(rt1320_vc_patch_code_write); i++) { - reg = rt1320_vc_patch_code_write[i].reg; - val = rt1320_vc_patch_code_write[i].def; - delay = rt1320_vc_patch_code_write[i].delay_us; + if (reg == 0x3fc2bf83) + rt1320_load_mcu_patch(rt1320); if ((reg == SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0)) && (val == 0x00)) { @@ -3762,6 +625,9 @@ static void rt1320_vc_preset(struct rt1320_sdw_priv *rt1320) regmap_write(rt1320->regmap, reg, val); if (delay) usleep_range(delay, delay + 1000); + + if (reg == SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0)) + rt1320_pde_transition_delay(rt1320, val); } } @@ -3799,13 +665,10 @@ static int rt1320_io_init(struct device *dev, struct sdw_slave *slave) /* initialization write */ if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION)) { - if (rt1320->version_id < RT1320_VC) { - regmap_multi_reg_write(rt1320->regmap, rt1320_blind_write, ARRAY_SIZE(rt1320_blind_write)); - regmap_multi_reg_write(rt1320->regmap, rt1320_patch_code_write, - ARRAY_SIZE(rt1320_patch_code_write)); - } else if (rt1320->version_id == RT1320_VC) { + if (rt1320->version_id < RT1320_VC) + rt1320_vab_preset(rt1320); + else rt1320_vc_preset(rt1320); - } regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0), diff --git a/sound/soc/codecs/rt1320-sdw.h b/sound/soc/codecs/rt1320-sdw.h index 1fbc1fcd71cf..95ef9d37c6db 100644 --- a/sound/soc/codecs/rt1320-sdw.h +++ b/sound/soc/codecs/rt1320-sdw.h @@ -82,6 +82,8 @@ enum rt1320_version_id { }; #define RT1320_VER_B_ID 0x07392238 +#define RT1320_VAB_MCU_PATCH "realtek/rt1320/rt1320-patch-code-vab.bin" +#define RT1320_VC_MCU_PATCH "realtek/rt1320/rt1320-patch-code-vc.bin" struct rt1320_sdw_priv { struct snd_soc_component *component; From 230c4286d7e7c33705258cba570ced9f3ec8a363 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:28 +0100 Subject: [PATCH 030/256] ASoC: bcm2835-i2s: Use maple tree register cache JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9e3da79544de209c006b6b4c1514be52a48a2c1d Author: Mark Brown Date: Tue Sep 24 18:21:20 2024 +0200 ASoC: bcm2835-i2s: Use maple tree register cache The bcm2835 I2S driver uses a rbtree register cache but has no clear need to do so. Since the maple tree cache uses a more modern data structure and makes implementation decisions more suitable for current systems switch the driver to use that instead. No functional changes. Signed-off-by: Mark Brown Link: https://patch.msgid.link/20240924-asoc-bcm-maple-v1-1-9d221f4a0195@kernel.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/bcm/bcm2835-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index 9bda6499e66e..87d2f06c2f53 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -817,7 +817,7 @@ static const struct regmap_config bcm2835_regmap_config = { .max_register = BCM2835_I2S_GRAY_REG, .precious_reg = bcm2835_i2s_precious_reg, .volatile_reg = bcm2835_i2s_volatile_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static const struct snd_soc_component_driver bcm2835_i2s_component = { From 7bae9b31d03b212a4a579b53e58a4fd036cd1a01 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:28 +0100 Subject: [PATCH 031/256] ASoC: tas5805m: Improve a size determination in tas5805m_i2c_probe() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0e9f73f109025f0d5d16b104b6684e6c03aa0c83 Author: Markus Elfring Date: Mon Sep 16 10:20:12 2024 +0200 ASoC: tas5805m: Improve a size determination in tas5805m_i2c_probe() Replace the specification of a data structure by a pointer dereference as the parameter for the operator "sizeof" to make the corresponding size determination a bit safer according to the Linux coding style convention. Signed-off-by: Markus Elfring Link: https://patch.msgid.link/6a6c87d3-9e4f-4980-ae06-b0d5e16dd0c0@web.de Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/tas5805m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c index 72baa889c6fa..183134725bda 100644 --- a/sound/soc/codecs/tas5805m.c +++ b/sound/soc/codecs/tas5805m.c @@ -474,7 +474,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c) return ret; } - tas5805m = devm_kzalloc(dev, sizeof(struct tas5805m_priv), GFP_KERNEL); + tas5805m = devm_kzalloc(dev, sizeof(*tas5805m), GFP_KERNEL); if (!tas5805m) return -ENOMEM; From a164c4f4583173c932b336576104c815a1c7632b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:29 +0100 Subject: [PATCH 032/256] ASoC: fsl: Use maple tree register cache JIRA: https://issues.redhat.com/browse/RHEL-80681 commit bbeffdda5f26a56072cb8cf741f4c52bc2174838 Author: Mark Brown Date: Tue Sep 24 15:58:42 2024 +0200 ASoC: fsl: Use maple tree register cache Several of the NXP drivers use regmaps with a rbtree register cache. Since the maple tree cache is using a generally more modern data structure which makes implementation choices more suitable for modern systems let's convert these drivers to it. This should have no practical impact. Signed-off-by: Mark Brown Link: https://patch.msgid.link/20240924-asoc-imx-maple-v1-1-8b993901f71e@kernel.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/fsl/fsl_aud2htx.c | 2 +- sound/soc/fsl/fsl_easrc.c | 2 +- sound/soc/fsl/fsl_micfil.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_aud2htx.c b/sound/soc/fsl/fsl_aud2htx.c index f8105c41c6f7..c927a9240807 100644 --- a/sound/soc/fsl/fsl_aud2htx.c +++ b/sound/soc/fsl/fsl_aud2htx.c @@ -169,7 +169,7 @@ static const struct regmap_config fsl_aud2htx_regmap_config = { .readable_reg = fsl_aud2htx_readable_reg, .volatile_reg = fsl_aud2htx_volatile_reg, .writeable_reg = fsl_aud2htx_writeable_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static const struct of_device_id fsl_aud2htx_dt_ids[] = { diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 4e260f40352b..33c744a2c123 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1748,7 +1748,7 @@ static const struct regmap_config fsl_easrc_regmap_config = { .rd_table = &fsl_easrc_readable_table, .wr_table = &fsl_easrc_writeable_table, .volatile_table = &fsl_easrc_volatileable_table, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; #ifdef DEBUG diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index 3c756d3cf4e9..2752abea7501 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -1044,7 +1044,7 @@ static const struct regmap_config fsl_micfil_regmap_config = { .readable_reg = fsl_micfil_readable_reg, .volatile_reg = fsl_micfil_volatile_reg, .writeable_reg = fsl_micfil_writeable_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; /* END OF REGMAP */ From db745087898de8df0b91ea0ce380302c0a8e0335 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:29 +0100 Subject: [PATCH 033/256] ASoC: codecs: aw88399: Fix spelling mistake "unsupport" -> "unsupported" JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 04e800fc328e6eba9f4ec3df375f2b500802653a Author: Colin Ian King Date: Mon Sep 23 13:03:25 2024 +0100 ASoC: codecs: aw88399: Fix spelling mistake "unsupport" -> "unsupported" There is a spelling mistake in a dev_err message. Fix it. Signed-off-by: Colin Ian King Link: https://patch.msgid.link/20240923120325.836918-1-colin.i.king@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/aw88399.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/aw88399.c b/sound/soc/codecs/aw88399.c index bba59885242d..ee3cc2a95f85 100644 --- a/sound/soc/codecs/aw88399.c +++ b/sound/soc/codecs/aw88399.c @@ -462,7 +462,7 @@ static int aw_dev_set_vcalb(struct aw88399 *aw88399) vcal_k * aw88399->vcalb_init_val; break; default: - dev_err(aw_dev->dev, "%s: unsupport vsense\n", __func__); + dev_err(aw_dev->dev, "%s: unsupported vsense\n", __func__); ret = -EINVAL; break; } From ebecf8710d21a2ac5f7eaede81011255c47e1482 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:29 +0100 Subject: [PATCH 034/256] ASoC: rt1320: fix the range of patch code address JIRA: https://issues.redhat.com/browse/RHEL-80681 commit a34b9d812d7ec95789b15ce84de5f03c6dd1137b Author: Shuming Fan Date: Tue Oct 1 15:18:36 2024 +0800 ASoC: rt1320: fix the range of patch code address >> sound/soc/codecs/rt1320-sdw.c:564:14: warning: result of comparison of constant 4295491583 with expression of type 'unsigned int' is always false [-Wtautological-constant-out-of-range-compare] 564 | if (addr > 0x10007ffff || addr < 0x10007000) { | ~~~~ ^ ~~~~~~~~~~~ 1 warning generated. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202410011159.InLKFd40-lkp@intel.com/ Signed-off-by: Shuming Fan Link: https://patch.msgid.link/20241001071836.3719162-1-shumingf@realtek.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/rt1320-sdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c index 2404de8ae03d..ebd6f09bd990 100644 --- a/sound/soc/codecs/rt1320-sdw.c +++ b/sound/soc/codecs/rt1320-sdw.c @@ -561,7 +561,7 @@ static void rt1320_load_mcu_patch(struct rt1320_sdw_priv *rt1320) val = (ptr[i + 4] & 0xff) | (ptr[i + 5] & 0xff) << 8 | (ptr[i + 6] & 0xff) << 16 | (ptr[i + 7] & 0xff) << 24; - if (addr > 0x10007ffff || addr < 0x10007000) { + if (addr > 0x10007fff || addr < 0x10007000) { dev_err(&slave->dev, "%s: the address 0x%x is wrong", __func__, addr); goto _exit_; } From f50f8f7f3b0bbece196bce50379a8f90ffa27ebc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:29 +0100 Subject: [PATCH 035/256] ASoC: amd: acp: drop bogus NULL check from i2s_irq_handler JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 8cd4e1f087b6906bacbbf8b637cac4e479a9cb34 Author: Murad Masimov Date: Tue Oct 1 22:08:39 2024 +0300 ASoC: amd: acp: drop bogus NULL check from i2s_irq_handler When i2s_irq_handler is called, it's guaranteed that adata is not NULL, since IRQ handlers are guaranteed to be provided with a valid data pointer. Moreover, adata pointer is being dereferenced right before the NULL check, which makes the check pointless, even if adata could be NULL. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Murad Masimov Link: https://patch.msgid.link/20241001190848.711-1-m.masimov@maxima.ru Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-platform.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index 7be9b4ff7923..1f352b2b3002 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -143,9 +143,6 @@ static irqreturn_t i2s_irq_handler(int irq, void *data) u16 i2s_flag = 0; u32 ext_intr_stat, ext_intr_stat1; - if (!adata) - return IRQ_NONE; - if (adata->rsrc->no_of_ctrls == 2) ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1))); From d0b870fe041746b013935d6022098e6a44af12a9 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:29 +0100 Subject: [PATCH 036/256] ASoC: codecs: wcd9335: remove unnecessary MODULE_ALIAS() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 6061483d7141db3a805f8660eae23805af02d544 Author: Masahiro Yamada Date: Thu Oct 3 00:14:34 2024 +0900 ASoC: codecs: wcd9335: remove unnecessary MODULE_ALIAS() Since commit b4b818305578 ("slimbus: generate MODULE_ALIAS() from MODULE_DEVICE_TABLE()"), modpost automatically generates MODULE_ALIAS() from MODULE_DEVICE_TABLE(slim, ). Signed-off-by: Masahiro Yamada Link: https://patch.msgid.link/20241002151436.43684-1-masahiroy@kernel.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/wcd9335.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 373a31ddccb2..a2521e16c099 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -5177,4 +5177,3 @@ static struct slim_driver wcd9335_slim_driver = { module_slim_driver(wcd9335_slim_driver); MODULE_DESCRIPTION("WCD9335 slim driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("slim:217:1a0:*"); From 4d5927704b0c3d8eae06b1f72bc36ff0414c265b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:29 +0100 Subject: [PATCH 037/256] soundwire: amd: refactor existing code for acp 6.3 platform JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7b54323dde29452dd06e6acd2701d9b489c9547d Author: Vijendar Mukunda Date: Tue Sep 24 13:48:44 2024 +0530 soundwire: amd: refactor existing code for acp 6.3 platform Refactor existing code by adding acp pci revision id coditional checks for ACP 6.3 platform. Rename the macros and structure names with ACP63 tag. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20240924081846.1834612-3-Vijendar.Mukunda@amd.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/amd_manager.c | 98 ++++++++++++++++++++----------- drivers/soundwire/amd_manager.h | 16 ++--- include/linux/soundwire/sdw_amd.h | 1 + 3 files changed, 72 insertions(+), 43 deletions(-) diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c index 0d01849c3586..0d26d755b6de 100644 --- a/drivers/soundwire/amd_manager.c +++ b/drivers/soundwire/amd_manager.c @@ -433,12 +433,18 @@ static int amd_sdw_port_params(struct sdw_bus *bus, struct sdw_port_params *p_pa u32 frame_fmt_reg, dpn_frame_fmt; dev_dbg(amd_manager->dev, "p_params->num:0x%x\n", p_params->num); - switch (amd_manager->instance) { - case ACP_SDW0: - frame_fmt_reg = sdw0_manager_dp_reg[p_params->num].frame_fmt_reg; - break; - case ACP_SDW1: - frame_fmt_reg = sdw1_manager_dp_reg[p_params->num].frame_fmt_reg; + switch (amd_manager->acp_rev) { + case ACP63_PCI_REV_ID: + switch (amd_manager->instance) { + case ACP_SDW0: + frame_fmt_reg = acp63_sdw0_dp_reg[p_params->num].frame_fmt_reg; + break; + case ACP_SDW1: + frame_fmt_reg = acp63_sdw1_dp_reg[p_params->num].frame_fmt_reg; + break; + default: + return -EINVAL; + } break; default: return -EINVAL; @@ -465,20 +471,28 @@ static int amd_sdw_transport_params(struct sdw_bus *bus, u32 frame_fmt_reg, sample_int_reg, hctrl_dp0_reg; u32 offset_reg, lane_ctrl_ch_en_reg; - switch (amd_manager->instance) { - case ACP_SDW0: - frame_fmt_reg = sdw0_manager_dp_reg[params->port_num].frame_fmt_reg; - sample_int_reg = sdw0_manager_dp_reg[params->port_num].sample_int_reg; - hctrl_dp0_reg = sdw0_manager_dp_reg[params->port_num].hctrl_dp0_reg; - offset_reg = sdw0_manager_dp_reg[params->port_num].offset_reg; - lane_ctrl_ch_en_reg = sdw0_manager_dp_reg[params->port_num].lane_ctrl_ch_en_reg; - break; - case ACP_SDW1: - frame_fmt_reg = sdw1_manager_dp_reg[params->port_num].frame_fmt_reg; - sample_int_reg = sdw1_manager_dp_reg[params->port_num].sample_int_reg; - hctrl_dp0_reg = sdw1_manager_dp_reg[params->port_num].hctrl_dp0_reg; - offset_reg = sdw1_manager_dp_reg[params->port_num].offset_reg; - lane_ctrl_ch_en_reg = sdw1_manager_dp_reg[params->port_num].lane_ctrl_ch_en_reg; + switch (amd_manager->acp_rev) { + case ACP63_PCI_REV_ID: + switch (amd_manager->instance) { + case ACP_SDW0: + frame_fmt_reg = acp63_sdw0_dp_reg[params->port_num].frame_fmt_reg; + sample_int_reg = acp63_sdw0_dp_reg[params->port_num].sample_int_reg; + hctrl_dp0_reg = acp63_sdw0_dp_reg[params->port_num].hctrl_dp0_reg; + offset_reg = acp63_sdw0_dp_reg[params->port_num].offset_reg; + lane_ctrl_ch_en_reg = + acp63_sdw0_dp_reg[params->port_num].lane_ctrl_ch_en_reg; + break; + case ACP_SDW1: + frame_fmt_reg = acp63_sdw1_dp_reg[params->port_num].frame_fmt_reg; + sample_int_reg = acp63_sdw1_dp_reg[params->port_num].sample_int_reg; + hctrl_dp0_reg = acp63_sdw1_dp_reg[params->port_num].hctrl_dp0_reg; + offset_reg = acp63_sdw1_dp_reg[params->port_num].offset_reg; + lane_ctrl_ch_en_reg = + acp63_sdw1_dp_reg[params->port_num].lane_ctrl_ch_en_reg; + break; + default: + return -EINVAL; + } break; default: return -EINVAL; @@ -520,12 +534,20 @@ static int amd_sdw_port_enable(struct sdw_bus *bus, u32 dpn_ch_enable; u32 lane_ctrl_ch_en_reg; - switch (amd_manager->instance) { - case ACP_SDW0: - lane_ctrl_ch_en_reg = sdw0_manager_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg; - break; - case ACP_SDW1: - lane_ctrl_ch_en_reg = sdw1_manager_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg; + switch (amd_manager->acp_rev) { + case ACP63_PCI_REV_ID: + switch (amd_manager->instance) { + case ACP_SDW0: + lane_ctrl_ch_en_reg = + acp63_sdw0_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg; + break; + case ACP_SDW1: + lane_ctrl_ch_en_reg = + acp63_sdw1_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg; + break; + default: + return -EINVAL; + } break; default: return -EINVAL; @@ -926,15 +948,21 @@ static int amd_sdw_manager_probe(struct platform_device *pdev) * information. */ amd_manager->bus.controller_id = 0; - - switch (amd_manager->instance) { - case ACP_SDW0: - amd_manager->num_dout_ports = AMD_SDW0_MAX_TX_PORTS; - amd_manager->num_din_ports = AMD_SDW0_MAX_RX_PORTS; - break; - case ACP_SDW1: - amd_manager->num_dout_ports = AMD_SDW1_MAX_TX_PORTS; - amd_manager->num_din_ports = AMD_SDW1_MAX_RX_PORTS; + dev_dbg(dev, "acp_rev:0x%x\n", amd_manager->acp_rev); + switch (amd_manager->acp_rev) { + case ACP63_PCI_REV_ID: + switch (amd_manager->instance) { + case ACP_SDW0: + amd_manager->num_dout_ports = AMD_ACP63_SDW0_MAX_TX_PORTS; + amd_manager->num_din_ports = AMD_ACP63_SDW0_MAX_RX_PORTS; + break; + case ACP_SDW1: + amd_manager->num_dout_ports = AMD_ACP63_SDW1_MAX_TX_PORTS; + amd_manager->num_din_ports = AMD_ACP63_SDW1_MAX_RX_PORTS; + break; + default: + return -EINVAL; + } break; default: return -EINVAL; diff --git a/drivers/soundwire/amd_manager.h b/drivers/soundwire/amd_manager.h index 707065468e05..cc2170e4521e 100644 --- a/drivers/soundwire/amd_manager.h +++ b/drivers/soundwire/amd_manager.h @@ -155,12 +155,12 @@ #define AMD_SDW_IRQ_MASK_8TO11 0x000c7777 #define AMD_SDW_IRQ_ERROR_MASK 0xff #define AMD_SDW_MAX_FREQ_NUM 1 -#define AMD_SDW0_MAX_TX_PORTS 3 -#define AMD_SDW0_MAX_RX_PORTS 3 -#define AMD_SDW1_MAX_TX_PORTS 1 -#define AMD_SDW1_MAX_RX_PORTS 1 -#define AMD_SDW0_MAX_DAI 6 -#define AMD_SDW1_MAX_DAI 2 +#define AMD_ACP63_SDW0_MAX_TX_PORTS 3 +#define AMD_ACP63_SDW0_MAX_RX_PORTS 3 +#define AMD_ACP63_SDW1_MAX_TX_PORTS 1 +#define AMD_ACP63_SDW1_MAX_RX_PORTS 1 +#define AMD_ACP63_SDW0_MAX_DAI 6 +#define AMD_ACP63_SDW1_MAX_DAI 2 #define AMD_SDW_SLAVE_0_ATTACHED 5 #define AMD_SDW_SSP_COUNTER_VAL 3 @@ -222,7 +222,7 @@ struct sdw_manager_dp_reg { * in SoundWire DMA driver. */ -static struct sdw_manager_dp_reg sdw0_manager_dp_reg[AMD_SDW0_MAX_DAI] = { +static struct sdw_manager_dp_reg acp63_sdw0_dp_reg[AMD_ACP63_SDW0_MAX_DAI] = { {ACP_SW_AUDIO0_TX_FRAME_FORMAT, ACP_SW_AUDIO0_TX_SAMPLEINTERVAL, ACP_SW_AUDIO0_TX_HCTRL_DP0, ACP_SW_AUDIO0_TX_OFFSET_DP0, ACP_SW_AUDIO0_TX_CHANNEL_ENABLE_DP0}, {ACP_SW_AUDIO1_TX_FRAME_FORMAT, ACP_SW_AUDIO1_TX_SAMPLEINTERVAL, ACP_SW_AUDIO1_TX_HCTRL, @@ -237,7 +237,7 @@ static struct sdw_manager_dp_reg sdw0_manager_dp_reg[AMD_SDW0_MAX_DAI] = { ACP_SW_AUDIO2_RX_OFFSET, ACP_SW_AUDIO2_RX_CHANNEL_ENABLE_DP0}, }; -static struct sdw_manager_dp_reg sdw1_manager_dp_reg[AMD_SDW1_MAX_DAI] = { +static struct sdw_manager_dp_reg acp63_sdw1_dp_reg[AMD_ACP63_SDW1_MAX_DAI] = { {ACP_SW_AUDIO1_TX_FRAME_FORMAT, ACP_SW_AUDIO1_TX_SAMPLEINTERVAL, ACP_SW_AUDIO1_TX_HCTRL, ACP_SW_AUDIO1_TX_OFFSET, ACP_SW_AUDIO1_TX_CHANNEL_ENABLE_DP0}, {ACP_SW_AUDIO1_RX_FRAME_FORMAT, ACP_SW_AUDIO1_RX_SAMPLEINTERVAL, ACP_SW_AUDIO1_RX_HCTRL, diff --git a/include/linux/soundwire/sdw_amd.h b/include/linux/soundwire/sdw_amd.h index 28a4eb77717f..6362cdb190d7 100644 --- a/include/linux/soundwire/sdw_amd.h +++ b/include/linux/soundwire/sdw_amd.h @@ -27,6 +27,7 @@ #define ACP_SDW0 0 #define ACP_SDW1 1 #define AMD_SDW_MAX_MANAGER_COUNT 2 +#define ACP63_PCI_REV_ID 0x63 struct acp_sdw_pdata { u16 instance; From 3383bc40a643f3ce02bc594cf514f7634f55dbdc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:30 +0100 Subject: [PATCH 038/256] soundwire: amd: pass acp pci revision id as resource data JIRA: https://issues.redhat.com/browse/RHEL-80681 commit ced20ea315fe8591093f19574ec32222c1ab71ba Author: Vijendar Mukunda Date: Tue Sep 24 13:48:43 2024 +0530 soundwire: amd: pass acp pci revision id as resource data Pass ACP pci revision id as resource data and store it in amd SoundWire manager private data structure. This field will be used to differentiate ACP variants. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20240924081846.1834612-2-Vijendar.Mukunda@amd.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/amd_init.c | 1 + drivers/soundwire/amd_manager.c | 1 + include/linux/soundwire/sdw_amd.h | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/drivers/soundwire/amd_init.c b/drivers/soundwire/amd_init.c index db040f435059..4f6e356e6bd2 100644 --- a/drivers/soundwire/amd_init.c +++ b/drivers/soundwire/amd_init.c @@ -121,6 +121,7 @@ static struct sdw_amd_ctx *sdw_amd_probe_controller(struct sdw_amd_res *res) sdw_pdata[index].instance = index; sdw_pdata[index].acp_sdw_lock = res->acp_lock; + sdw_pdata[index].acp_rev = res->acp_rev; pdevinfo[index].name = "amd_sdw_manager"; pdevinfo[index].id = index; pdevinfo[index].parent = res->parent; diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c index 0d26d755b6de..5a4bfaef65fb 100644 --- a/drivers/soundwire/amd_manager.c +++ b/drivers/soundwire/amd_manager.c @@ -932,6 +932,7 @@ static int amd_sdw_manager_probe(struct platform_device *pdev) amd_manager->mmio = amd_manager->acp_mmio + (amd_manager->instance * SDW_MANAGER_REG_OFFSET); amd_manager->acp_sdw_lock = pdata->acp_sdw_lock; + amd_manager->acp_rev = pdata->acp_rev; amd_manager->cols_index = sdw_find_col_index(AMD_SDW_DEFAULT_COLUMNS); amd_manager->rows_index = sdw_find_row_index(AMD_SDW_DEFAULT_ROWS); amd_manager->dev = dev; diff --git a/include/linux/soundwire/sdw_amd.h b/include/linux/soundwire/sdw_amd.h index 6362cdb190d7..c9586f22c5a9 100644 --- a/include/linux/soundwire/sdw_amd.h +++ b/include/linux/soundwire/sdw_amd.h @@ -31,6 +31,7 @@ struct acp_sdw_pdata { u16 instance; + u32 acp_rev; /* mutex to protect acp common register access */ struct mutex *acp_sdw_lock; }; @@ -67,6 +68,7 @@ struct sdw_amd_dai_runtime { * @instance: SoundWire manager instance * @quirks: SoundWire manager quirks * @wake_en_mask: wake enable mask per SoundWire manager + * @acp_rev: acp pci device revision id * @clk_stopped: flag set to true when clock is stopped * @power_mode_mask: flag interprets amd SoundWire manager power mode * @dai_runtime_array: dai runtime array @@ -95,6 +97,7 @@ struct amd_sdw_manager { u32 quirks; u32 wake_en_mask; u32 power_mode_mask; + u32 acp_rev; bool clk_stopped; struct sdw_amd_dai_runtime **dai_runtime_array; @@ -135,6 +138,7 @@ struct sdw_amd_ctx { * struct sdw_amd_res - Soundwire AMD global resource structure, * typically populated by the DSP driver/Legacy driver * + * @acp_rev: acp pci device revision id * @addr: acp pci device resource start address * @reg_range: ACP register range * @link_mask: bit-wise mask listing links selected by the DSP driver/ @@ -147,6 +151,7 @@ struct sdw_amd_ctx { * @acp_lock: mutex protecting acp common registers access */ struct sdw_amd_res { + u32 acp_rev; u32 addr; u32 reg_range; u32 link_mask; From 997950c3546705d904e3b88ca0d7709446fe304c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:30 +0100 Subject: [PATCH 039/256] ASoC: amd: ps: pass acp pci revision id as soundwire resource data JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 425f598ea69713b9e60f08e48a19be56b7bfddbc Author: Vijendar Mukunda Date: Tue Sep 24 13:48:46 2024 +0530 ASoC: amd: ps: pass acp pci revision id as soundwire resource data Add acp_rev as structure member in acp pci driver private data structure to store acp pci revision id and assign this variable to SoundWire resource data acp_rev variable. Signed-off-by: Vijendar Mukunda Acked-by: Mark Brown Link: https://lore.kernel.org/r/20240924081846.1834612-5-Vijendar.Mukunda@amd.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- sound/soc/amd/ps/acp63.h | 2 ++ sound/soc/amd/ps/pci-ps.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 39208305dd6c..e54eabaa4d3e 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -231,6 +231,7 @@ struct sdw_dma_ring_buf_reg { * @sdw_en_stat: flag set to true when any one of the SoundWire manager instance is enabled * @addr: pci ioremap address * @reg_range: ACP reigister range + * @acp_rev: ACP PCI revision id * @sdw0-dma_intr_stat: DMA interrupt status array for SoundWire manager-SW0 instance * @sdw_dma_intr_stat: DMA interrupt status array for SoundWire manager-SW1 instance */ @@ -254,6 +255,7 @@ struct acp63_dev_data { bool sdw_en_stat; u32 addr; u32 reg_range; + u32 acp_rev; u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS]; u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; }; diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 5c4a0be7a788..9872c7597d71 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -267,6 +267,7 @@ static int amd_sdw_probe(struct device *dev) sdw_res.acp_lock = &acp_data->acp_lock; sdw_res.count = acp_data->info.count; sdw_res.mmio_base = acp_data->acp63_base; + sdw_res.acp_rev = acp_data->acp_rev; sdw_res.link_mask = acp_data->info.link_mask; ret = sdw_amd_probe(&sdw_res, &acp_data->sdw); if (ret) @@ -591,6 +592,7 @@ static int snd_acp63_probe(struct pci_dev *pci, } adata->addr = addr; adata->reg_range = ACP63_REG_END - ACP63_REG_START; + adata->acp_rev = pci->revision; pci_set_master(pci); pci_set_drvdata(pci, adata); mutex_init(&adata->acp_lock); From a68c74d7600edd683a62fc9a9a0666667751386b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:30 +0100 Subject: [PATCH 040/256] ASoC: SOF: amd: pass acp_rev as soundwire resource data JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1bb50ead592ceaf2b1572c7d08797b8b3229432e Author: Vijendar Mukunda Date: Tue Sep 24 13:48:45 2024 +0530 ASoC: SOF: amd: pass acp_rev as soundwire resource data Pass acp_rev(ACP pci revision id) as soundwire resource data for SoundWire controller probe function. Signed-off-by: Vijendar Mukunda Acked-by: Mark Brown Link: https://lore.kernel.org/r/20240924081846.1834612-4-Vijendar.Mukunda@amd.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- sound/soc/sof/amd/acp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index 95d4762c9d93..f7814dadf3ba 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -693,6 +693,7 @@ static int amd_sof_sdw_probe(struct snd_sof_dev *sdev) sdw_res.count = acp_data->info.count; sdw_res.link_mask = acp_data->info.link_mask; sdw_res.mmio_base = sdev->bar[ACP_DSP_BAR]; + sdw_res.acp_rev = acp_data->pci_rev; ret = sdw_amd_probe(&sdw_res, &acp_data->sdw); if (ret) From 67524487e417f36d4ba45b068606aa659400d6d6 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:30 +0100 Subject: [PATCH 041/256] soundwire: Correct some typos in comments JIRA: https://issues.redhat.com/browse/RHEL-80681 commit a54dc8c68a5b33ca00b8dcd3b87681aacfbfc9dc Author: Shen Lichuan Date: Wed Sep 25 16:11:34 2024 +0800 soundwire: Correct some typos in comments Fixed some confusing spelling errors that were currently identified, the details are as follows: -in the code comments: drivers/soundwire/bus.c:115: enumuration==> enumeration drivers/soundwire/qcom.c:1176: wil ==> will drivers/soundwire/sysfs_slave.c:218: highligh ==> highlight Signed-off-by: Shen Lichuan Link: https://lore.kernel.org/r/20240925081134.10248-1-shenlichuan@vivo.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/bus.c | 2 +- drivers/soundwire/qcom.c | 2 +- drivers/soundwire/sysfs_slave.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 263ca32f0c5c..d1dc62c34f1c 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -112,7 +112,7 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, /* Set higher order bits */ *bus->assigned = ~GENMASK(SDW_BROADCAST_DEV_NUM, SDW_ENUM_DEV_NUM); - /* Set enumuration device number and broadcast device number */ + /* Set enumeration device number and broadcast device number */ set_bit(SDW_ENUM_DEV_NUM, bus->assigned); set_bit(SDW_BROADCAST_DEV_NUM, bus->assigned); diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index aed57002fd0e..2b403b14066c 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -1173,7 +1173,7 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl, else sconfig.direction = SDW_DATA_DIR_RX; - /* hw parameters wil be ignored as we only support PDM */ + /* hw parameters will be ignored as we only support PDM */ sconfig.ch_count = 1; sconfig.frame_rate = params_rate(params); sconfig.type = stream->type; diff --git a/drivers/soundwire/sysfs_slave.c b/drivers/soundwire/sysfs_slave.c index 83e3f6cc3250..fe1d4a5a4793 100644 --- a/drivers/soundwire/sysfs_slave.c +++ b/drivers/soundwire/sysfs_slave.c @@ -224,7 +224,7 @@ int sdw_slave_sysfs_init(struct sdw_slave *slave) /* * the status is shown in capital letters for UNATTACHED and RESERVED - * on purpose, to highligh users to the fact that these status values + * on purpose, to highlight users to the fact that these status values * are not expected. */ static const char *const slave_status[] = { From be8188313ca81d865de5d259415f1325db480e46 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:30 +0100 Subject: [PATCH 042/256] soundwire: optimize sdw_dpn_prop JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9942f90bdcc035eb5f01d7343dac99bd805ef3ec Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:43 2024 +0800 soundwire: optimize sdw_dpn_prop before: struct sdw_dpn_prop { u32 num; /* 0 4 */ u32 max_word; /* 4 4 */ u32 min_word; /* 8 4 */ u32 num_words; /* 12 4 */ u32 * words; /* 16 8 */ enum sdw_dpn_type type; /* 24 4 */ u32 max_grouping; /* 28 4 */ bool simple_ch_prep_sm; /* 32 1 */ /* XXX 3 bytes hole, try to pack */ u32 ch_prep_timeout; /* 36 4 */ u32 imp_def_interrupts; /* 40 4 */ u32 max_ch; /* 44 4 */ u32 min_ch; /* 48 4 */ u32 num_channels; /* 52 4 */ u32 * channels; /* 56 8 */ /* --- cacheline 1 boundary (64 bytes) --- */ u32 num_ch_combinations; /* 64 4 */ /* XXX 4 bytes hole, try to pack */ u32 * ch_combinations; /* 72 8 */ u32 modes; /* 80 4 */ u32 max_async_buffer; /* 84 4 */ bool block_pack_mode; /* 88 1 */ bool read_only_wordlength; /* 89 1 */ /* XXX 2 bytes hole, try to pack */ u32 port_encoding; /* 92 4 */ struct sdw_dpn_audio_mode * audio_modes; /* 96 8 */ /* size: 104, cachelines: 2, members: 22 */ /* sum members: 95, holes: 3, sum holes: 9 */ /* last cacheline: 40 bytes */ }; after: struct sdw_dpn_prop { struct sdw_dpn_audio_mode * audio_modes; /* 0 8 */ u32 num; /* 8 4 */ u32 max_word; /* 12 4 */ u32 min_word; /* 16 4 */ u32 num_words; /* 20 4 */ u32 * words; /* 24 8 */ enum sdw_dpn_type type; /* 32 4 */ u32 max_grouping; /* 36 4 */ u32 ch_prep_timeout; /* 40 4 */ u32 imp_def_interrupts; /* 44 4 */ u32 max_ch; /* 48 4 */ u32 min_ch; /* 52 4 */ u32 num_channels; /* 56 4 */ u32 num_ch_combinations; /* 60 4 */ /* --- cacheline 1 boundary (64 bytes) --- */ u32 * channels; /* 64 8 */ u32 * ch_combinations; /* 72 8 */ u32 modes; /* 80 4 */ u32 max_async_buffer; /* 84 4 */ u32 port_encoding; /* 88 4 */ bool block_pack_mode; /* 92 1 */ bool read_only_wordlength; /* 93 1 */ bool simple_ch_prep_sm; /* 94 1 */ /* size: 96, cachelines: 2, members: 22 */ /* padding: 1 */ /* last cacheline: 32 bytes */ }; Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-8-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- include/linux/soundwire/sdw.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 5e0dd47a0412..0afe07510daa 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -288,6 +288,7 @@ struct sdw_dpn_audio_mode { /** * struct sdw_dpn_prop - Data Port DPn properties + * @audio_modes: Audio modes supported * @num: port number * @max_word: Maximum number of bits in a Payload Channel Sample, 1 to 64 * (inclusive) @@ -298,26 +299,26 @@ struct sdw_dpn_audio_mode { * @type: Data port type. Full, Simplified or Reduced * @max_grouping: Maximum number of samples that can be grouped together for * a full data port - * @simple_ch_prep_sm: If the port supports simplified channel prepare state - * machine * @ch_prep_timeout: Port-specific timeout value, in milliseconds * @imp_def_interrupts: If set, each bit corresponds to support for * implementation-defined interrupts * @max_ch: Maximum channels supported * @min_ch: Minimum channels supported * @num_channels: Number of discrete channels supported - * @channels: Discrete channels supported * @num_ch_combinations: Number of channel combinations supported + * @channels: Discrete channels supported * @ch_combinations: Channel combinations supported * @modes: SDW mode supported * @max_async_buffer: Number of samples that this port can buffer in * asynchronous modes + * @port_encoding: Payload Channel Sample encoding schemes supported * @block_pack_mode: Type of block port mode supported * @read_only_wordlength: Read Only wordlength field in DPN_BlockCtrl1 register - * @port_encoding: Payload Channel Sample encoding schemes supported - * @audio_modes: Audio modes supported + * @simple_ch_prep_sm: If the port supports simplified channel prepare state + * machine */ struct sdw_dpn_prop { + struct sdw_dpn_audio_mode *audio_modes; u32 num; u32 max_word; u32 min_word; @@ -325,21 +326,20 @@ struct sdw_dpn_prop { u32 *words; enum sdw_dpn_type type; u32 max_grouping; - bool simple_ch_prep_sm; u32 ch_prep_timeout; u32 imp_def_interrupts; u32 max_ch; u32 min_ch; u32 num_channels; - u32 *channels; u32 num_ch_combinations; + u32 *channels; u32 *ch_combinations; u32 modes; u32 max_async_buffer; + u32 port_encoding; bool block_pack_mode; bool read_only_wordlength; - u32 port_encoding; - struct sdw_dpn_audio_mode *audio_modes; + bool simple_ch_prep_sm; }; /** From 9df503f5d0c1ad363ad81f524c2e4cef762c389e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:33 +0100 Subject: [PATCH 043/256] soundwire: optimize sdw_dp0_prop JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 557e28f8b53243097162cf4d3e59bcee9fb9713b Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:42 2024 +0800 soundwire: optimize sdw_dp0_prop Move pointers and booleans. Before: struct sdw_dp0_prop { u32 max_word; /* 0 4 */ u32 min_word; /* 4 4 */ u32 num_words; /* 8 4 */ /* XXX 4 bytes hole, try to pack */ u32 * words; /* 16 8 */ bool BRA_flow_controlled; /* 24 1 */ bool simple_ch_prep_sm; /* 25 1 */ /* XXX 2 bytes hole, try to pack */ u32 ch_prep_timeout; /* 28 4 */ bool imp_def_interrupts; /* 32 1 */ /* size: 40, cachelines: 1, members: 8 */ /* sum members: 27, holes: 2, sum holes: 6 */ /* padding: 7 */ /* last cacheline: 40 bytes */ }; after: struct sdw_dp0_prop { u32 * words; /* 0 8 */ u32 max_word; /* 8 4 */ u32 min_word; /* 12 4 */ u32 num_words; /* 16 4 */ u32 ch_prep_timeout; /* 20 4 */ bool BRA_flow_controlled; /* 24 1 */ bool simple_ch_prep_sm; /* 25 1 */ bool imp_def_interrupts; /* 26 1 */ /* size: 32, cachelines: 1, members: 8 */ /* padding: 5 */ /* last cacheline: 32 bytes */ }; Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-7-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- include/linux/soundwire/sdw.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 0afe07510daa..f9cfbdfde567 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -226,16 +226,16 @@ enum sdw_clk_stop_mode { /** * struct sdw_dp0_prop - DP0 properties + * @words: wordlengths supported * @max_word: Maximum number of bits in a Payload Channel Sample, 1 to 64 * (inclusive) * @min_word: Minimum number of bits in a Payload Channel Sample, 1 to 64 * (inclusive) * @num_words: number of wordlengths supported - * @words: wordlengths supported + * @ch_prep_timeout: Port-specific timeout value, in milliseconds * @BRA_flow_controlled: Slave implementation results in an OK_NotReady * response * @simple_ch_prep_sm: If channel prepare sequence is required - * @ch_prep_timeout: Port-specific timeout value, in milliseconds * @imp_def_interrupts: If set, each bit corresponds to support for * implementation-defined interrupts * @@ -244,13 +244,13 @@ enum sdw_clk_stop_mode { * support */ struct sdw_dp0_prop { + u32 *words; u32 max_word; u32 min_word; u32 num_words; - u32 *words; + u32 ch_prep_timeout; bool BRA_flow_controlled; bool simple_ch_prep_sm; - u32 ch_prep_timeout; bool imp_def_interrupts; }; From 0efede8c6324a9f916a9f75fb7dd17e178dbf841 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:34 +0100 Subject: [PATCH 044/256] soundwire: optimize sdw_slave_prop JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1c758df5a83ea0c9b5055536336d8a586b5010b0 Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:41 2024 +0800 soundwire: optimize sdw_slave_prop move pointers first, and move booleans together. before: struct sdw_slave_prop { u32 mipi_revision; /* 0 4 */ bool wake_capable; /* 4 1 */ bool test_mode_capable; /* 5 1 */ bool clk_stop_mode1; /* 6 1 */ bool simple_clk_stop_capable; /* 7 1 */ u32 clk_stop_timeout; /* 8 4 */ u32 ch_prep_timeout; /* 12 4 */ enum sdw_clk_stop_reset_behave reset_behave; /* 16 4 */ bool high_PHY_capable; /* 20 1 */ bool paging_support; /* 21 1 */ bool bank_delay_support; /* 22 1 */ /* XXX 1 byte hole, try to pack */ enum sdw_p15_behave p15_behave; /* 24 4 */ bool lane_control_support; /* 28 1 */ /* XXX 3 bytes hole, try to pack */ u32 master_count; /* 32 4 */ u32 source_ports; /* 36 4 */ u32 sink_ports; /* 40 4 */ /* XXX 4 bytes hole, try to pack */ struct sdw_dp0_prop * dp0_prop; /* 48 8 */ struct sdw_dpn_prop * src_dpn_prop; /* 56 8 */ /* --- cacheline 1 boundary (64 bytes) --- */ struct sdw_dpn_prop * sink_dpn_prop; /* 64 8 */ u8 scp_int1_mask; /* 72 1 */ /* XXX 3 bytes hole, try to pack */ u32 quirks; /* 76 4 */ bool clock_reg_supported; /* 80 1 */ bool use_domain_irq; /* 81 1 */ /* size: 88, cachelines: 2, members: 23 */ /* sum members: 71, holes: 4, sum holes: 11 */ /* padding: 6 */ /* last cacheline: 24 bytes */ }; after: truct sdw_slave_prop { struct sdw_dp0_prop * dp0_prop; /* 0 8 */ struct sdw_dpn_prop * src_dpn_prop; /* 8 8 */ struct sdw_dpn_prop * sink_dpn_prop; /* 16 8 */ u32 mipi_revision; /* 24 4 */ bool wake_capable; /* 28 1 */ bool test_mode_capable; /* 29 1 */ bool clk_stop_mode1; /* 30 1 */ bool simple_clk_stop_capable; /* 31 1 */ u32 clk_stop_timeout; /* 32 4 */ u32 ch_prep_timeout; /* 36 4 */ enum sdw_clk_stop_reset_behave reset_behave; /* 40 4 */ bool high_PHY_capable; /* 44 1 */ bool paging_support; /* 45 1 */ bool bank_delay_support; /* 46 1 */ bool lane_control_support; /* 47 1 */ enum sdw_p15_behave p15_behave; /* 48 4 */ u32 master_count; /* 52 4 */ u32 source_ports; /* 56 4 */ u32 sink_ports; /* 60 4 */ /* --- cacheline 1 boundary (64 bytes) --- */ u32 quirks; /* 64 4 */ u8 scp_int1_mask; /* 68 1 */ bool clock_reg_supported; /* 69 1 */ bool use_domain_irq; /* 70 1 */ /* size: 72, cachelines: 2, members: 23 */ /* padding: 1 */ /* last cacheline: 8 bytes */ }; Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-6-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- include/linux/soundwire/sdw.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index f9cfbdfde567..ff9a882aeae2 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -344,6 +344,9 @@ struct sdw_dpn_prop { /** * struct sdw_slave_prop - SoundWire Slave properties + * @dp0_prop: Data Port 0 properties + * @src_dpn_prop: Source Data Port N properties + * @sink_dpn_prop: Sink Data Port N properties * @mipi_revision: Spec version of the implementation * @wake_capable: Wake-up events are supported * @test_mode_capable: If test mode is supported @@ -360,15 +363,12 @@ struct sdw_dpn_prop { * SCP_AddrPage2 * @bank_delay_support: Slave implements bank delay/bridge support registers * SCP_BankDelay and SCP_NextFrame + * @lane_control_support: Slave supports lane control * @p15_behave: Slave behavior when the Master attempts a read to the Port15 * alias - * @lane_control_support: Slave supports lane control * @master_count: Number of Masters present on this Slave * @source_ports: Bitmap identifying source ports * @sink_ports: Bitmap identifying sink ports - * @dp0_prop: Data Port 0 properties - * @src_dpn_prop: Source Data Port N properties - * @sink_dpn_prop: Sink Data Port N properties * @scp_int1_mask: SCP_INT1_MASK desired settings * @quirks: bitmask identifying deltas from the MIPI specification * @clock_reg_supported: the Peripheral implements the clock base and scale @@ -377,6 +377,9 @@ struct sdw_dpn_prop { * @use_domain_irq: call actual IRQ handler on slave, as well as callback */ struct sdw_slave_prop { + struct sdw_dp0_prop *dp0_prop; + struct sdw_dpn_prop *src_dpn_prop; + struct sdw_dpn_prop *sink_dpn_prop; u32 mipi_revision; bool wake_capable; bool test_mode_capable; @@ -388,16 +391,13 @@ struct sdw_slave_prop { bool high_PHY_capable; bool paging_support; bool bank_delay_support; - enum sdw_p15_behave p15_behave; bool lane_control_support; + enum sdw_p15_behave p15_behave; u32 master_count; u32 source_ports; u32 sink_ports; - struct sdw_dp0_prop *dp0_prop; - struct sdw_dpn_prop *src_dpn_prop; - struct sdw_dpn_prop *sink_dpn_prop; - u8 scp_int1_mask; u32 quirks; + u8 scp_int1_mask; bool clock_reg_supported; bool use_domain_irq; }; From 0595306885e0b6f7b4bf42ce25f7aeea3010f15f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:35 +0100 Subject: [PATCH 045/256] soundwire: optimize sdw_bus structure JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0a323dad1c4e04048988cd04c60eaffd6ae61b1a Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:40 2024 +0800 soundwire: optimize sdw_bus structure The sdw_bus structure has seen multiple additions over the years. It's one of the most used structures in this subsystem, so there's merit in reshuffling the members a bit with 'pahole' to reduce holes and structures across cache lines. before: struct sdw_bus { struct device * dev; /* 0 8 */ struct sdw_master_device * md; /* 8 8 */ int controller_id; /* 16 4 */ unsigned int link_id; /* 20 4 */ int id; /* 24 4 */ /* XXX 4 bytes hole, try to pack */ struct list_head slaves; /* 32 16 */ long unsigned int assigned[1]; /* 48 8 */ struct mutex bus_lock; /* 56 160 */ /* --- cacheline 3 boundary (192 bytes) was 24 bytes ago --- */ struct lock_class_key bus_lock_key; /* 216 16 */ struct mutex msg_lock; /* 232 160 */ /* --- cacheline 6 boundary (384 bytes) was 8 bytes ago --- */ struct lock_class_key msg_lock_key; /* 392 16 */ int (*compute_params)(struct sdw_bus *); /* 408 8 */ const struct sdw_master_ops * ops; /* 416 8 */ const struct sdw_master_port_ops * port_ops; /* 424 8 */ struct sdw_bus_params params; /* 432 36 */ /* XXX 4 bytes hole, try to pack */ /* --- cacheline 7 boundary (448 bytes) was 24 bytes ago --- */ struct sdw_master_prop prop; /* 472 72 */ /* XXX last struct has 6 bytes of padding */ /* --- cacheline 8 boundary (512 bytes) was 32 bytes ago --- */ void * vendor_specific_prop; /* 544 8 */ struct list_head m_rt_list; /* 552 16 */ struct dentry * debugfs; /* 568 8 */ /* --- cacheline 9 boundary (576 bytes) --- */ struct irq_chip irq_chip; /* 576 264 */ /* --- cacheline 13 boundary (832 bytes) was 8 bytes ago --- */ struct irq_domain * domain; /* 840 8 */ struct sdw_defer defer_msg; /* 848 112 */ /* --- cacheline 15 boundary (960 bytes) --- */ unsigned int clk_stop_timeout; /* 960 4 */ u32 bank_switch_timeout; /* 964 4 */ bool multi_link; /* 968 1 */ /* XXX 3 bytes hole, try to pack */ int hw_sync_min_links; /* 972 4 */ int stream_refcount; /* 976 4 */ /* size: 984, cachelines: 16, members: 27 */ /* sum members: 969, holes: 3, sum holes: 11 */ /* padding: 4 */ /* paddings: 1, sum paddings: 6 */ /* last cacheline: 24 bytes */ }; after: struct sdw_bus { struct device * dev; /* 0 8 */ struct sdw_master_device * md; /* 8 8 */ struct lock_class_key bus_lock_key; /* 16 16 */ struct mutex bus_lock; /* 32 160 */ /* --- cacheline 3 boundary (192 bytes) --- */ struct list_head slaves; /* 192 16 */ struct lock_class_key msg_lock_key; /* 208 16 */ struct mutex msg_lock; /* 224 160 */ /* --- cacheline 6 boundary (384 bytes) --- */ struct list_head m_rt_list; /* 384 16 */ struct sdw_defer defer_msg; /* 400 112 */ /* --- cacheline 8 boundary (512 bytes) --- */ struct sdw_bus_params params; /* 512 36 */ int stream_refcount; /* 548 4 */ const struct sdw_master_ops * ops; /* 552 8 */ const struct sdw_master_port_ops * port_ops; /* 560 8 */ struct sdw_master_prop prop; /* 568 72 */ /* XXX last struct has 6 bytes of padding */ /* --- cacheline 10 boundary (640 bytes) --- */ void * vendor_specific_prop; /* 640 8 */ int hw_sync_min_links; /* 648 4 */ int controller_id; /* 652 4 */ unsigned int link_id; /* 656 4 */ int id; /* 660 4 */ int (*compute_params)(struct sdw_bus *); /* 664 8 */ long unsigned int assigned[1]; /* 672 8 */ unsigned int clk_stop_timeout; /* 680 4 */ u32 bank_switch_timeout; /* 684 4 */ struct irq_chip irq_chip; /* 688 264 */ /* --- cacheline 14 boundary (896 bytes) was 56 bytes ago --- */ struct irq_domain * domain; /* 952 8 */ /* --- cacheline 15 boundary (960 bytes) --- */ struct dentry * debugfs; /* 960 8 */ bool multi_link; /* 968 1 */ /* size: 976, cachelines: 16, members: 27 */ /* padding: 7 */ /* paddings: 1, sum paddings: 6 */ /* last cacheline: 16 bytes */ }; Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-5-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- include/linux/soundwire/sdw.h | 81 ++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index ff9a882aeae2..db9d08c93c98 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -871,68 +871,71 @@ struct sdw_master_ops { * struct sdw_bus - SoundWire bus * @dev: Shortcut to &bus->md->dev to avoid changing the entire code. * @md: Master device - * @controller_id: system-unique controller ID. If set to -1, the bus @id will be used. - * @link_id: Link id number, can be 0 to N, unique for each Controller - * @id: bus system-wide unique id - * @slaves: list of Slaves on this bus - * @assigned: Bitmap for Slave device numbers. - * Bit set implies used number, bit clear implies unused number. + * @bus_lock_key: bus lock key associated to @bus_lock * @bus_lock: bus lock + * @slaves: list of Slaves on this bus + * @msg_lock_key: message lock key associated to @msg_lock * @msg_lock: message lock - * @compute_params: points to Bus resource management implementation - * @ops: Master callback ops - * @port_ops: Master port callback ops - * @params: Current bus parameters - * @prop: Master properties - * @vendor_specific_prop: pointer to non-standard properties * @m_rt_list: List of Master instance of all stream(s) running on Bus. This * is used to compute and program bus bandwidth, clock, frame shape, * transport and port parameters - * @debugfs: Bus debugfs - * @domain: IRQ domain * @defer_msg: Defer message - * @clk_stop_timeout: Clock stop timeout computed - * @bank_switch_timeout: Bank switch timeout computed - * @multi_link: Store bus property that indicates if multi links - * are supported. This flag is populated by drivers after reading - * appropriate firmware (ACPI/DT). + * @params: Current bus parameters + * @stream_refcount: number of streams currently using this bus + * @ops: Master callback ops + * @port_ops: Master port callback ops + * @prop: Master properties + * @vendor_specific_prop: pointer to non-standard properties * @hw_sync_min_links: Number of links used by a stream above which * hardware-based synchronization is required. This value is only * meaningful if multi_link is set. If set to 1, hardware-based * synchronization will be used even if a stream only uses a single * SoundWire segment. - * @stream_refcount: number of streams currently using this bus + * @controller_id: system-unique controller ID. If set to -1, the bus @id will be used. + * @link_id: Link id number, can be 0 to N, unique for each Controller + * @id: bus system-wide unique id + * @compute_params: points to Bus resource management implementation + * @assigned: Bitmap for Slave device numbers. + * Bit set implies used number, bit clear implies unused number. + * @clk_stop_timeout: Clock stop timeout computed + * @bank_switch_timeout: Bank switch timeout computed + * @domain: IRQ domain + * @irq_chip: IRQ chip + * @debugfs: Bus debugfs (optional) + * @multi_link: Store bus property that indicates if multi links + * are supported. This flag is populated by drivers after reading + * appropriate firmware (ACPI/DT). */ struct sdw_bus { struct device *dev; struct sdw_master_device *md; + struct lock_class_key bus_lock_key; + struct mutex bus_lock; + struct list_head slaves; + struct lock_class_key msg_lock_key; + struct mutex msg_lock; + struct list_head m_rt_list; + struct sdw_defer defer_msg; + struct sdw_bus_params params; + int stream_refcount; + const struct sdw_master_ops *ops; + const struct sdw_master_port_ops *port_ops; + struct sdw_master_prop prop; + void *vendor_specific_prop; + int hw_sync_min_links; int controller_id; unsigned int link_id; int id; - struct list_head slaves; - DECLARE_BITMAP(assigned, SDW_MAX_DEVICES); - struct mutex bus_lock; - struct lock_class_key bus_lock_key; - struct mutex msg_lock; - struct lock_class_key msg_lock_key; int (*compute_params)(struct sdw_bus *bus); - const struct sdw_master_ops *ops; - const struct sdw_master_port_ops *port_ops; - struct sdw_bus_params params; - struct sdw_master_prop prop; - void *vendor_specific_prop; - struct list_head m_rt_list; + DECLARE_BITMAP(assigned, SDW_MAX_DEVICES); + unsigned int clk_stop_timeout; + u32 bank_switch_timeout; + struct irq_chip irq_chip; + struct irq_domain *domain; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs; #endif - struct irq_chip irq_chip; - struct irq_domain *domain; - struct sdw_defer defer_msg; - unsigned int clk_stop_timeout; - u32 bank_switch_timeout; bool multi_link; - int hw_sync_min_links; - int stream_refcount; }; int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, From 338d8119234b2a812a712c37c71117aad193b6af Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:35 +0100 Subject: [PATCH 046/256] soundwire: optimize sdw_master_prop JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 6cb2c156439430a7f9db2e1f71a7dccf1ca978bf Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:39 2024 +0800 soundwire: optimize sdw_master_prop Make pahole happy by moving pointers and u64 first instead of interleaving them. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-4-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- include/linux/soundwire/sdw.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index db9d08c93c98..c2dbd99d6aef 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -406,13 +406,14 @@ struct sdw_slave_prop { /** * struct sdw_master_prop - Master properties + * @clk_gears: Clock gears supported + * @clk_freq: Clock frequencies supported, in Hz + * @quirks: bitmask identifying optional behavior beyond the scope of the MIPI specification * @revision: MIPI spec version of the implementation * @clk_stop_modes: Bitmap, bit N set when clock-stop-modeN supported * @max_clk_freq: Maximum Bus clock frequency, in Hz * @num_clk_gears: Number of clock gears supported - * @clk_gears: Clock gears supported * @num_clk_freq: Number of clock frequencies supported, in Hz - * @clk_freq: Clock frequencies supported, in Hz * @default_frame_rate: Controller default Frame rate, in Hz * @default_row: Number of rows * @default_col: Number of columns @@ -421,24 +422,23 @@ struct sdw_slave_prop { * command * @mclk_freq: clock reference passed to SoundWire Master, in Hz. * @hw_disabled: if true, the Master is not functional, typically due to pin-mux - * @quirks: bitmask identifying optional behavior beyond the scope of the MIPI specification */ struct sdw_master_prop { + u32 *clk_gears; + u32 *clk_freq; + u64 quirks; u32 revision; u32 clk_stop_modes; u32 max_clk_freq; u32 num_clk_gears; - u32 *clk_gears; u32 num_clk_freq; - u32 *clk_freq; u32 default_frame_rate; u32 default_row; u32 default_col; - bool dynamic_frame; u32 err_threshold; u32 mclk_freq; + bool dynamic_frame; bool hw_disabled; - u64 quirks; }; /* Definitions for Master quirks */ From ba0e1a0ee60c97f350c4cfc85ce1cba6ea024028 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:36 +0100 Subject: [PATCH 047/256] soundwire: optimize sdw_stream_runtime memory layout JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 444d6824a4feca142b0a57095a2f1f1bda98e2ab Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:38 2024 +0800 soundwire: optimize sdw_stream_runtime memory layout pahole suggestion: swap position of 'm_rt_count' before: pahole -C sdw_stream_runtime drivers/soundwire/soundwire-bus.ko struct sdw_stream_runtime { const char * name; /* 0 8 */ struct sdw_stream_params params; /* 8 12 */ enum sdw_stream_state state; /* 20 4 */ enum sdw_stream_type type; /* 24 4 */ /* XXX 4 bytes hole, try to pack */ struct list_head master_list; /* 32 16 */ int m_rt_count; /* 48 4 */ /* size: 56, cachelines: 1, members: 6 */ /* sum members: 48, holes: 1, sum holes: 4 */ /* padding: 4 */ /* last cacheline: 56 bytes */ }; after: pahole --reorganize -C sdw_stream_runtime drivers/soundwire/soundwire-bus.ko struct sdw_stream_runtime { const char * name; /* 0 8 */ struct sdw_stream_params params; /* 8 12 */ enum sdw_stream_state state; /* 20 4 */ enum sdw_stream_type type; /* 24 4 */ int m_rt_count; /* 28 4 */ struct list_head master_list; /* 32 16 */ /* size: 48, cachelines: 1, members: 6 */ /* last cacheline: 48 bytes */ }; /* saved 8 bytes! */ Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-3-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- include/linux/soundwire/sdw.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index c2dbd99d6aef..cc0afb8af333 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -820,15 +820,15 @@ struct sdw_master_port_ops { struct sdw_msg; /** - * struct sdw_defer - SDW deffered message - * @length: message length + * struct sdw_defer - SDW deferred message * @complete: message completion * @msg: SDW message + * @length: message length */ struct sdw_defer { + struct sdw_msg *msg; int length; struct completion complete; - struct sdw_msg *msg; }; /** @@ -1013,18 +1013,18 @@ struct sdw_stream_params { * @params: Stream parameters * @state: Current state of the stream * @type: Stream type PCM or PDM + * @m_rt_count: Count of Master runtime(s) in this stream * @master_list: List of Master runtime(s) in this stream. * master_list can contain only one m_rt per Master instance * for a stream - * @m_rt_count: Count of Master runtime(s) in this stream */ struct sdw_stream_runtime { const char *name; struct sdw_stream_params params; enum sdw_stream_state state; enum sdw_stream_type type; - struct list_head master_list; int m_rt_count; + struct list_head master_list; }; struct sdw_stream_runtime *sdw_alloc_stream(const char *stream_name); From 9f898c963bd1cbf2a59b9341f88b317c47d87989 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:36 +0100 Subject: [PATCH 048/256] soundwire: mipi_disco: add MIPI-specific property_read_bool() helpers JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 093227bc53a023991ba04315f42839a22b613113 Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:37 2024 +0800 soundwire: mipi_disco: add MIPI-specific property_read_bool() helpers The existing device/fwnode_property_read_bool() helpers only check if the property is present. The MIPI DisCo for SoundWire specification allows properties to be exposed with a value of 'false'. Using the standard helpers to retrieve the MIPI-defined properties causes all kinds of logical inversions leading to loss of functionality - such as jack detection in clock-stop mode broken when the device properties are read in Realtek codec drivers. This patch adds new MIPI/SoundWire helpers which first check if the property is present, and then return the actual value extracted from platform firmware. Modifying the default property handling was considered as a possible solution, but it could lead to other types of logical inversions breaking 'working' setups. Andy Shevchenko also pointed out that DT keeps values in the BE32 format, it's probably best to avoid endianness complications. The path of least resistance was chosen, with MIPI-specific helpers which can be tested and with no side effects outside of the SoundWire subsystem. Closes: https://github.com/thesofproject/linux/issues/5129 Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-2-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/mipi_disco.c | 50 ++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index e5d9df26d4dc..fdab3d4a1379 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -23,6 +23,26 @@ #include #include "bus.h" +static bool mipi_fwnode_property_read_bool(const struct fwnode_handle *fwnode, + const char *propname) +{ + int ret; + u8 val; + + if (!fwnode_property_present(fwnode, propname)) + return false; + ret = fwnode_property_read_u8_array(fwnode, propname, &val, 1); + if (ret < 0) + return false; + return !!val; +} + +static bool mipi_device_property_read_bool(const struct device *dev, + const char *propname) +{ + return mipi_fwnode_property_read_bool(dev_fwnode(dev), propname); +} + /** * sdw_master_read_prop() - Read Master properties * @bus: SDW bus instance @@ -48,11 +68,11 @@ int sdw_master_read_prop(struct sdw_bus *bus) return -EIO; } - if (fwnode_property_read_bool(link, + if (mipi_fwnode_property_read_bool(link, "mipi-sdw-clock-stop-mode0-supported")) prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0); - if (fwnode_property_read_bool(link, + if (mipi_fwnode_property_read_bool(link, "mipi-sdw-clock-stop-mode1-supported")) prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1); @@ -114,7 +134,7 @@ int sdw_master_read_prop(struct sdw_bus *bus) fwnode_property_read_u32(link, "mipi-sdw-default-frame-col-size", &prop->default_col); - prop->dynamic_frame = fwnode_property_read_bool(link, + prop->dynamic_frame = mipi_fwnode_property_read_bool(link, "mipi-sdw-dynamic-frame-shape"); fwnode_property_read_u32(link, "mipi-sdw-command-error-threshold", @@ -153,13 +173,13 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave, dp0->words, dp0->num_words); } - dp0->BRA_flow_controlled = fwnode_property_read_bool(port, + dp0->BRA_flow_controlled = mipi_fwnode_property_read_bool(port, "mipi-sdw-bra-flow-controlled"); - dp0->simple_ch_prep_sm = fwnode_property_read_bool(port, + dp0->simple_ch_prep_sm = mipi_fwnode_property_read_bool(port, "mipi-sdw-simplified-channel-prepare-sm"); - dp0->imp_def_interrupts = fwnode_property_read_bool(port, + dp0->imp_def_interrupts = mipi_fwnode_property_read_bool(port, "mipi-sdw-imp-def-dp0-interrupts-supported"); return 0; @@ -220,7 +240,7 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, "mipi-sdw-max-grouping-supported", &dpn[i].max_grouping); - dpn[i].simple_ch_prep_sm = fwnode_property_read_bool(node, + dpn[i].simple_ch_prep_sm = mipi_fwnode_property_read_bool(node, "mipi-sdw-simplified-channelprepare-sm"); fwnode_property_read_u32(node, @@ -278,7 +298,7 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, fwnode_property_read_u32(node, "mipi-sdw-max-async-buffer", &dpn[i].max_async_buffer); - dpn[i].block_pack_mode = fwnode_property_read_bool(node, + dpn[i].block_pack_mode = mipi_fwnode_property_read_bool(node, "mipi-sdw-block-packing-mode"); fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type", @@ -308,19 +328,19 @@ int sdw_slave_read_prop(struct sdw_slave *slave) device_property_read_u32(dev, "mipi-sdw-sw-interface-revision", &prop->mipi_revision); - prop->wake_capable = device_property_read_bool(dev, + prop->wake_capable = mipi_device_property_read_bool(dev, "mipi-sdw-wake-up-unavailable"); prop->wake_capable = !prop->wake_capable; - prop->test_mode_capable = device_property_read_bool(dev, + prop->test_mode_capable = mipi_device_property_read_bool(dev, "mipi-sdw-test-mode-supported"); prop->clk_stop_mode1 = false; - if (device_property_read_bool(dev, + if (mipi_device_property_read_bool(dev, "mipi-sdw-clock-stop-mode1-supported")) prop->clk_stop_mode1 = true; - prop->simple_clk_stop_capable = device_property_read_bool(dev, + prop->simple_clk_stop_capable = mipi_device_property_read_bool(dev, "mipi-sdw-simplified-clockstopprepare-sm-supported"); device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout", @@ -333,13 +353,13 @@ int sdw_slave_read_prop(struct sdw_slave *slave) "mipi-sdw-clockstopprepare-hard-reset-behavior", &prop->reset_behave); - prop->high_PHY_capable = device_property_read_bool(dev, + prop->high_PHY_capable = mipi_device_property_read_bool(dev, "mipi-sdw-highPHY-capable"); - prop->paging_support = device_property_read_bool(dev, + prop->paging_support = mipi_device_property_read_bool(dev, "mipi-sdw-paging-support"); - prop->bank_delay_support = device_property_read_bool(dev, + prop->bank_delay_support = mipi_device_property_read_bool(dev, "mipi-sdw-bank-delay-support"); device_property_read_u32(dev, From 823924e3ade12bc2fb8e37bc510d3a07532bf2dc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:36 +0100 Subject: [PATCH 049/256] soundwire: mipi-disco: remove DPn audio-modes JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1ae4aa59d79399be0591c8d78c44e280406e2c34 Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:44 2024 +0800 soundwire: mipi-disco: remove DPn audio-modes The concept of DPn audio-modes was never used by anyone, and was removed from the DisCo for SoundWire 2.0 specification. Remove the definitions and TODO. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-9-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/mipi_disco.c | 2 -- include/linux/soundwire/sdw.h | 34 ---------------------------------- 2 files changed, 36 deletions(-) diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index fdab3d4a1379..79cf8212f97a 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -304,8 +304,6 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type", &dpn[i].port_encoding); - /* TODO: Read audio mode */ - fwnode_handle_put(node); i++; diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index cc0afb8af333..66feaa79ecfc 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -254,41 +254,8 @@ struct sdw_dp0_prop { bool imp_def_interrupts; }; -/** - * struct sdw_dpn_audio_mode - Audio mode properties for DPn - * @bus_min_freq: Minimum bus frequency, in Hz - * @bus_max_freq: Maximum bus frequency, in Hz - * @bus_num_freq: Number of discrete frequencies supported - * @bus_freq: Discrete bus frequencies, in Hz - * @min_freq: Minimum sampling frequency, in Hz - * @max_freq: Maximum sampling bus frequency, in Hz - * @num_freq: Number of discrete sampling frequency supported - * @freq: Discrete sampling frequencies, in Hz - * @prep_ch_behave: Specifies the dependencies between Channel Prepare - * sequence and bus clock configuration - * If 0, Channel Prepare can happen at any Bus clock rate - * If 1, Channel Prepare sequence shall happen only after Bus clock is - * changed to a frequency supported by this mode or compatible modes - * described by the next field - * @glitchless: Bitmap describing possible glitchless transitions from this - * Audio Mode to other Audio Modes - */ -struct sdw_dpn_audio_mode { - u32 bus_min_freq; - u32 bus_max_freq; - u32 bus_num_freq; - u32 *bus_freq; - u32 max_freq; - u32 min_freq; - u32 num_freq; - u32 *freq; - u32 prep_ch_behave; - u32 glitchless; -}; - /** * struct sdw_dpn_prop - Data Port DPn properties - * @audio_modes: Audio modes supported * @num: port number * @max_word: Maximum number of bits in a Payload Channel Sample, 1 to 64 * (inclusive) @@ -318,7 +285,6 @@ struct sdw_dpn_audio_mode { * machine */ struct sdw_dpn_prop { - struct sdw_dpn_audio_mode *audio_modes; u32 num; u32 max_word; u32 min_word; From a69b4630e4446c2543c5a6183b5613a35d0b8f1f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:36 +0100 Subject: [PATCH 050/256] soundwire: mipi-disco: add comment on DP0-supported property JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1ab88b57bbc2196545a510679e01b1f26158c39b Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:48 2024 +0800 soundwire: mipi-disco: add comment on DP0-supported property The DisCo for SoundWire 2.0 spec adds support for a new property, but it's not very helpful. Add a comment to explain that it's intentionally ignored. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-13-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/mipi_disco.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index 79cf8212f97a..6b1cb083b323 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -372,7 +372,11 @@ int sdw_slave_read_prop(struct sdw_slave *slave) device_property_read_u32(dev, "mipi-sdw-sink-port-list", &prop->sink_ports); - /* Read dp0 properties */ + /* + * Read dp0 properties - we don't rely on the 'mipi-sdw-dp-0-supported' + * property since the 'mipi-sdw-dp0-subproperties' property is logically + * equivalent. + */ port = device_get_named_child_node(dev, "mipi-sdw-dp-0-subproperties"); if (!port) { dev_dbg(dev, "DP0 node not found!!\n"); From 645e4dce1b37a1770ea9252ac241b2ea67d80222 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:36 +0100 Subject: [PATCH 051/256] soundwire: mipi-disco: add new properties from 2.0 spec JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 543bd28a3bfeff31f748ba83348b63313dd37ff9 Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:49 2024 +0800 soundwire: mipi-disco: add new properties from 2.0 spec The DisCo for SoundWire 2.0 spec adds support for new 'mipi-sdw-sdca-interrupt-register-list' and 'mipi-sdw-commit-register-supported'. This patch only adds the definitions and property reads, but the use of these properties will come at some point in the future when needed. Note a slight conceptual disconnect between the MIPI DisCo definition of a boolean property and the Linux implementation. The latter only checks the presence of the property to set its value to 'true', whereas the MIPI definitions allow for a property with a 'false' value. This patch uses the new introduced mipi_device_property_read_bool() to handle it. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-14-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/mipi_disco.c | 6 ++++++ include/linux/soundwire/sdw.h | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index 6b1cb083b323..28b1de9c9de0 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -372,6 +372,12 @@ int sdw_slave_read_prop(struct sdw_slave *slave) device_property_read_u32(dev, "mipi-sdw-sink-port-list", &prop->sink_ports); + device_property_read_u32(dev, "mipi-sdw-sdca-interrupt-register-list", + &prop->sdca_interrupt_register_list); + + prop->commit_register_supported = mipi_device_property_read_bool(dev, + "mipi-sdw-commit-register-supported"); + /* * Read dp0 properties - we don't rely on the 'mipi-sdw-dp-0-supported' * property since the 'mipi-sdw-dp0-subproperties' property is logically diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 66feaa79ecfc..952514f044f0 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -335,8 +335,11 @@ struct sdw_dpn_prop { * @master_count: Number of Masters present on this Slave * @source_ports: Bitmap identifying source ports * @sink_ports: Bitmap identifying sink ports - * @scp_int1_mask: SCP_INT1_MASK desired settings * @quirks: bitmask identifying deltas from the MIPI specification + * @sdca_interrupt_register_list: indicates which sets of SDCA interrupt status + * and masks are supported + * @commit_register_supported: is PCP_Commit register supported + * @scp_int1_mask: SCP_INT1_MASK desired settings * @clock_reg_supported: the Peripheral implements the clock base and scale * registers introduced with the SoundWire 1.2 specification. SDCA devices * do not need to set this boolean property as the registers are required. @@ -363,6 +366,8 @@ struct sdw_slave_prop { u32 source_ports; u32 sink_ports; u32 quirks; + u32 sdca_interrupt_register_list; + u8 commit_register_supported; u8 scp_int1_mask; bool clock_reg_supported; bool use_domain_irq; From cb714cba6d948c9a39c42141e0603d0abdb395b2 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:36 +0100 Subject: [PATCH 052/256] soundwire: mipi-disco: add support for peripheral channelprepare timeout JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 4b230967c5506b1e55d4fd37722d87fb7aaa1ce7 Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:47 2024 +0800 soundwire: mipi-disco: add support for peripheral channelprepare timeout The DisCo for SoundWire 2.0 spec renamed the 'mipi-sdw-slave-channelprepare-timeout', add support for the new definition in backwards-compatible ways. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-12-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/mipi_disco.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index 28b1de9c9de0..3179bebc2c26 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -322,6 +322,7 @@ int sdw_slave_read_prop(struct sdw_slave *slave) struct device *dev = &slave->dev; struct fwnode_handle *port; int nval; + int ret; device_property_read_u32(dev, "mipi-sdw-sw-interface-revision", &prop->mipi_revision); @@ -344,8 +345,11 @@ int sdw_slave_read_prop(struct sdw_slave *slave) device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout", &prop->clk_stop_timeout); - device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout", - &prop->ch_prep_timeout); + ret = device_property_read_u32(dev, "mipi-sdw-peripheral-channelprepare-timeout", + &prop->ch_prep_timeout); + if (ret < 0) + device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout", + &prop->ch_prep_timeout); device_property_read_u32(dev, "mipi-sdw-clockstopprepare-hard-reset-behavior", From 9d3c15c6fea309759f69a70a30f6fbcf69f26589 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:37 +0100 Subject: [PATCH 053/256] soundwire: mipi-disco: add error handling for property array read JIRA: https://issues.redhat.com/browse/RHEL-80681 commit a489afc105ed55f7537fb158e40d083ee57a698b Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:45 2024 +0800 soundwire: mipi-disco: add error handling for property array read The existing code assumes that there are no possible errors when using fwnode_property_read_u32_array(), because fwnode_property_count_u32() reads this array to determine its number of elements. We need to also protect the second read to be completely bullet-proof. Suggested-by: Andy Shevchenko Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-10-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/mipi_disco.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index 3179bebc2c26..e0606f449acb 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -52,7 +52,9 @@ int sdw_master_read_prop(struct sdw_bus *bus) struct sdw_master_prop *prop = &bus->prop; struct fwnode_handle *link; char name[32]; - int nval, i; + int nval; + int ret; + int i; device_property_read_u32(bus->dev, "mipi-sdw-sw-interface-revision", @@ -91,9 +93,11 @@ int sdw_master_read_prop(struct sdw_bus *bus) return -ENOMEM; } - fwnode_property_read_u32_array(link, + ret = fwnode_property_read_u32_array(link, "mipi-sdw-clock-frequencies-supported", prop->clk_freq, prop->num_clk_freq); + if (ret < 0) + return ret; } /* @@ -119,10 +123,12 @@ int sdw_master_read_prop(struct sdw_bus *bus) return -ENOMEM; } - fwnode_property_read_u32_array(link, + ret = fwnode_property_read_u32_array(link, "mipi-sdw-supported-clock-gears", prop->clk_gears, prop->num_clk_gears); + if (ret < 0) + return ret; } fwnode_property_read_u32(link, "mipi-sdw-default-frame-rate", @@ -151,6 +157,7 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave, struct sdw_dp0_prop *dp0) { int nval; + int ret; fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength", &dp0->max_word); @@ -168,9 +175,11 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave, if (!dp0->words) return -ENOMEM; - fwnode_property_read_u32_array(port, + ret = fwnode_property_read_u32_array(port, "mipi-sdw-port-wordlength-configs", dp0->words, dp0->num_words); + if (ret < 0) + return ret; } dp0->BRA_flow_controlled = mipi_fwnode_property_read_bool(port, @@ -191,9 +200,10 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, { struct fwnode_handle *node; u32 bit, i = 0; - int nval; unsigned long addr; char name[40]; + int nval; + int ret; addr = ports; /* valid ports are 1 to 14 so apply mask */ @@ -228,9 +238,11 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, return -ENOMEM; } - fwnode_property_read_u32_array(node, + ret = fwnode_property_read_u32_array(node, "mipi-sdw-port-wordlength-configs", dpn[i].words, dpn[i].num_words); + if (ret < 0) + return ret; } fwnode_property_read_u32(node, "mipi-sdw-data-port-type", @@ -269,9 +281,11 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, return -ENOMEM; } - fwnode_property_read_u32_array(node, + ret = fwnode_property_read_u32_array(node, "mipi-sdw-channel-number-list", dpn[i].channels, dpn[i].num_channels); + if (ret < 0) + return ret; } nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list"); @@ -286,10 +300,12 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, return -ENOMEM; } - fwnode_property_read_u32_array(node, + ret = fwnode_property_read_u32_array(node, "mipi-sdw-channel-combination-list", dpn[i].ch_combinations, dpn[i].num_ch_combinations); + if (ret < 0) + return ret; } fwnode_property_read_u32(node, From 40cd8c04c35583a48c7afbe39eec6af000807322 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:37 +0100 Subject: [PATCH 054/256] soundwire: mipi_disco: add support for clock-scales property JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 89e95be18de16ed4942bb77b639118abcd085ce4 Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:46 2024 +0800 soundwire: mipi_disco: add support for clock-scales property The DisCo for SoundWire 2.0 spec adds support for the 'mipi-sdw-supported-clock-scales' property, which is just a rename. Add in a backwards-compatible manner. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-11-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/mipi_disco.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index e0606f449acb..36e734751225 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -51,6 +51,7 @@ int sdw_master_read_prop(struct sdw_bus *bus) { struct sdw_master_prop *prop = &bus->prop; struct fwnode_handle *link; + const char *scales_prop; char name[32]; int nval; int ret; @@ -112,7 +113,12 @@ int sdw_master_read_prop(struct sdw_bus *bus) } } - nval = fwnode_property_count_u32(link, "mipi-sdw-supported-clock-gears"); + scales_prop = "mipi-sdw-supported-clock-scales"; + nval = fwnode_property_count_u32(link, scales_prop); + if (nval == 0) { + scales_prop = "mipi-sdw-supported-clock-gears"; + nval = fwnode_property_count_u32(link, scales_prop); + } if (nval > 0) { prop->num_clk_gears = nval; prop->clk_gears = devm_kcalloc(bus->dev, prop->num_clk_gears, @@ -124,7 +130,7 @@ int sdw_master_read_prop(struct sdw_bus *bus) } ret = fwnode_property_read_u32_array(link, - "mipi-sdw-supported-clock-gears", + scales_prop, prop->clk_gears, prop->num_clk_gears); if (ret < 0) From 29de04a3563df828211e78125ace765592643179 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:37 +0100 Subject: [PATCH 055/256] soundwire: mipi-disco: add support for DP0/DPn 'lane-list' property JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 71b405b184449fffcb76ea0814104b71dfdb2aee Author: Pierre-Louis Bossart Date: Thu Oct 3 15:06:50 2024 +0800 soundwire: mipi-disco: add support for DP0/DPn 'lane-list' property The SoundWire specification did not clearly require that ports could use all Lanes. Some SoundWire/SDCA peripheral adopters added restrictions on which lanes can be used by what port, and the DisCo for SoundWire 2.1 specification added a 'lane-list' property to model this hardware limitation. When not specified, the ports can use all Lanes. Otherwise, the 'lane-list' indicates which Lanes can be used, sorted by order of preference (most-preferred-first). This patch only reads the properties, the use of this property will come at a later time with multi-lane support. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003070650.62787-15-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/mipi_disco.c | 32 ++++++++++++++++++++++++++++++++ include/linux/soundwire/sdw.h | 8 ++++++++ 2 files changed, 40 insertions(+) diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index 36e734751225..9d59f486edbe 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -197,6 +197,22 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave, dp0->imp_def_interrupts = mipi_fwnode_property_read_bool(port, "mipi-sdw-imp-def-dp0-interrupts-supported"); + nval = fwnode_property_count_u32(port, "mipi-sdw-lane-list"); + if (nval > 0) { + dp0->num_lanes = nval; + dp0->lane_list = devm_kcalloc(&slave->dev, + dp0->num_lanes, sizeof(*dp0->lane_list), + GFP_KERNEL); + if (!dp0->lane_list) + return -ENOMEM; + + ret = fwnode_property_read_u32_array(port, + "mipi-sdw-lane-list", + dp0->lane_list, dp0->num_lanes); + if (ret < 0) + return ret; + } + return 0; } @@ -326,6 +342,22 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type", &dpn[i].port_encoding); + nval = fwnode_property_count_u32(node, "mipi-sdw-lane-list"); + if (nval > 0) { + dpn[i].num_lanes = nval; + dpn[i].lane_list = devm_kcalloc(&slave->dev, + dpn[i].num_lanes, sizeof(*dpn[i].lane_list), + GFP_KERNEL); + if (!dpn[i].lane_list) + return -ENOMEM; + + ret = fwnode_property_read_u32_array(node, + "mipi-sdw-lane-list", + dpn[i].lane_list, dpn[i].num_lanes); + if (ret < 0) + return ret; + } + fwnode_handle_put(node); i++; diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 952514f044f0..73f655334fe9 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -238,6 +238,8 @@ enum sdw_clk_stop_mode { * @simple_ch_prep_sm: If channel prepare sequence is required * @imp_def_interrupts: If set, each bit corresponds to support for * implementation-defined interrupts + * @num_lanes: array size of @lane_list + * @lane_list: indicates which Lanes can be used by DP0 * * The wordlengths are specified by Spec as max, min AND number of * discrete values, implementation can define based on the wordlengths they @@ -252,6 +254,8 @@ struct sdw_dp0_prop { bool BRA_flow_controlled; bool simple_ch_prep_sm; bool imp_def_interrupts; + int num_lanes; + u32 *lane_list; }; /** @@ -275,6 +279,8 @@ struct sdw_dp0_prop { * @num_ch_combinations: Number of channel combinations supported * @channels: Discrete channels supported * @ch_combinations: Channel combinations supported + * @lane_list: indicates which Lanes can be used by DPn + * @num_lanes: array size of @lane_list * @modes: SDW mode supported * @max_async_buffer: Number of samples that this port can buffer in * asynchronous modes @@ -300,6 +306,8 @@ struct sdw_dpn_prop { u32 num_ch_combinations; u32 *channels; u32 *ch_combinations; + u32 *lane_list; + int num_lanes; u32 modes; u32 max_async_buffer; u32 port_encoding; From 3366bfdc7ccecdbb05e824e075255432acfadd86 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:37 +0100 Subject: [PATCH 056/256] ASoC: sh: rz-ssi: Use SSIFCR_FIFO_RST macro JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 64207f8024899938f8e13c4649a060a19f18bff3 Author: Biju Das Date: Thu Oct 3 09:11:38 2024 +0100 ASoC: sh: rz-ssi: Use SSIFCR_FIFO_RST macro Use SSIFCR_FIFO_RST macro to make the line shorter. Suggested-by: Nobuhiro Iwamatsu Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20241003081140.31332-1-biju.das.jz@bp.renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sh/rz-ssi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index 6d25c2902d3d..b517b2d6ab43 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -311,8 +311,7 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate, ssicr |= SSICR_CKDV(clk_ckdv); ssicr |= SSICR_DWL(1) | SSICR_SWL(3); rz_ssi_reg_writel(ssi, SSICR, ssicr); - rz_ssi_reg_writel(ssi, SSIFCR, - (SSIFCR_AUCKE | SSIFCR_TFRST | SSIFCR_RFRST)); + rz_ssi_reg_writel(ssi, SSIFCR, SSIFCR_AUCKE | SSIFCR_FIFO_RST); return 0; } @@ -343,8 +342,7 @@ static void rz_ssi_set_idle(struct rz_ssi_priv *ssi) dev_info(ssi->dev, "timeout waiting for SSI idle\n"); /* Hold FIFOs in reset */ - rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, - SSIFCR_TFRST | SSIFCR_RFRST); + rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_FIFO_RST); } static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) From e3d3d79a0d3c62dbd8c6b240501aa621f025900a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:38 +0100 Subject: [PATCH 057/256] ASoC: Intel: sof_rt5682: Add support for ptl_max98360a_rt5682 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 56d3705e4b36bf454965e66d8264356a23135aa7 Author: Dharageswari R Date: Fri Oct 4 11:01:34 2024 +0800 ASoC: Intel: sof_rt5682: Add support for ptl_max98360a_rt5682 This patch adds the driver data for rt5682 codec on SSP0 and max98360a speaker amplifiers on SSP1 for PTL platform. Signed-off-by: Dharageswari R Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241004030135.67968-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/intel/boards/sof_rt5682.c | 8 ++++++++ sound/soc/intel/common/soc-acpi-intel-ptl-match.c | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 866589fece7a..5ceb376d4924 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -884,6 +884,14 @@ static const struct platform_device_id board_ids[] = { /* SSP 0 and SSP 2 are used for HDMI IN */ SOF_SSP_MASK_HDMI_CAPTURE(0x5)), }, + { + .name = "ptl_rt5682_def", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), + }, { } }; MODULE_DEVICE_TABLE(platform, board_ids); diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c index c0fe13c30364..7107f0151030 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -9,8 +9,21 @@ #include #include #include "soc-acpi-intel-sdw-mockup-match.h" +#include + +static const struct snd_soc_acpi_codecs ptl_rt5682_rt5682s_hp = { + .num_codecs = 2, + .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID}, +}; struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_machines[] = { + { + .comp_ids = &ptl_rt5682_rt5682s_hp, + .drv_name = "ptl_rt5682_def", + .sof_tplg_filename = "sof-ptl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ptl_machines); From fd1029780902a56cc099a8839849bcb5666170cc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:38 +0100 Subject: [PATCH 058/256] ASoC: uniphier: Handle regmap_write errors in aio_src_set_param() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 23fa0b04d3fd4b8277083e9a8abb1a975a05c837 Author: Ingyu Jang Date: Thu Sep 26 19:40:04 2024 +0900 ASoC: uniphier: Handle regmap_write errors in aio_src_set_param() The aio_src_set_param() function did not previously check the return values of regmap_write() and regmap_update_bits(). If these functions fail, it could lead to silent failures when configuring the sample rate converter (SRC), causing improper behavior in audio processing without any indication of an error. This patch modifies aio_src_set_param to check the return values of regmap_write() and regmap_update_bits(). If either function returns an error, the error code is propagated back to the caller to ensure proper error handling. This change aligns with the existing error-handling behavior in functions like uniphier_aio_prepare(), where a failure in a sub-function should result in an immediate return of the error. Signed-off-by: Ingyu Jang Link: https://patch.msgid.link/SE1P216MB2287F4D575CFBDC9755E896BFD6A2@SE1P216MB2287.KORP216.PROD.OUTLOOK.COM Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/uniphier/aio-core.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sound/soc/uniphier/aio-core.c b/sound/soc/uniphier/aio-core.c index b8195778953e..a3447d49aca4 100644 --- a/sound/soc/uniphier/aio-core.c +++ b/sound/soc/uniphier/aio-core.c @@ -920,16 +920,19 @@ int aio_src_set_param(struct uniphier_aio_sub *sub, { struct regmap *r = sub->aio->chip->regmap; u32 v; + int ret; if (sub->swm->dir != PORT_DIR_OUTPUT) return 0; - regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map), + ret = regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map), OPORTMXSRC1CTR_THMODE_SRC | OPORTMXSRC1CTR_SRCPATH_CALC | OPORTMXSRC1CTR_SYNC_ASYNC | OPORTMXSRC1CTR_FSIIPSEL_INNER | OPORTMXSRC1CTR_FSISEL_ACLK); + if (ret) + return ret; switch (params_rate(params)) { default: @@ -950,12 +953,18 @@ int aio_src_set_param(struct uniphier_aio_sub *sub, break; } - regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map), + + ret = regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map), v | OPORTMXRATE_I_ACLKSRC_APLL | OPORTMXRATE_I_LRCKSTP_STOP); - regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map), + if (ret) + return ret; + + ret = regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map), OPORTMXRATE_I_LRCKSTP_MASK, OPORTMXRATE_I_LRCKSTP_START); + if (ret) + return ret; return 0; } From 1fd1b0c205181a983237bd2ca2fee109dc9dd583 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:38 +0100 Subject: [PATCH 059/256] ASoC: tlv320adc3xxx: Fix unsigned int compared against 0 JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 40ba40fa4e054c62507026454529e3d530e10456 Author: Advait Dhamorikar Date: Fri Oct 4 19:40:46 2024 +0530 ASoC: tlv320adc3xxx: Fix unsigned int compared against 0 An unsigned value held by offset can never be negative, so this test will always evaluate the same way and is therefore redundant. Signed-off-by: Advait Dhamorikar Link: https://patch.msgid.link/20241004141046.61265-1-advaitdhamorikar@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/tlv320adc3xxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c index a7defb03e0c7..78c26764fe6f 100644 --- a/sound/soc/codecs/tlv320adc3xxx.c +++ b/sound/soc/codecs/tlv320adc3xxx.c @@ -961,7 +961,7 @@ static int adc3xxx_gpio_request(struct gpio_chip *chip, unsigned int offset) if (offset >= ADC3XXX_GPIOS_MAX) return -EINVAL; - if (offset >= 0 && offset < ADC3XXX_GPIO_PINS) { + if (offset < ADC3XXX_GPIO_PINS) { /* GPIO1 is offset 0, GPIO2 is offset 1 */ /* We check here that the GPIO pins are either not configured * in the DT, or that they purposely are set as outputs. From fbf2f43a21ddaefa142837af8d8e175571ef6f2d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:38 +0100 Subject: [PATCH 060/256] ASoC: fsl: fsl_qmc_audio: Remove the logging when parsing channels JIRA: https://issues.redhat.com/browse/RHEL-80681 commit c6e86e19e778553dbedab617aafb25b6bbaf4cd9 Author: Herve Codina Date: Thu Oct 3 14:20:15 2024 +0200 ASoC: fsl: fsl_qmc_audio: Remove the logging when parsing channels On each channel parsing, a log message is issued. This log message is not needed and become annoying when many channels are used (up to 64 channel supported). Simply remove this unneeded log message. Signed-off-by: Herve Codina Link: https://patch.msgid.link/20241003122015.677681-1-herve.codina@bootlin.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/fsl/fsl_qmc_audio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index 1665c835a6fc..30c8a3478212 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -838,8 +838,6 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * qmc_dai->id, i, ret); return ret; } - dev_info(qmc_audio->dev, "dai %d QMC channel %d mode %d, nb_tx_ts %u, nb_rx_ts %u\n", - qmc_dai->id, i, info.mode, info.nb_tx_ts, info.nb_rx_ts); if (info.mode != QMC_TRANSPARENT) { dev_err(qmc_audio->dev, "dai %d QMC chan %d mode %d is not QMC_TRANSPARENT\n", From 6ddb834bfb06dadf6fdb0cdcef5fb82312f02b92 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:39 +0100 Subject: [PATCH 061/256] ASoC: intel/sdw_utils: refactor RT multifunction sdca speaker codecs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 10488630e1072cc5feebf25d1be04505fafb59a5 Author: Naveen Manohar Date: Mon Oct 7 15:59:54 2024 +0800 ASoC: intel/sdw_utils: refactor RT multifunction sdca speaker codecs Merge spk_rtd_init for multifunction sdca codecs:rt712/rt722 Signed-off-by: Naveen Manohar Reviewed-by: Péter Ujfalusi Reviewed-by: Liam Girdwood Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241007075955.12575-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/soc_sdw_utils.h | 3 +- .../intel/common/soc-acpi-intel-ptl-match.c | 18 ++-- sound/soc/sdw_utils/Makefile | 3 +- sound/soc/sdw_utils/soc_sdw_rt712_sdca.c | 48 ----------- sound/soc/sdw_utils/soc_sdw_rt722_sdca.c | 41 --------- sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c | 85 +++++++++++++++++++ sound/soc/sdw_utils/soc_sdw_utils.c | 4 +- 7 files changed, 98 insertions(+), 104 deletions(-) delete mode 100644 sound/soc/sdw_utils/soc_sdw_rt712_sdca.c delete mode 100644 sound/soc/sdw_utils/soc_sdw_rt722_sdca.c create mode 100644 sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h index 0150b3735b4b..a25f94d6eb67 100644 --- a/include/sound/soc_sdw_utils.h +++ b/include/sound/soc_sdw_utils.h @@ -236,8 +236,7 @@ int asoc_sdw_rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_s int asoc_sdw_rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); int asoc_sdw_rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); int asoc_sdw_rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int asoc_sdw_rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int asoc_sdw_rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt_mf_sdca_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); int asoc_sdw_rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); int asoc_sdw_cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); int asoc_sdw_cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c index 7107f0151030..5ed905440e9d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -36,10 +36,10 @@ static const struct snd_soc_acpi_endpoint single_endpoint = { }; /* - * RT722 is a multi-function codec, three endpoints are created for - * its headset, amp and dmic functions. + * Multi-function codecs with three endpoints created for + * headset, amp and dmic functions. */ -static const struct snd_soc_acpi_endpoint rt722_endpoints[] = { +static const struct snd_soc_acpi_endpoint rt_mf_endpoints[] = { { .num = 0, .aggregated = 0, @@ -72,8 +72,8 @@ static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = { { .adr = 0x000030025d072201ull, - .num_endpoints = ARRAY_SIZE(rt722_endpoints), - .endpoints = rt722_endpoints, + .num_endpoints = ARRAY_SIZE(rt_mf_endpoints), + .endpoints = rt_mf_endpoints, .name_prefix = "rt722" } }; @@ -81,8 +81,8 @@ static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = { static const struct snd_soc_acpi_adr_device rt722_1_single_adr[] = { { .adr = 0x000130025d072201ull, - .num_endpoints = ARRAY_SIZE(rt722_endpoints), - .endpoints = rt722_endpoints, + .num_endpoints = ARRAY_SIZE(rt_mf_endpoints), + .endpoints = rt_mf_endpoints, .name_prefix = "rt722" } }; @@ -90,8 +90,8 @@ static const struct snd_soc_acpi_adr_device rt722_1_single_adr[] = { static const struct snd_soc_acpi_adr_device rt722_3_single_adr[] = { { .adr = 0x000330025d072201ull, - .num_endpoints = ARRAY_SIZE(rt722_endpoints), - .endpoints = rt722_endpoints, + .num_endpoints = ARRAY_SIZE(rt_mf_endpoints), + .endpoints = rt_mf_endpoints, .name_prefix = "rt722" } }; diff --git a/sound/soc/sdw_utils/Makefile b/sound/soc/sdw_utils/Makefile index 28229ed96ffb..daf019113553 100644 --- a/sound/soc/sdw_utils/Makefile +++ b/sound/soc/sdw_utils/Makefile @@ -1,9 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only snd-soc-sdw-utils-y := soc_sdw_utils.o soc_sdw_dmic.o soc_sdw_rt_dmic.o \ soc_sdw_rt700.o soc_sdw_rt711.o \ - soc_sdw_rt712_sdca.o soc_sdw_rt722_sdca.o \ soc_sdw_rt5682.o soc_sdw_rt_sdca_jack_common.o \ - soc_sdw_rt_amp.o \ + soc_sdw_rt_amp.o soc_sdw_rt_mf_sdca.o \ soc_sdw_bridge_cs35l56.o \ soc_sdw_cs42l42.o soc_sdw_cs42l43.o \ soc_sdw_cs_amp.o \ diff --git a/sound/soc/sdw_utils/soc_sdw_rt712_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt712_sdca.c deleted file mode 100644 index 5127210b9a03..000000000000 --- a/sound/soc/sdw_utils/soc_sdw_rt712_sdca.c +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// This file incorporates work covered by the following copyright notice: -// Copyright (c) 2023 Intel Corporation -// Copyright (c) 2024 Advanced Micro Devices, Inc. - -/* - * soc_sdw_rt712_sdca - Helpers to handle RT712-SDCA from generic machine driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * dapm routes for rt712 spk will be registered dynamically according - * to the number of rt712 spk used. The first two entries will be registered - * for one codec case, and the last two entries are also registered - * if two rt712s are used. - */ -static const struct snd_soc_dapm_route rt712_spk_map[] = { - { "Speaker", NULL, "rt712 SPOL" }, - { "Speaker", NULL, "rt712 SPOR" }, -}; - -int asoc_sdw_rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) -{ - struct snd_soc_card *card = rtd->card; - int ret; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s spk:rt712", - card->components); - if (!card->components) - return -ENOMEM; - - ret = snd_soc_dapm_add_routes(&card->dapm, rt712_spk_map, ARRAY_SIZE(rt712_spk_map)); - if (ret) - dev_err(rtd->dev, "failed to add SPK map: %d\n", ret); - - return ret; -} -EXPORT_SYMBOL_NS(asoc_sdw_rt712_spk_rtd_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/sdw_utils/soc_sdw_rt722_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt722_sdca.c deleted file mode 100644 index 6a402172289f..000000000000 --- a/sound/soc/sdw_utils/soc_sdw_rt722_sdca.c +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// This file incorporates work covered by the following copyright notice: -// Copyright (c) 2023 Intel Corporation -// Copyright (c) 2024 Advanced Micro Devices, Inc. - -/* - * soc_sdw_rt722_sdca - Helpers to handle RT722-SDCA from generic machine driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const struct snd_soc_dapm_route rt722_spk_map[] = { - { "Speaker", NULL, "rt722 SPK" }, -}; - -int asoc_sdw_rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) -{ - struct snd_soc_card *card = rtd->card; - int ret; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s spk:rt722", - card->components); - if (!card->components) - return -ENOMEM; - - ret = snd_soc_dapm_add_routes(&card->dapm, rt722_spk_map, ARRAY_SIZE(rt722_spk_map)); - if (ret) - dev_err(rtd->dev, "failed to add rt722 spk map: %d\n", ret); - - return ret; -} -EXPORT_SYMBOL_NS(asoc_sdw_rt722_spk_rtd_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c new file mode 100644 index 000000000000..8143d59ad10f --- /dev/null +++ b/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: +// Copyright (c) 2024 Intel Corporation. + +/* + * soc_sdw_rt_mf_sdca + * - Helpers to handle RT Multifunction Codec from generic machine driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CODEC_NAME_SIZE 6 + +/* dapm routes for RT-SPK will be registered dynamically */ +static const struct snd_soc_dapm_route rt712_spk_map[] = { + { "Speaker", NULL, "rt712 SPOL" }, + { "Speaker", NULL, "rt712 SPOR" }, +}; + +static const struct snd_soc_dapm_route rt722_spk_map[] = { + { "Speaker", NULL, "rt722 SPK" }, +}; + +/* Structure to map codec names to respective route arrays and sizes */ +struct codec_route_map { + const char *codec_name; + const struct snd_soc_dapm_route *route_map; + size_t route_size; +}; + +/* Codec route maps array */ +static const struct codec_route_map codec_routes[] = { + { "rt712", rt712_spk_map, ARRAY_SIZE(rt712_spk_map) }, + { "rt722", rt722_spk_map, ARRAY_SIZE(rt722_spk_map) }, +}; + +static const struct codec_route_map *get_codec_route_map(const char *codec_name) +{ + for (size_t i = 0; i < ARRAY_SIZE(codec_routes); i++) { + if (strcmp(codec_routes[i].codec_name, codec_name) == 0) + return &codec_routes[i]; + } + return NULL; +} + +int asoc_sdw_rt_mf_sdca_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +{ + struct snd_soc_card *card = rtd->card; + char codec_name[CODEC_NAME_SIZE]; + int ret; + + /* acquire codec name */ + snprintf(codec_name, CODEC_NAME_SIZE, "%s", dai->name); + + /* acquire corresponding route map and size */ + const struct codec_route_map *route_map = get_codec_route_map(codec_name); + + if (!route_map) { + dev_err(rtd->dev, "failed to get codec name and route map\n"); + return -EINVAL; + } + + /* Update card components */ + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s spk:%s", + card->components, codec_name); + if (!card->components) + return -ENOMEM; + + /* Add routes */ + ret = snd_soc_dapm_add_routes(&card->dapm, route_map->route_map, route_map->route_size); + if (ret) + dev_err(rtd->dev, "failed to add rt sdca spk map: %d\n", ret); + + return ret; +} +EXPORT_SYMBOL_NS(asoc_sdw_rt_mf_sdca_spk_rtd_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index e6ac5c0fd3be..30ffd33706a2 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -138,7 +138,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, .init = asoc_sdw_rt_amp_init, .exit = asoc_sdw_rt_amp_exit, - .rtd_init = asoc_sdw_rt712_spk_rtd_init, + .rtd_init = asoc_sdw_rt_mf_sdca_spk_rtd_init, .controls = generic_spk_controls, .num_controls = ARRAY_SIZE(generic_spk_controls), .widgets = generic_spk_widgets, @@ -358,7 +358,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, .init = asoc_sdw_rt_amp_init, .exit = asoc_sdw_rt_amp_exit, - .rtd_init = asoc_sdw_rt722_spk_rtd_init, + .rtd_init = asoc_sdw_rt_mf_sdca_spk_rtd_init, .controls = generic_spk_controls, .num_controls = ARRAY_SIZE(generic_spk_controls), .widgets = generic_spk_widgets, From c81362a4d1e6feafce7c527cdc95a0d68b4fcafd Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:39 +0100 Subject: [PATCH 062/256] ASoC: Intel: soc-acpi-intel-ptl-match: Add rt721 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 846a8d3cf3bace9f235c38caf1d8d853c323dbd4 Author: Naveen Manohar Date: Mon Oct 7 15:59:55 2024 +0800 ASoC: Intel: soc-acpi-intel-ptl-match: Add rt721 support Patch adds driver data & match table for rt721 multi-function codec on PTL-RVP at sdw link3. Signed-off-by: Naveen Manohar Reviewed-by: Péter Ujfalusi Reviewed-by: Liam Girdwood Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241007075955.12575-4-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- .../intel/common/soc-acpi-intel-ptl-match.c | 24 +++++++++++ sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c | 5 +++ .../sdw_utils/soc_sdw_rt_sdca_jack_common.c | 8 ++++ sound/soc/sdw_utils/soc_sdw_utils.c | 41 +++++++++++++++++++ 4 files changed, 78 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c index 5ed905440e9d..f1c0d7a02cda 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -69,6 +69,24 @@ static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt721_3_single_adr[] = { + { + .adr = 0x000330025d072101ull, + .num_endpoints = ARRAY_SIZE(rt_mf_endpoints), + .endpoints = rt_mf_endpoints, + .name_prefix = "rt721" + } +}; + +static const struct snd_soc_acpi_link_adr ptl_rt721_l3[] = { + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt721_3_single_adr), + .adr_d = rt721_3_single_adr, + }, + {}, +}; + static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = { { .adr = 0x000030025d072201ull, @@ -159,6 +177,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-ptl-rt711.tplg", }, + { + .link_mask = BIT(3), + .links = ptl_rt721_l3, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-ptl-rt721.tplg", + }, { .link_mask = BIT(0), .links = ptl_rt722_only, diff --git a/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c index 8143d59ad10f..81e43319876e 100644 --- a/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c +++ b/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c @@ -25,6 +25,10 @@ static const struct snd_soc_dapm_route rt712_spk_map[] = { { "Speaker", NULL, "rt712 SPOR" }, }; +static const struct snd_soc_dapm_route rt721_spk_map[] = { + { "Speaker", NULL, "rt721 SPK" }, +}; + static const struct snd_soc_dapm_route rt722_spk_map[] = { { "Speaker", NULL, "rt722 SPK" }, }; @@ -39,6 +43,7 @@ struct codec_route_map { /* Codec route maps array */ static const struct codec_route_map codec_routes[] = { { "rt712", rt712_spk_map, ARRAY_SIZE(rt712_spk_map) }, + { "rt721", rt721_spk_map, ARRAY_SIZE(rt721_spk_map) }, { "rt722", rt722_spk_map, ARRAY_SIZE(rt722_spk_map) }, }; diff --git a/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c b/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c index 3e6211dc1599..af43efbb8f79 100644 --- a/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c +++ b/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c @@ -60,6 +60,11 @@ static const struct snd_soc_dapm_route rt713_sdca_map[] = { { "rt713 MIC2", NULL, "Headset Mic" }, }; +static const struct snd_soc_dapm_route rt721_sdca_map[] = { + { "Headphone", NULL, "rt721 HP" }, + { "rt721 MIC2", NULL, "Headset Mic" }, +}; + static const struct snd_soc_dapm_route rt722_sdca_map[] = { { "Headphone", NULL, "rt722 HP" }, { "rt722 MIC2", NULL, "Headset Mic" }, @@ -121,6 +126,9 @@ int asoc_sdw_rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_s } else if (strstr(component->name_prefix, "rt713")) { ret = snd_soc_dapm_add_routes(&card->dapm, rt713_sdca_map, ARRAY_SIZE(rt713_sdca_map)); + } else if (strstr(component->name_prefix, "rt721")) { + ret = snd_soc_dapm_add_routes(&card->dapm, rt721_sdca_map, + ARRAY_SIZE(rt721_sdca_map)); } else if (strstr(component->name_prefix, "rt722")) { ret = snd_soc_dapm_add_routes(&card->dapm, rt722_sdca_map, ARRAY_SIZE(rt722_sdca_map)); diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index 30ffd33706a2..c8f933bf891a 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -333,6 +333,47 @@ struct asoc_sdw_codec_info codec_info_list[] = { }, .dai_num = 1, }, + { + .part_id = 0x721, + .version_id = 3, + .dais = { + { + .direction = {true, true}, + .dai_name = "rt721-sdca-aif1", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .init = asoc_sdw_rt_sdca_jack_init, + .exit = asoc_sdw_rt_sdca_jack_exit, + .rtd_init = asoc_sdw_rt_sdca_jack_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), + }, + { + .direction = {true, false}, + .dai_name = "rt721-sdca-aif2", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + /* No feedback capability is provided by rt721-sdca codec driver*/ + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .init = asoc_sdw_rt_amp_init, + .exit = asoc_sdw_rt_amp_exit, + .rtd_init = asoc_sdw_rt_mf_sdca_spk_rtd_init, + .controls = generic_spk_controls, + .num_controls = ARRAY_SIZE(generic_spk_controls), + .widgets = generic_spk_widgets, + .num_widgets = ARRAY_SIZE(generic_spk_widgets), + }, + { + .direction = {false, true}, + .dai_name = "rt721-sdca-aif3", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_rt_dmic_rtd_init, + }, + }, + .dai_num = 3, + }, { .part_id = 0x722, .version_id = 3, From ca08f9f80aca55b6e4049046c2421fd52346c320 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:39 +0100 Subject: [PATCH 063/256] ASoC: rt-sdw-common: Common functions for Realtek soundwire driver JIRA: https://issues.redhat.com/browse/RHEL-80681 commit bbca8e7050e0769d46eb775082d1926db05e7dac Author: Jack Yu Date: Tue Oct 1 09:16:27 2024 +0000 ASoC: rt-sdw-common: Common functions for Realtek soundwire driver This is the first version of common functions for Realtek soundwire codec driver. Signed-off-by: Jack Yu Link: https://patch.msgid.link/959e8dcb075948459be4463f6a4ca6ee@realtek.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt-sdw-common.c | 238 +++++++++++++++++++++++++++++++ sound/soc/codecs/rt-sdw-common.h | 66 +++++++++ 4 files changed, 311 insertions(+) create mode 100644 sound/soc/codecs/rt-sdw-common.c create mode 100644 sound/soc/codecs/rt-sdw-common.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index ffbed0a4f096..afcad822e80c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1475,6 +1475,11 @@ config SND_SOC_RL6231 default m if SND_SOC_RT1305=m default m if SND_SOC_RT1308=m +config SND_SOC_RT_SDW_COMMON + tristate + default y if SND_SOC_RT721_SDCA_SDW=y + default m if SND_SOC_RT721_SDCA_SDW=m + config SND_SOC_RL6347A tristate default y if SND_SOC_RT274=y diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 91f5dd1173f2..e7b17a77a455 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -211,6 +211,7 @@ snd-soc-peb2466-y := peb2466.o snd-soc-rk3328-y := rk3328_codec.o snd-soc-rk817-y := rk817_codec.o snd-soc-rl6231-y := rl6231.o +snd-soc-rt-sdw-common-y := rt-sdw-common.o snd-soc-rl6347a-y := rl6347a.o snd-soc-rt1011-y := rt1011.o snd-soc-rt1015-y := rt1015.o @@ -608,6 +609,7 @@ obj-$(CONFIG_SND_SOC_PEB2466) += snd-soc-peb2466.o obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o +obj-$(CONFIG_SND_SOC_RT_SDW_COMMON) += snd-soc-rt-sdw-common.o obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o obj-$(CONFIG_SND_SOC_RT1015) += snd-soc-rt1015.o diff --git a/sound/soc/codecs/rt-sdw-common.c b/sound/soc/codecs/rt-sdw-common.c new file mode 100644 index 000000000000..9ed0e9855699 --- /dev/null +++ b/sound/soc/codecs/rt-sdw-common.c @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt-sdw-common.c +// +// Copyright(c) 2024 Realtek Semiconductor Corp. +// + +/* + * This file defines common functions used with Realtek soundwire codecs. + */ + +#include +#include +#include +#include +#include + +#include "rt-sdw-common.h" + +/** + * rt_sdca_index_write - Write a value to Realtek defined register. + * + * @map: map for setting. + * @nid: Realtek-defined ID. + * @reg: register. + * @value: value. + * + * A value of zero will be returned on success, a negative errno will + * be returned in error cases. + */ +int rt_sdca_index_write(struct regmap *map, unsigned int nid, + unsigned int reg, unsigned int value) +{ + unsigned int addr = (nid << 20) | reg; + int ret; + + ret = regmap_write(map, addr, value); + if (ret < 0) + pr_err("Failed to set value: %06x <= %04x ret=%d\n", + addr, value, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(rt_sdca_index_write); + +/** + * rt_sdca_index_read - Read value from Realtek defined register. + * + * @map: map for setting. + * @nid: Realtek-defined ID. + * @reg: register. + * @value: value. + * + * A value of zero will be returned on success, a negative errno will + * be returned in error cases. + */ +int rt_sdca_index_read(struct regmap *map, unsigned int nid, + unsigned int reg, unsigned int *value) +{ + unsigned int addr = (nid << 20) | reg; + int ret; + + ret = regmap_read(map, addr, value); + if (ret < 0) + pr_err("Failed to get value: %06x => %04x ret=%d\n", + addr, *value, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(rt_sdca_index_read); + +/** + * rt_sdca_index_update_bits - Update value on Realtek defined register. + * + * @map: map for setting. + * @nid: Realtek-defined ID. + * @reg: register. + * @mask: Bitmask to change + * @value: New value for bitmask + * + * A value of zero will be returned on success, a negative errno will + * be returned in error cases. + */ + +int rt_sdca_index_update_bits(struct regmap *map, + unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) +{ + unsigned int tmp; + int ret; + + ret = rt_sdca_index_read(map, nid, reg, &tmp); + if (ret < 0) + return ret; + + set_mask_bits(&tmp, mask, val); + return rt_sdca_index_write(map, nid, reg, tmp); +} +EXPORT_SYMBOL_GPL(rt_sdca_index_update_bits); + +/** + * rt_sdca_btn_type - Decision of button type. + * + * @buffer: UMP message buffer. + * + * A button type will be returned regarding to buffer, + * it returns zero if buffer cannot be recognized. + */ +int rt_sdca_btn_type(unsigned char *buffer) +{ + u8 btn_type = 0; + int ret; + + btn_type |= buffer[0] & 0xf; + btn_type |= (buffer[0] >> 4) & 0xf; + btn_type |= buffer[1] & 0xf; + btn_type |= (buffer[1] >> 4) & 0xf; + + if (btn_type & BIT(0)) + ret |= SND_JACK_BTN_2; + if (btn_type & BIT(1)) + ret |= SND_JACK_BTN_3; + if (btn_type & BIT(2)) + ret |= SND_JACK_BTN_0; + if (btn_type & BIT(3)) + ret |= SND_JACK_BTN_1; + + return ret; +} +EXPORT_SYMBOL_GPL(rt_sdca_btn_type); + +/** + * rt_sdca_headset_detect - Headset jack type detection. + * + * @map: map for setting. + * @entity_id: SDCA entity ID. + * + * A headset jack type will be returned, a negative errno will + * be returned in error cases. + */ +int rt_sdca_headset_detect(struct regmap *map, unsigned int entity_id) +{ + unsigned int det_mode, jack_type; + int ret; + + /* get detected_mode */ + ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_JACK_CODEC, entity_id, + RT_SDCA_CTL_DETECTED_MODE, 0), &det_mode); + + if (ret < 0) + goto io_error; + + switch (det_mode) { + case 0x00: + jack_type = 0; + break; + case 0x03: + jack_type = SND_JACK_HEADPHONE; + break; + case 0x05: + jack_type = SND_JACK_HEADSET; + break; + } + + /* write selected_mode */ + if (det_mode) { + ret = regmap_write(map, SDW_SDCA_CTL(SDCA_NUM_JACK_CODEC, entity_id, + RT_SDCA_CTL_SELECTED_MODE, 0), det_mode); + if (ret < 0) + goto io_error; + } + + return jack_type; + +io_error: + pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); + return ret; +} +EXPORT_SYMBOL_GPL(rt_sdca_headset_detect); + +/** + * rt_sdca_button_detect - Read UMP message and decide button type. + * + * @map: map for setting. + * @entity_id: SDCA entity ID. + * @hid_buf_addr: HID buffer address. + * @hid_id: Report ID for HID. + * + * A button type will be returned regarding to buffer, + * it returns zero if buffer cannot be recognized. + */ +int rt_sdca_button_detect(struct regmap *map, unsigned int entity_id, + unsigned int hid_buf_addr, unsigned int hid_id) +{ + unsigned int btn_type = 0, offset, idx, val, owner; + unsigned char buf[3]; + int ret; + + /* get current UMP message owner */ + ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_HID, entity_id, + RT_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), &owner); + if (ret < 0) + return 0; + + /* if owner is device then there is no button event from device */ + if (owner == 1) + return 0; + + /* read UMP message offset */ + ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_HID, entity_id, + RT_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), &offset); + if (ret < 0) + goto _end_btn_det_; + + for (idx = 0; idx < sizeof(buf); idx++) { + ret = regmap_read(map, hid_buf_addr + offset + idx, &val); + if (ret < 0) + goto _end_btn_det_; + buf[idx] = val & 0xff; + } + /* Report ID for HID */ + if (buf[0] == hid_id) + btn_type = rt_sdca_btn_type(&buf[1]); + +_end_btn_det_: + /* Host is owner, so set back to device */ + if (owner == 0) + /* set owner to device */ + regmap_write(map, + SDW_SDCA_CTL(SDCA_NUM_HID, entity_id, + RT_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 0x01); + + return btn_type; +} +EXPORT_SYMBOL_GPL(rt_sdca_button_detect); + +MODULE_DESCRIPTION("Realtek soundwire common functions"); +MODULE_AUTHOR("jack yu "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt-sdw-common.h b/sound/soc/codecs/rt-sdw-common.h new file mode 100644 index 000000000000..4759516feb38 --- /dev/null +++ b/sound/soc/codecs/rt-sdw-common.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +// +// rt-sdw-common.h +// +// Copyright(c) 2024 Realtek Semiconductor Corp. +// + +/* + * This file defines common functions used with Realtek soundwire codecs. + */ + +#ifndef __RT_SDW_COMMON_H__ +#define __RT_SDW_COMMON_H__ + +#define SDCA_NUM_JACK_CODEC 0x01 +#define SDCA_NUM_MIC_ARRAY 0x02 +#define SDCA_NUM_HID 0x03 +#define SDCA_NUM_AMP 0x04 +#define RT_SDCA_CTL_SELECTED_MODE 0x01 +#define RT_SDCA_CTL_DETECTED_MODE 0x02 +#define RT_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10 +#define RT_SDCA_CTL_HIDTX_MESSAGE_OFFSET 0x12 + +struct rt_sdca_dmic_kctrl_priv { + unsigned int reg_base; + unsigned int count; + unsigned int max; + unsigned int invert; +}; + +#define RT_SDCA_PR_VALUE(xreg_base, xcount, xmax, xinvert) \ + ((unsigned long)&(struct rt_sdca_dmic_kctrl_priv) \ + {.reg_base = xreg_base, .count = xcount, .max = xmax, \ + .invert = xinvert}) + +#define RT_SDCA_FU_CTRL(xname, reg_base, xmax, xinvert, xcount, \ + xinfo, xget, xput) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = xinfo, \ + .get = xget, \ + .put = xput, \ + .private_value = RT_SDCA_PR_VALUE(reg_base, xcount, xmax, xinvert)} + +#define RT_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\ + xhandler_put, xcount, xmax, tlv_array, xinfo) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .tlv.p = (tlv_array), \ + .info = xinfo, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = RT_SDCA_PR_VALUE(reg_base, xcount, xmax, 0) } + + +int rt_sdca_index_write(struct regmap *map, unsigned int nid, + unsigned int reg, unsigned int value); +int rt_sdca_index_read(struct regmap *map, unsigned int nid, + unsigned int reg, unsigned int *value); +int rt_sdca_index_update_bits(struct regmap *map, + unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val); +int rt_sdca_btn_type(unsigned char *buffer); +int rt_sdca_headset_detect(struct regmap *map, unsigned int entity_id); +int rt_sdca_button_detect(struct regmap *map, unsigned int entity_id, + unsigned int hid_buf_addr, unsigned int hid_id); + +#endif /* __RT_SDW_COMMON_H__ */ From 83c658e9b9ee4c1091ee204b0569d2987c6043a9 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:39 +0100 Subject: [PATCH 064/256] ASoC: rt721-sdca: Add RT721 SDCA driver JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 86ce355c1f9ab943bbe099ea7d0b8a3af2247f65 Author: Jack Yu Date: Tue Oct 1 09:17:38 2024 +0000 ASoC: rt721-sdca: Add RT721 SDCA driver This is the initial codec driver for rt721-sdca. It's a three functions (jack,mic,amp) soundwire driver. Signed-off-by: Jack Yu v2: Fix typo in mbq default registers. v3: Include soundwire common functions for Realtek. Link: https://patch.msgid.link/d18b35f8b6934fc6a2be6c4458a63fe5@realtek.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 7 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt721-sdca-sdw.c | 551 ++++++++++ sound/soc/codecs/rt721-sdca-sdw.h | 150 +++ sound/soc/codecs/rt721-sdca.c | 1547 +++++++++++++++++++++++++++++ sound/soc/codecs/rt721-sdca.h | 268 +++++ 6 files changed, 2525 insertions(+) create mode 100644 sound/soc/codecs/rt721-sdca-sdw.c create mode 100644 sound/soc/codecs/rt721-sdca-sdw.h create mode 100644 sound/soc/codecs/rt721-sdca.c create mode 100644 sound/soc/codecs/rt721-sdca.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index afcad822e80c..6fc6bfe5be8b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -216,6 +216,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT712_SDCA_DMIC_SDW imply SND_SOC_RT715_SDW imply SND_SOC_RT715_SDCA_SDW + imply SND_SOC_RT721_SDCA_SDW imply SND_SOC_RT722_SDCA_SDW imply SND_SOC_RT1308_SDW imply SND_SOC_RT1316_SDW @@ -1678,6 +1679,12 @@ config SND_SOC_RT712_SDCA_DMIC_SDW select REGMAP_SOUNDWIRE select REGMAP_SOUNDWIRE_MBQ +config SND_SOC_RT721_SDCA_SDW + tristate "Realtek RT721 SDCA Codec - SDW" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + select REGMAP_SOUNDWIRE_MBQ + config SND_SOC_RT722_SDCA_SDW tristate "Realtek RT722 SDCA Codec - SDW" depends on SOUNDWIRE diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index e7b17a77a455..c2eb999a1d92 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -255,6 +255,7 @@ snd-soc-rt712-sdca-y := rt712-sdca.o rt712-sdca-sdw.o snd-soc-rt712-sdca-dmic-y := rt712-sdca-dmic.o snd-soc-rt715-y := rt715.o rt715-sdw.o snd-soc-rt715-sdca-y := rt715-sdca.o rt715-sdca-sdw.o +snd-soc-rt721-sdca-y := rt721-sdca.o rt721-sdca-sdw.o snd-soc-rt722-sdca-y := rt722-sdca.o rt722-sdca-sdw.o snd-soc-rt9120-y := rt9120.o snd-soc-rtq9128-y := rtq9128.o @@ -654,6 +655,7 @@ obj-$(CONFIG_SND_SOC_RT712_SDCA_SDW) += snd-soc-rt712-sdca.o obj-$(CONFIG_SND_SOC_RT712_SDCA_DMIC_SDW) += snd-soc-rt712-sdca-dmic.o obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o +obj-$(CONFIG_SND_SOC_RT721_SDCA_SDW) += snd-soc-rt721-sdca.o obj-$(CONFIG_SND_SOC_RT722_SDCA_SDW) += snd-soc-rt722-sdca.o obj-$(CONFIG_SND_SOC_RT9120) += snd-soc-rt9120.o obj-$(CONFIG_SND_SOC_RTQ9128) += snd-soc-rtq9128.o diff --git a/sound/soc/codecs/rt721-sdca-sdw.c b/sound/soc/codecs/rt721-sdca-sdw.c new file mode 100644 index 000000000000..c0f8cccae3b2 --- /dev/null +++ b/sound/soc/codecs/rt721-sdca-sdw.c @@ -0,0 +1,551 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt721-sdca-sdw.c -- rt721 SDCA ALSA SoC audio driver +// +// Copyright(c) 2024 Realtek Semiconductor Corp. +// +// + +#include +#include +#include +#include +#include +#include + +#include "rt721-sdca.h" +#include "rt721-sdca-sdw.h" +#include "rt-sdw-common.h" + +static bool rt721_sdca_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2f01 ... 0x2f0a: + case 0x2f35: + case 0x2f50: + case 0x2f51: + case 0x2f58 ... 0x2f5d: + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XUV, + RT721_SDCA_CTL_XUV, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49, + RT721_SDCA_CTL_SELECTED_MODE, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49, + RT721_SDCA_CTL_DETECTED_MODE, 0): + case SDW_SDCA_CTL(FUNC_NUM_HID, RT721_SDCA_ENT_HID01, + RT721_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, + RT721_SDCA_ENT_HID01, RT721_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): + case RT721_BUF_ADDR_HID1 ... RT721_BUF_ADDR_HID2: + return true; + default: + return false; + } +} + +static bool rt721_sdca_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2f01: + case 0x2f51: + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49, + RT721_SDCA_CTL_DETECTED_MODE, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XUV, + RT721_SDCA_CTL_XUV, 0): + case SDW_SDCA_CTL(FUNC_NUM_HID, RT721_SDCA_ENT_HID01, + RT721_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, + RT721_SDCA_ENT_HID01, RT721_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): + case RT721_BUF_ADDR_HID1 ... RT721_BUF_ADDR_HID2: + return true; + default: + return false; + } +} + +static bool rt721_sdca_mbq_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x0900007: + case 0x0a00005: + case 0x0c00005: + case 0x0d00014: + case 0x0310100: + case 0x2000001: + case 0x2000002: + case 0x2000003: + case 0x2000013: + case 0x200003c: + case 0x2000046: + case 0x5810000: + case 0x5810036: + case 0x5810037: + case 0x5810038: + case 0x5810039: + case 0x5b10018: + case 0x5b10019: + case 0x5f00045: + case 0x5f00048: + case 0x6100000: + case 0x6100005: + case 0x6100006: + case 0x610000d: + case 0x6100010: + case 0x6100011: + case 0x6100013: + case 0x6100015: + case 0x6100017: + case 0x6100025: + case 0x6100029: + case 0x610002c ... 0x610002f: + case 0x6100053 ... 0x6100055: + case 0x6100057: + case 0x610005a: + case 0x610005b: + case 0x610006a: + case 0x610006d: + case 0x6100092: + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, RT721_SDCA_CTL_FU_VOLUME, + CH_L): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, RT721_SDCA_CTL_FU_VOLUME, + CH_R): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, RT721_SDCA_CTL_FU_VOLUME, + CH_L): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, RT721_SDCA_CTL_FU_VOLUME, + CH_R): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44, + RT721_SDCA_CTL_FU_CH_GAIN, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44, + RT721_SDCA_CTL_FU_CH_GAIN, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME, + CH_01): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME, + CH_02): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME, + CH_03): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME, + CH_04): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, RT721_SDCA_CTL_FU_VOLUME, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, RT721_SDCA_CTL_FU_VOLUME, CH_R): + return true; + default: + return false; + } +} + +static bool rt721_sdca_mbq_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x0310100: + case 0x0a00005: + case 0x0c00005: + case 0x0d00014: + case 0x2000000: + case 0x200000d: + case 0x2000019: + case 0x2000020: + case 0x2000030: + case 0x2000046: + case 0x2000067: + case 0x2000084: + case 0x2000086: + case 0x5810000: + case 0x5810036: + case 0x5810037: + case 0x5810038: + case 0x5810039: + case 0x5b10018: + case 0x5b10019: + return true; + default: + return false; + } +} + +static const struct regmap_config rt721_sdca_regmap = { + .reg_bits = 32, + .val_bits = 8, + .readable_reg = rt721_sdca_readable_register, + .volatile_reg = rt721_sdca_volatile_register, + .max_register = 0x44ffffff, + .reg_defaults = rt721_sdca_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(rt721_sdca_reg_defaults), + .cache_type = REGCACHE_MAPLE, + .use_single_read = true, + .use_single_write = true, +}; + +static const struct regmap_config rt721_sdca_mbq_regmap = { + .name = "sdw-mbq", + .reg_bits = 32, + .val_bits = 16, + .readable_reg = rt721_sdca_mbq_readable_register, + .volatile_reg = rt721_sdca_mbq_volatile_register, + .max_register = 0x41000312, + .reg_defaults = rt721_sdca_mbq_defaults, + .num_reg_defaults = ARRAY_SIZE(rt721_sdca_mbq_defaults), + .cache_type = REGCACHE_MAPLE, + .use_single_read = true, + .use_single_write = true, +}; + +static int rt721_sdca_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct rt721_sdca_priv *rt721 = dev_get_drvdata(&slave->dev); + + if (status == SDW_SLAVE_UNATTACHED) + rt721->hw_init = false; + + if (status == SDW_SLAVE_ATTACHED) { + if (rt721->hs_jack) { + /* + * Due to the SCP_SDCA_INTMASK will be cleared by any reset, and then + * if the device attached again, we will need to set the setting back. + * It could avoid losing the jack detection interrupt. + * This also could sync with the cache value as the rt721_sdca_jack_init set. + */ + sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK1, + SDW_SCP_SDCA_INTMASK_SDCA_6); + sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK2, + SDW_SCP_SDCA_INTMASK_SDCA_8); + } + } + + /* + * Perform initialization only if slave status is present and + * hw_init flag is false + */ + if (rt721->hw_init || status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return rt721_sdca_io_init(&slave->dev, slave); +} + +static int rt721_sdca_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval; + int i, j; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + sdw_slave_read_prop(slave); + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; + + prop->paging_support = true; + + /* + * port = 1 for headphone playback + * port = 2 for headset-mic capture + * port = 3 for speaker playback + * port = 6 for digital-mic capture + */ + prop->source_ports = BIT(6) | BIT(2); /* BITMAP: 01000100 */ + prop->sink_ports = BIT(3) | BIT(1); /* BITMAP: 00001010 */ + + nval = hweight32(prop->source_ports); + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* do this again for sink now */ + nval = hweight32(prop->sink_ports); + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + j = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[j].num = bit; + dpn[j].type = SDW_DPN_FULL; + dpn[j].simple_ch_prep_sm = true; + dpn[j].ch_prep_timeout = 10; + j++; + } + + /* set the timeout values */ + prop->clk_stop_timeout = 900; + + /* wake-up event */ + prop->wake_capable = 1; + + /* Three data lanes are supported by rt721-sdca codec */ + prop->lane_control_support = true; + + return 0; +} + +static int rt721_sdca_interrupt_callback(struct sdw_slave *slave, + struct sdw_slave_intr_status *status) +{ + struct rt721_sdca_priv *rt721 = dev_get_drvdata(&slave->dev); + int ret, stat; + int count = 0, retry = 3; + unsigned int sdca_cascade, scp_sdca_stat1, scp_sdca_stat2 = 0; + + if (cancel_delayed_work_sync(&rt721->jack_detect_work)) { + dev_warn(&slave->dev, "%s the pending delayed_work was cancelled", __func__); + /* avoid the HID owner doesn't change to device */ + if (rt721->scp_sdca_stat2) + scp_sdca_stat2 = rt721->scp_sdca_stat2; + } + + /* + * The critical section below intentionally protects a rather large piece of code. + * We don't want to allow the system suspend to disable an interrupt while we are + * processing it, which could be problematic given the quirky SoundWire interrupt + * scheme. We do want however to prevent new workqueues from being scheduled if + * the disable_irq flag was set during system suspend. + */ + mutex_lock(&rt721->disable_irq_lock); + + ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1); + if (ret < 0) + goto io_error; + + rt721->scp_sdca_stat1 = ret; + ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2); + if (ret < 0) + goto io_error; + + rt721->scp_sdca_stat2 = ret; + if (scp_sdca_stat2) + rt721->scp_sdca_stat2 |= scp_sdca_stat2; + do { + /* clear flag */ + ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1); + if (ret < 0) + goto io_error; + if (ret & SDW_SCP_SDCA_INTMASK_SDCA_0) { + ret = sdw_update_no_pm(rt721->slave, SDW_SCP_SDCA_INT1, + SDW_SCP_SDCA_INT_SDCA_0, SDW_SCP_SDCA_INT_SDCA_0); + if (ret < 0) + goto io_error; + } else if (ret & SDW_SCP_SDCA_INTMASK_SDCA_6) { + ret = sdw_update_no_pm(rt721->slave, SDW_SCP_SDCA_INT1, + SDW_SCP_SDCA_INT_SDCA_6, SDW_SCP_SDCA_INT_SDCA_6); + if (ret < 0) + goto io_error; + } + ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2); + if (ret < 0) + goto io_error; + if (ret & SDW_SCP_SDCA_INTMASK_SDCA_8) { + ret = sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INT2, + SDW_SCP_SDCA_INTMASK_SDCA_8); + if (ret < 0) + goto io_error; + } + + /* check if flag clear or not */ + ret = sdw_read_no_pm(rt721->slave, SDW_DP0_INT); + if (ret < 0) + goto io_error; + sdca_cascade = ret & SDW_DP0_SDCA_CASCADE; + + ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1); + if (ret < 0) + goto io_error; + scp_sdca_stat1 = ret & SDW_SCP_SDCA_INTMASK_SDCA_0; + + ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2); + if (ret < 0) + goto io_error; + scp_sdca_stat2 = ret & SDW_SCP_SDCA_INTMASK_SDCA_8; + + stat = scp_sdca_stat1 || scp_sdca_stat2 || sdca_cascade; + + count++; + } while (stat != 0 && count < retry); + + if (stat) + dev_warn(&slave->dev, + "%s scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__, + rt721->scp_sdca_stat1, rt721->scp_sdca_stat2); + ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1); + ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2); + + if (status->sdca_cascade && !rt721->disable_irq) + mod_delayed_work(system_power_efficient_wq, + &rt721->jack_detect_work, msecs_to_jiffies(280)); + + mutex_unlock(&rt721->disable_irq_lock); + + return 0; + +io_error: + mutex_unlock(&rt721->disable_irq_lock); + pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); + return ret; +} + +static const struct sdw_slave_ops rt721_sdca_slave_ops = { + .read_prop = rt721_sdca_read_prop, + .interrupt_callback = rt721_sdca_interrupt_callback, + .update_status = rt721_sdca_update_status, +}; + +static int rt721_sdca_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap, *mbq_regmap; + + /* Regmap Initialization */ + mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt721_sdca_mbq_regmap); + if (IS_ERR(mbq_regmap)) + return PTR_ERR(mbq_regmap); + + regmap = devm_regmap_init_sdw(slave, &rt721_sdca_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return rt721_sdca_init(&slave->dev, regmap, mbq_regmap, slave); +} + +static int rt721_sdca_sdw_remove(struct sdw_slave *slave) +{ + struct rt721_sdca_priv *rt721 = dev_get_drvdata(&slave->dev); + + if (rt721->hw_init) { + cancel_delayed_work_sync(&rt721->jack_detect_work); + cancel_delayed_work_sync(&rt721->jack_btn_check_work); + } + + if (rt721->first_hw_init) + pm_runtime_disable(&slave->dev); + + mutex_destroy(&rt721->calibrate_mutex); + mutex_destroy(&rt721->disable_irq_lock); + + return 0; +} + +static const struct sdw_device_id rt721_sdca_id[] = { + SDW_SLAVE_ENTRY_EXT(0x025d, 0x721, 0x3, 0x1, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, rt721_sdca_id); + +static int __maybe_unused rt721_sdca_dev_suspend(struct device *dev) +{ + struct rt721_sdca_priv *rt721 = dev_get_drvdata(dev); + + if (!rt721->hw_init) + return 0; + + cancel_delayed_work_sync(&rt721->jack_detect_work); + cancel_delayed_work_sync(&rt721->jack_btn_check_work); + + regcache_cache_only(rt721->regmap, true); + regcache_cache_only(rt721->mbq_regmap, true); + + return 0; +} + +static int __maybe_unused rt721_sdca_dev_system_suspend(struct device *dev) +{ + struct rt721_sdca_priv *rt721_sdca = dev_get_drvdata(dev); + struct sdw_slave *slave = dev_to_sdw_dev(dev); + int ret1, ret2; + + if (!rt721_sdca->hw_init) + return 0; + + /* + * prevent new interrupts from being handled after the + * deferred work completes and before the parent disables + * interrupts on the link + */ + mutex_lock(&rt721_sdca->disable_irq_lock); + rt721_sdca->disable_irq = true; + ret1 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK1, + SDW_SCP_SDCA_INTMASK_SDCA_0 | SDW_SCP_SDCA_INTMASK_SDCA_6, 0); + ret2 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK2, + SDW_SCP_SDCA_INTMASK_SDCA_8, 0); + mutex_unlock(&rt721_sdca->disable_irq_lock); + + if (ret1 < 0 || ret2 < 0) { + /* log but don't prevent suspend from happening */ + dev_dbg(&slave->dev, "%s: could not disable SDCA interrupts\n:", __func__); + } + + return rt721_sdca_dev_suspend(dev); +} + +#define RT721_PROBE_TIMEOUT 5000 + +static int __maybe_unused rt721_sdca_dev_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct rt721_sdca_priv *rt721 = dev_get_drvdata(dev); + unsigned long time; + + if (!rt721->first_hw_init) + return 0; + + if (!slave->unattach_request) { + mutex_lock(&rt721->disable_irq_lock); + if (rt721->disable_irq == true) { + sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_6); + sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8); + rt721->disable_irq = false; + } + mutex_unlock(&rt721->disable_irq_lock); + goto regmap_sync; + } + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(RT721_PROBE_TIMEOUT)); + if (!time) { + dev_err(&slave->dev, "Initialization not complete, timed out\n"); + sdw_show_ping_status(slave->bus, true); + + return -ETIMEDOUT; + } + +regmap_sync: + slave->unattach_request = 0; + regcache_cache_only(rt721->regmap, false); + regcache_sync(rt721->regmap); + regcache_cache_only(rt721->mbq_regmap, false); + regcache_sync(rt721->mbq_regmap); + return 0; +} + +static const struct dev_pm_ops rt721_sdca_pm = { + SET_SYSTEM_SLEEP_PM_OPS(rt721_sdca_dev_system_suspend, rt721_sdca_dev_resume) + SET_RUNTIME_PM_OPS(rt721_sdca_dev_suspend, rt721_sdca_dev_resume, NULL) +}; + +static struct sdw_driver rt721_sdca_sdw_driver = { + .driver = { + .name = "rt721-sdca", + .owner = THIS_MODULE, + .pm = &rt721_sdca_pm, + }, + .probe = rt721_sdca_sdw_probe, + .remove = rt721_sdca_sdw_remove, + .ops = &rt721_sdca_slave_ops, + .id_table = rt721_sdca_id, +}; +module_sdw_driver(rt721_sdca_sdw_driver); + +MODULE_DESCRIPTION("ASoC RT721 SDCA SDW driver"); +MODULE_AUTHOR("Jack Yu "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt721-sdca-sdw.h b/sound/soc/codecs/rt721-sdca-sdw.h new file mode 100644 index 000000000000..214b31b82583 --- /dev/null +++ b/sound/soc/codecs/rt721-sdca-sdw.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * rt721-sdca-sdw.h -- RT721 SDCA ALSA SoC audio driver header + * + * Copyright(c) 2024 Realtek Semiconductor Corp. + */ + +#ifndef __RT721_SDW_H__ +#define __RT721_SDW_H__ + +#include +#include + +static const struct reg_default rt721_sdca_reg_defaults[] = { + { 0x202d, 0x00 }, + { 0x2f01, 0x00 }, + { 0x2f02, 0x09 }, + { 0x2f03, 0x08 }, + { 0x2f04, 0x00 }, + { 0x2f05, 0x0e }, + { 0x2f06, 0x01 }, + { 0x2f09, 0x00 }, + { 0x2f0a, 0x00 }, + { 0x2f35, 0x00 }, + { 0x2f50, 0xf0 }, + { 0x2f58, 0x07 }, + { 0x2f59, 0x07 }, + { 0x2f5a, 0x00 }, + { 0x2f5b, 0x07 }, + { 0x2f5c, 0x27 }, + { 0x2f5d, 0x07 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_CS01, + RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_CS11, + RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE12, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE40, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, + RT721_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, + RT721_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, + RT721_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, + RT721_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, + RT721_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, + RT721_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, + RT721_SDCA_CTL_FU_MUTE, CH_03), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, + RT721_SDCA_CTL_FU_MUTE, CH_04), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_CS1F, + RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_IT26, + RT721_SDCA_CTL_VENDOR_DEF, 0), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_PDE2A, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_CS31, + RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, + RT721_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, + RT721_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_OT23, + RT721_SDCA_CTL_VENDOR_DEF, 0), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23, + RT721_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23, + RT721_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_FU55, + RT721_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_FU55, + RT721_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, +}; + +static const struct reg_default rt721_sdca_mbq_defaults[] = { + { 0x0900007, 0xc004 }, + { 0x2000001, 0x0000 }, + { 0x2000002, 0x0000 }, + { 0x2000003, 0x0000 }, + { 0x2000013, 0x8001 }, + { 0x200003c, 0x0000 }, + { 0x2000046, 0x3400 }, + { 0x5f00044, 0x6040 }, + { 0x5f00045, 0x3333 }, + { 0x5f00048, 0x0000 }, + { 0x6100005, 0x0005 }, + { 0x6100006, 0x0000 }, + { 0x610000d, 0x0051 }, + { 0x6100010, 0x0180 }, + { 0x6100011, 0x0000 }, + { 0x6100013, 0x0000 }, + { 0x6100015, 0x0000 }, + { 0x6100017, 0x8049 }, + { 0x6100025, 0x1000 }, + { 0x6100029, 0x0809 }, + { 0x610002c, 0x2828 }, + { 0x610002d, 0x2929 }, + { 0x610002e, 0x3529 }, + { 0x610002f, 0x2901 }, + { 0x6100053, 0x2630 }, + { 0x6100054, 0x2a2a }, + { 0x6100055, 0x152f }, + { 0x6100057, 0x2200 }, + { 0x610005a, 0x2a4b }, + { 0x610005b, 0x2a00 }, + { 0x610006a, 0x0102 }, + { 0x610006d, 0x0102 }, + { 0x6100092, 0x4f61 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, RT721_SDCA_CTL_FU_VOLUME, + CH_L), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, RT721_SDCA_CTL_FU_VOLUME, + CH_R), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, RT721_SDCA_CTL_FU_VOLUME, + CH_L), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, RT721_SDCA_CTL_FU_VOLUME, + CH_R), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44, RT721_SDCA_CTL_FU_CH_GAIN, + CH_L), 0xfe00 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44, RT721_SDCA_CTL_FU_CH_GAIN, + CH_R), 0xfe00 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_FU15, RT721_SDCA_CTL_FU_CH_GAIN, CH_01), + 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_FU15, RT721_SDCA_CTL_FU_CH_GAIN, CH_02), + 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_FU15, RT721_SDCA_CTL_FU_CH_GAIN, CH_03), + 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_FU15, RT721_SDCA_CTL_FU_CH_GAIN, CH_04), + 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME, + CH_01), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME, + CH_02), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME, + CH_03), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME, + CH_04), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, RT721_SDCA_CTL_FU_VOLUME, CH_L), + 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, RT721_SDCA_CTL_FU_VOLUME, CH_R), + 0x0000 }, +}; + +#endif /* __RT721_SDW_H__ */ diff --git a/sound/soc/codecs/rt721-sdca.c b/sound/soc/codecs/rt721-sdca.c new file mode 100644 index 000000000000..36056cb7a3ca --- /dev/null +++ b/sound/soc/codecs/rt721-sdca.c @@ -0,0 +1,1547 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt721-sdca.c -- rt721 SDCA ALSA SoC audio driver +// +// Copyright(c) 2024 Realtek Semiconductor Corp. +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rt721-sdca.h" +#include "rt-sdw-common.h" + +static void rt721_sdca_jack_detect_handler(struct work_struct *work) +{ + struct rt721_sdca_priv *rt721 = + container_of(work, struct rt721_sdca_priv, jack_detect_work.work); + int btn_type = 0, ret; + + if (!rt721->hs_jack) + return; + + if (!rt721->component->card || !rt721->component->card->instantiated) + return; + + /* SDW_SCP_SDCA_INT_SDCA_6 is used for jack detection */ + if (rt721->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_6) { + rt721->jack_type = rt_sdca_headset_detect(rt721->regmap, + RT721_SDCA_ENT_GE49); + if (ret < 0) + return; + } + + /* SDW_SCP_SDCA_INT_SDCA_8 is used for button detection */ + if (rt721->scp_sdca_stat2 & SDW_SCP_SDCA_INT_SDCA_8) + btn_type = rt_sdca_button_detect(rt721->regmap, + RT721_SDCA_ENT_HID01, RT721_BUF_ADDR_HID1, + RT721_SDCA_HID_ID); + + if (rt721->jack_type == 0) + btn_type = 0; + + dev_dbg(&rt721->slave->dev, + "in %s, jack_type=%d\n", __func__, rt721->jack_type); + dev_dbg(&rt721->slave->dev, + "in %s, btn_type=0x%x\n", __func__, btn_type); + dev_dbg(&rt721->slave->dev, + "in %s, scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__, + rt721->scp_sdca_stat1, rt721->scp_sdca_stat2); + + snd_soc_jack_report(rt721->hs_jack, rt721->jack_type | btn_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + + if (btn_type) { + /* button released */ + snd_soc_jack_report(rt721->hs_jack, rt721->jack_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + + mod_delayed_work(system_power_efficient_wq, + &rt721->jack_btn_check_work, msecs_to_jiffies(200)); + } +} + +static void rt721_sdca_btn_check_handler(struct work_struct *work) +{ + struct rt721_sdca_priv *rt721 = + container_of(work, struct rt721_sdca_priv, jack_btn_check_work.work); + int btn_type = 0, ret, idx; + unsigned int det_mode, offset, val; + unsigned char buf[3]; + + ret = regmap_read(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49, + RT721_SDCA_CTL_DETECTED_MODE, 0), &det_mode); + if (ret < 0) + goto io_error; + + /* pin attached */ + if (det_mode) { + /* read UMP message offset */ + ret = regmap_read(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_HID, RT721_SDCA_ENT_HID01, + RT721_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), &offset); + if (ret < 0) + goto io_error; + + for (idx = 0; idx < sizeof(buf); idx++) { + ret = regmap_read(rt721->regmap, + RT721_BUF_ADDR_HID1 + offset + idx, &val); + if (ret < 0) + goto io_error; + buf[idx] = val & 0xff; + } + /* Report ID for HID1 */ + if (buf[0] == 0x11) + btn_type = rt_sdca_btn_type(&buf[1]); + } else + rt721->jack_type = 0; + + dev_dbg(&rt721->slave->dev, "%s, btn_type=0x%x\n", __func__, btn_type); + snd_soc_jack_report(rt721->hs_jack, rt721->jack_type | btn_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + + if (btn_type) { + /* button released */ + snd_soc_jack_report(rt721->hs_jack, rt721->jack_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + + mod_delayed_work(system_power_efficient_wq, + &rt721->jack_btn_check_work, msecs_to_jiffies(200)); + } + + return; + +io_error: + pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); +} + +static void rt721_sdca_dmic_preset(struct rt721_sdca_priv *rt721) +{ + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_MISC_POWER_CTL31, 0x8000); + rt_sdca_index_write(rt721->mbq_regmap, RT721_ANA_POW_PART, + RT721_VREF1_HV_CTRL1, 0xe000); + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_MISC_POWER_CTL31, 0x8007); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_ENT_FLOAT_CTL9, 0x2a2a); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_ENT_FLOAT_CTL10, 0x2a00); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_ENT_FLOAT_CTL6, 0x2a2a); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_ENT_FLOAT_CTL5, 0x2626); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_ENT_FLOAT_CTL8, 0x1e00); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_ENT_FLOAT_CTL7, 0x1515); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_CH_FLOAT_CTL3, 0x0304); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_CH_FLOAT_CTL4, 0x0304); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_HDA_LEGACY_CTL1, 0x0000); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_IT26, + RT721_SDCA_CTL_VENDOR_DEF, 0), 0x01); + regmap_write(rt721->mbq_regmap, 0x5910009, 0x2e01); + rt_sdca_index_write(rt721->mbq_regmap, RT721_RC_CALIB_CTRL, + RT721_RC_CALIB_CTRL0, 0x0b00); + rt_sdca_index_write(rt721->mbq_regmap, RT721_RC_CALIB_CTRL, + RT721_RC_CALIB_CTRL0, 0x0b40); + regmap_write(rt721->regmap, 0x2f5c, 0x25); +} + +static void rt721_sdca_amp_preset(struct rt721_sdca_priv *rt721) +{ + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_MISC_POWER_CTL31, 0x8000); + rt_sdca_index_write(rt721->mbq_regmap, RT721_ANA_POW_PART, + RT721_VREF1_HV_CTRL1, 0xe000); + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_MISC_POWER_CTL31, 0x8007); + regmap_write(rt721->mbq_regmap, 0x5810000, 0x6420); + regmap_write(rt721->mbq_regmap, 0x5810000, 0x6421); + regmap_write(rt721->mbq_regmap, 0x5810000, 0xe421); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_CH_FLOAT_CTL6, 0x5561); + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_REG, + RT721_GPIO_PAD_CTRL5, 0x8003); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_OT23, + RT721_SDCA_CTL_VENDOR_DEF, 0), 0x04); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23, + RT721_SDCA_CTL_FU_MUTE, CH_01), 0x00); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23, + RT721_SDCA_CTL_FU_MUTE, CH_02), 0x00); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_FU55, + RT721_SDCA_CTL_FU_MUTE, CH_01), 0x00); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_FU55, + RT721_SDCA_CTL_FU_MUTE, CH_02), 0x00); +} + +static void rt721_sdca_jack_preset(struct rt721_sdca_priv *rt721) +{ + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_MISC_POWER_CTL31, 0x8000); + rt_sdca_index_write(rt721->mbq_regmap, RT721_ANA_POW_PART, + RT721_VREF1_HV_CTRL1, 0xe000); + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_MISC_POWER_CTL31, 0x8007); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_GE_REL_CTRL1, 0x8011); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_UMP_HID_CTRL3, 0xcf00); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_UMP_HID_CTRL4, 0x000f); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_UMP_HID_CTRL1, 0x1100); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_UMP_HID_CTRL5, 0x0c12); + rt_sdca_index_write(rt721->mbq_regmap, RT721_JD_CTRL, + RT721_JD_1PIN_GAT_CTRL2, 0xc002); + rt_sdca_index_write(rt721->mbq_regmap, RT721_RC_CALIB_CTRL, + RT721_RC_CALIB_CTRL0, 0x0b00); + rt_sdca_index_write(rt721->mbq_regmap, RT721_RC_CALIB_CTRL, + RT721_RC_CALIB_CTRL0, 0x0b40); + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_UAJ_TOP_TCON14, 0x3333); + regmap_write(rt721->mbq_regmap, 0x5810035, 0x0036); + regmap_write(rt721->mbq_regmap, 0x5810030, 0xee00); + rt_sdca_index_write(rt721->mbq_regmap, RT721_CAP_PORT_CTRL, + RT721_HP_AMP_2CH_CAL1, 0x0140); + regmap_write(rt721->mbq_regmap, 0x5810000, 0x0021); + regmap_write(rt721->mbq_regmap, 0x5810000, 0x8021); + rt_sdca_index_write(rt721->mbq_regmap, RT721_CAP_PORT_CTRL, + RT721_HP_AMP_2CH_CAL18, 0x5522); + regmap_write(rt721->mbq_regmap, 0x5b10007, 0x2000); + regmap_write(rt721->mbq_regmap, 0x5B10017, 0x1b0f); + rt_sdca_index_write(rt721->mbq_regmap, RT721_CBJ_CTRL, + RT721_CBJ_A0_GAT_CTRL1, 0x2a02); + rt_sdca_index_write(rt721->mbq_regmap, RT721_CAP_PORT_CTRL, + RT721_HP_AMP_2CH_CAL4, 0xa105); + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_UAJ_TOP_TCON14, 0x3b33); + regmap_write(rt721->mbq_regmap, 0x310400, 0x3023); + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_UAJ_TOP_TCON14, 0x3f33); + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_UAJ_TOP_TCON13, 0x6048); + regmap_write(rt721->mbq_regmap, 0x310401, 0x3000); + regmap_write(rt721->mbq_regmap, 0x310402, 0x1b00); + regmap_write(rt721->mbq_regmap, 0x310300, 0x000f); + regmap_write(rt721->mbq_regmap, 0x310301, 0x3000); + regmap_write(rt721->mbq_regmap, 0x310302, 0x1b00); + rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL, + RT721_UAJ_TOP_TCON17, 0x0008); + rt_sdca_index_write(rt721->mbq_regmap, RT721_DAC_CTRL, + RT721_DAC_2CH_CTRL3, 0x55ff); + rt_sdca_index_write(rt721->mbq_regmap, RT721_DAC_CTRL, + RT721_DAC_2CH_CTRL4, 0xcc00); + rt_sdca_index_write(rt721->mbq_regmap, RT721_ANA_POW_PART, + RT721_MBIAS_LV_CTRL2, 0x6677); + rt_sdca_index_write(rt721->mbq_regmap, RT721_ANA_POW_PART, + RT721_VREF2_LV_CTRL1, 0x7600); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_ENT_FLOAT_CTL2, 0x1234); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_ENT_FLOAT_CTL3, 0x3512); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_ENT_FLOAT_CTL1, 0x4040); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_ENT_FLOAT_CTL4, 0x1201); + regmap_write(rt721->regmap, 0x2f58, 0x07); +} + +static void rt721_sdca_jack_init(struct rt721_sdca_priv *rt721) +{ + mutex_lock(&rt721->calibrate_mutex); + if (rt721->hs_jack) { + sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK1, + SDW_SCP_SDCA_INTMASK_SDCA_0 | SDW_SCP_SDCA_INTMASK_SDCA_6); + sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK2, + SDW_SCP_SDCA_INTMASK_SDCA_8); + dev_dbg(&rt721->slave->dev, "in %s enable\n", __func__); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_HDA_LEGACY_UAJ_CTL, 0x036E); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XU03, + RT721_SDCA_CTL_SELECTED_MODE, 0), 0); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XU0D, + RT721_SDCA_CTL_SELECTED_MODE, 0), 0); + rt_sdca_index_update_bits(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_GE_REL_CTRL1, 0x4000, 0x4000); + } + mutex_unlock(&rt721->calibrate_mutex); +} + +static int rt721_sdca_set_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *hs_jack, void *data) +{ + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + int ret; + + rt721->hs_jack = hs_jack; + + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); + return 0; + } + + rt721_sdca_jack_init(rt721); + + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + + return 0; +} + +/* For SDCA control DAC/ADC Gain */ +static int rt721_sdca_set_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + unsigned int read_l, read_r, gain_l_val, gain_r_val; + unsigned int adc_vol_flag = 0, changed = 0; + unsigned int lvalue, rvalue; + const unsigned int interval_offset = 0xc0; + const unsigned int tendA = 0x200; + const unsigned int tendB = 0xa00; + + if (strstr(ucontrol->id.name, "FU1E Capture Volume") || + strstr(ucontrol->id.name, "FU0F Capture Volume")) + adc_vol_flag = 1; + + regmap_read(rt721->mbq_regmap, mc->reg, &lvalue); + regmap_read(rt721->mbq_regmap, mc->rreg, &rvalue); + + /* L Channel */ + gain_l_val = ucontrol->value.integer.value[0]; + if (gain_l_val > mc->max) + gain_l_val = mc->max; + + if (mc->shift == 8) { + /* boost gain */ + gain_l_val = gain_l_val * tendB; + } else if (mc->shift == 1) { + /* FU33 boost gain */ + if (gain_l_val == 0) + gain_l_val = 0x8000; + else + gain_l_val = (gain_l_val - 1) * tendA; + } else { + /* ADC/DAC gain */ + if (adc_vol_flag) + gain_l_val = 0x1e00 - ((mc->max - gain_l_val) * interval_offset); + else + gain_l_val = 0 - ((mc->max - gain_l_val) * interval_offset); + gain_l_val &= 0xffff; + } + + /* R Channel */ + gain_r_val = ucontrol->value.integer.value[1]; + if (gain_r_val > mc->max) + gain_r_val = mc->max; + + if (mc->shift == 8) { + /* boost gain */ + gain_r_val = gain_r_val * tendB; + } else if (mc->shift == 1) { + /* FU33 boost gain */ + if (gain_r_val == 0) + gain_r_val = 0x8000; + else + gain_r_val = (gain_r_val - 1) * tendA; + } else { + /* ADC/DAC gain */ + if (adc_vol_flag) + gain_r_val = 0x1e00 - ((mc->max - gain_r_val) * interval_offset); + else + gain_r_val = 0 - ((mc->max - gain_r_val) * interval_offset); + gain_r_val &= 0xffff; + } + + if (lvalue != gain_l_val || rvalue != gain_r_val) + changed = 1; + else + return 0; + + /* Lch*/ + regmap_write(rt721->mbq_regmap, mc->reg, gain_l_val); + + /* Rch */ + regmap_write(rt721->mbq_regmap, mc->rreg, gain_r_val); + + regmap_read(rt721->mbq_regmap, mc->reg, &read_l); + regmap_read(rt721->mbq_regmap, mc->rreg, &read_r); + if (read_r == gain_r_val && read_l == gain_l_val) + return changed; + + return -EIO; +} + +static int rt721_sdca_set_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + unsigned int read_l, read_r, ctl_l = 0, ctl_r = 0; + unsigned int adc_vol_flag = 0; + const unsigned int interval_offset = 0xc0; + const unsigned int tendB = 0xa00; + + if (strstr(ucontrol->id.name, "FU1E Capture Volume") || + strstr(ucontrol->id.name, "FU0F Capture Volume")) + adc_vol_flag = 1; + + regmap_read(rt721->mbq_regmap, mc->reg, &read_l); + regmap_read(rt721->mbq_regmap, mc->rreg, &read_r); + + if (mc->shift == 8) /* boost gain */ + ctl_l = read_l / tendB; + else { + if (adc_vol_flag) + ctl_l = mc->max - (((0x1e00 - read_l) & 0xffff) / interval_offset); + else + ctl_l = mc->max - (((0 - read_l) & 0xffff) / interval_offset); + } + + if (read_l != read_r) { + if (mc->shift == 8) /* boost gain */ + ctl_r = read_r / tendB; + else { /* ADC/DAC gain */ + if (adc_vol_flag) + ctl_r = mc->max - (((0x1e00 - read_r) & 0xffff) / interval_offset); + else + ctl_r = mc->max - (((0 - read_r) & 0xffff) / interval_offset); + } + } else { + ctl_r = ctl_l; + } + + ucontrol->value.integer.value[0] = ctl_l; + ucontrol->value.integer.value[1] = ctl_r; + + return 0; +} + +static int rt721_sdca_set_fu1e_capture_ctl(struct rt721_sdca_priv *rt721) +{ + int err, i; + unsigned int ch_mute; + + for (i = 0; i < ARRAY_SIZE(rt721->fu1e_mixer_mute); i++) { + ch_mute = rt721->fu1e_dapm_mute || rt721->fu1e_mixer_mute[i]; + err = regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, + RT721_SDCA_CTL_FU_MUTE, CH_01) + i, ch_mute); + if (err < 0) + return err; + } + + return 0; +} + +static int rt721_sdca_fu1e_capture_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + struct rt721_sdca_dmic_kctrl_priv *p = + (struct rt721_sdca_dmic_kctrl_priv *)kcontrol->private_value; + unsigned int i; + + for (i = 0; i < p->count; i++) + ucontrol->value.integer.value[i] = !rt721->fu1e_mixer_mute[i]; + + return 0; +} + +static int rt721_sdca_fu1e_capture_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + struct rt721_sdca_dmic_kctrl_priv *p = + (struct rt721_sdca_dmic_kctrl_priv *)kcontrol->private_value; + int err, changed = 0, i; + + for (i = 0; i < p->count; i++) { + if (rt721->fu1e_mixer_mute[i] != !ucontrol->value.integer.value[i]) + changed = 1; + rt721->fu1e_mixer_mute[i] = !ucontrol->value.integer.value[i]; + } + + err = rt721_sdca_set_fu1e_capture_ctl(rt721); + if (err < 0) + return err; + + return changed; +} + +static int rt721_sdca_set_fu0f_capture_ctl(struct rt721_sdca_priv *rt721) +{ + int err; + unsigned int ch_l, ch_r; + + ch_l = (rt721->fu0f_dapm_mute || rt721->fu0f_mixer_l_mute) ? 0x01 : 0x00; + ch_r = (rt721->fu0f_dapm_mute || rt721->fu0f_mixer_r_mute) ? 0x01 : 0x00; + + err = regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, + RT721_SDCA_CTL_FU_MUTE, CH_L), ch_l); + if (err < 0) + return err; + + err = regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, + RT721_SDCA_CTL_FU_MUTE, CH_R), ch_r); + if (err < 0) + return err; + + return 0; +} + +static int rt721_sdca_fu0f_capture_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = !rt721->fu0f_mixer_l_mute; + ucontrol->value.integer.value[1] = !rt721->fu0f_mixer_r_mute; + return 0; +} + +static int rt721_sdca_fu0f_capture_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + int err, changed = 0; + + if (rt721->fu0f_mixer_l_mute != !ucontrol->value.integer.value[0] || + rt721->fu0f_mixer_r_mute != !ucontrol->value.integer.value[1]) + changed = 1; + + rt721->fu0f_mixer_l_mute = !ucontrol->value.integer.value[0]; + rt721->fu0f_mixer_r_mute = !ucontrol->value.integer.value[1]; + err = rt721_sdca_set_fu0f_capture_ctl(rt721); + if (err < 0) + return err; + + return changed; +} + +static int rt721_sdca_fu_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct rt721_sdca_dmic_kctrl_priv *p = + (struct rt721_sdca_dmic_kctrl_priv *)kcontrol->private_value; + + if (p->max == 1) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = p->count; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = p->max; + return 0; +} + +static int rt721_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + struct rt721_sdca_dmic_kctrl_priv *p = + (struct rt721_sdca_dmic_kctrl_priv *)kcontrol->private_value; + unsigned int boost_step = 0x0a00; + unsigned int vol_max = 0x1e00; + unsigned int regvalue, ctl, i; + unsigned int adc_vol_flag = 0; + const unsigned int interval_offset = 0xc0; + + if (strstr(ucontrol->id.name, "FU1E Capture Volume")) + adc_vol_flag = 1; + + /* check all channels */ + for (i = 0; i < p->count; i++) { + regmap_read(rt721->mbq_regmap, p->reg_base + i, ®value); + + if (!adc_vol_flag) /* boost gain */ + ctl = regvalue / boost_step; + else { /* ADC gain */ + if (adc_vol_flag) + ctl = p->max - (((vol_max - regvalue) & 0xffff) / interval_offset); + else + ctl = p->max - (((0 - regvalue) & 0xffff) / interval_offset); + } + + ucontrol->value.integer.value[i] = ctl; + } + + return 0; +} + +static int rt721_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt721_sdca_dmic_kctrl_priv *p = + (struct rt721_sdca_dmic_kctrl_priv *)kcontrol->private_value; + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + unsigned int boost_step = 0x0a00; + unsigned int vol_max = 0x1e00; + unsigned int gain_val[4]; + unsigned int i, adc_vol_flag = 0, changed = 0; + unsigned int regvalue[4]; + const unsigned int interval_offset = 0xc0; + int err; + + if (strstr(ucontrol->id.name, "FU1E Capture Volume")) + adc_vol_flag = 1; + + /* check all channels */ + for (i = 0; i < p->count; i++) { + regmap_read(rt721->mbq_regmap, p->reg_base + i, ®value[i]); + + gain_val[i] = ucontrol->value.integer.value[i]; + if (gain_val[i] > p->max) + gain_val[i] = p->max; + + if (!adc_vol_flag) /* boost gain */ + gain_val[i] = gain_val[i] * boost_step; + else { /* ADC gain */ + gain_val[i] = vol_max - ((p->max - gain_val[i]) * interval_offset); + gain_val[i] &= 0xffff; + } + + if (regvalue[i] != gain_val[i]) + changed = 1; + } + + if (!changed) + return 0; + + for (i = 0; i < p->count; i++) { + err = regmap_write(rt721->mbq_regmap, p->reg_base + i, gain_val[i]); + if (err < 0) + dev_err(&rt721->slave->dev, "%#08x can't be set\n", p->reg_base + i); + } + + return changed; +} + +static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0); +static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -1725, 75, 0); +static const DECLARE_TLV_DB_SCALE(boost_vol_tlv, 0, 1000, 0); +static const DECLARE_TLV_DB_SCALE(mic2_boost_vol_tlv, -200, 200, 0); + +static const struct snd_kcontrol_new rt721_sdca_controls[] = { + /* Headphone playback settings */ + SOC_DOUBLE_R_EXT_TLV("FU05 Playback Volume", + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, + RT721_SDCA_CTL_FU_VOLUME, CH_L), + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, + RT721_SDCA_CTL_FU_VOLUME, CH_R), 0, 0x57, 0, + rt721_sdca_set_gain_get, rt721_sdca_set_gain_put, out_vol_tlv), + /* Headset mic capture settings */ + SOC_DOUBLE_EXT("FU0F Capture Switch", SND_SOC_NOPM, 0, 1, 1, 0, + rt721_sdca_fu0f_capture_get, rt721_sdca_fu0f_capture_put), + SOC_DOUBLE_R_EXT_TLV("FU0F Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, + RT721_SDCA_CTL_FU_VOLUME, CH_L), + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, + RT721_SDCA_CTL_FU_VOLUME, CH_R), 0, 0x3f, 0, + rt721_sdca_set_gain_get, rt721_sdca_set_gain_put, mic_vol_tlv), + SOC_DOUBLE_R_EXT_TLV("FU33 Boost Volume", + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44, + RT721_SDCA_CTL_FU_CH_GAIN, CH_L), + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44, + RT721_SDCA_CTL_FU_CH_GAIN, CH_R), 1, 0x15, 0, + rt721_sdca_set_gain_get, rt721_sdca_set_gain_put, mic2_boost_vol_tlv), + /* AMP playback settings */ + SOC_DOUBLE_R_EXT_TLV("FU06 Playback Volume", + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, + RT721_SDCA_CTL_FU_VOLUME, CH_L), + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, + RT721_SDCA_CTL_FU_VOLUME, CH_R), 0, 0x57, 0, + rt721_sdca_set_gain_get, rt721_sdca_set_gain_put, out_vol_tlv), + /* DMIC capture settings */ + RT_SDCA_FU_CTRL("FU1E Capture Switch", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, + RT721_SDCA_CTL_FU_MUTE, CH_01), 1, 1, 4, rt721_sdca_fu_info, + rt721_sdca_fu1e_capture_get, rt721_sdca_fu1e_capture_put), + RT_SDCA_EXT_TLV("FU1E Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, + RT721_SDCA_CTL_FU_VOLUME, CH_01), + rt721_sdca_dmic_set_gain_get, rt721_sdca_dmic_set_gain_put, + 4, 0x3f, mic_vol_tlv, rt721_sdca_fu_info), + RT_SDCA_EXT_TLV("FU15 Boost Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_FU15, + RT721_SDCA_CTL_FU_CH_GAIN, CH_01), + rt721_sdca_dmic_set_gain_get, rt721_sdca_dmic_set_gain_put, + 4, 3, boost_vol_tlv, rt721_sdca_fu_info), +}; + +static int rt721_sdca_adc_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + unsigned int val = 0, mask_sft, mask; + + if (strstr(ucontrol->id.name, "ADC 09 Mux")) { + mask_sft = 12; + mask = 0x7; + } else if (strstr(ucontrol->id.name, "ADC 08 R Mux")) { + mask_sft = 10; + mask = 0x3; + } else if (strstr(ucontrol->id.name, "ADC 08 L Mux")) { + mask_sft = 8; + mask = 0x3; + } else if (strstr(ucontrol->id.name, "ADC 10 R Mux")) { + mask_sft = 6; + mask = 0x3; + } else if (strstr(ucontrol->id.name, "ADC 10 L Mux")) { + mask_sft = 4; + mask = 0x3; + } else if (strstr(ucontrol->id.name, "ADC 07 R Mux")) { + mask_sft = 2; + mask = 0x3; + } else if (strstr(ucontrol->id.name, "ADC 07 L Mux")) { + mask_sft = 0; + mask = 0x3; + } else + return -EINVAL; + + rt_sdca_index_read(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_HDA_LEGACY_MUX_CTL0, &val); + + ucontrol->value.enumerated.item[0] = (val >> mask_sft) & mask; + + return 0; +} + +static int rt721_sdca_adc_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int *item = ucontrol->value.enumerated.item; + unsigned int val, val2 = 0, change, mask_sft, mask; + unsigned int check; + + if (item[0] >= e->items) + return -EINVAL; + + if (strstr(ucontrol->id.name, "ADC 09 Mux")) { + mask_sft = 12; + mask = 0x7; + } else if (strstr(ucontrol->id.name, "ADC 08 R Mux")) { + mask_sft = 10; + mask = 0x3; + } else if (strstr(ucontrol->id.name, "ADC 08 L Mux")) { + mask_sft = 8; + mask = 0x3; + } else if (strstr(ucontrol->id.name, "ADC 10 R Mux")) { + mask_sft = 6; + mask = 0x3; + } else if (strstr(ucontrol->id.name, "ADC 10 L Mux")) { + mask_sft = 4; + mask = 0x3; + } else if (strstr(ucontrol->id.name, "ADC 07 R Mux")) { + mask_sft = 2; + mask = 0x3; + } else if (strstr(ucontrol->id.name, "ADC 07 L Mux")) { + mask_sft = 0; + mask = 0x3; + } else + return -EINVAL; + + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; + rt_sdca_index_read(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_HDA_LEGACY_MUX_CTL0, &val2); + + if (strstr(ucontrol->id.name, "ADC 09 Mux")) + val2 = (val2 >> mask_sft) & 0x7; + else + val2 = (val2 >> mask_sft) & 0x3; + + if (val == val2) + change = 0; + else + change = 1; + + if (change) { + rt_sdca_index_read(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_HDA_LEGACY_MUX_CTL0, &check); + rt_sdca_index_update_bits(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_HDA_LEGACY_MUX_CTL0, mask << mask_sft, + val << mask_sft); + } + + snd_soc_dapm_mux_update_power(dapm, kcontrol, + item[0], e, NULL); + + return change; +} + +static const char * const adc09_mux_text[] = { + "MIC2", + "LINE1", + "LINE2", +}; +static const char * const adc07_10_mux_text[] = { + "DMIC1 RE", + "DMIC1 FE", + "DMIC2 RE", + "DMIC2 FE", +}; + +static SOC_ENUM_SINGLE_DECL( + rt721_adc09_enum, SND_SOC_NOPM, 0, adc09_mux_text); +static SOC_ENUM_SINGLE_DECL( + rt721_dmic_enum, SND_SOC_NOPM, 0, adc07_10_mux_text); + +static const struct snd_kcontrol_new rt721_sdca_adc09_mux = + SOC_DAPM_ENUM_EXT("ADC 09 Mux", rt721_adc09_enum, + rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put); +static const struct snd_kcontrol_new rt721_sdca_adc08_r_mux = + SOC_DAPM_ENUM_EXT("ADC 08 R Mux", rt721_dmic_enum, + rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put); +static const struct snd_kcontrol_new rt721_sdca_adc08_l_mux = + SOC_DAPM_ENUM_EXT("ADC 08 L Mux", rt721_dmic_enum, + rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put); +static const struct snd_kcontrol_new rt721_sdca_adc10_r_mux = + SOC_DAPM_ENUM_EXT("ADC 10 R Mux", rt721_dmic_enum, + rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put); +static const struct snd_kcontrol_new rt721_sdca_adc10_l_mux = + SOC_DAPM_ENUM_EXT("ADC 10 L Mux", rt721_dmic_enum, + rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put); +static const struct snd_kcontrol_new rt721_sdca_adc07_r_mux = + SOC_DAPM_ENUM_EXT("ADC 07 R Mux", rt721_dmic_enum, + rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put); +static const struct snd_kcontrol_new rt721_sdca_adc07_l_mux = + SOC_DAPM_ENUM_EXT("ADC 07 L Mux", rt721_dmic_enum, + rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put); + + +static int rt721_sdca_fu42_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + unsigned char unmute = 0x0, mute = 0x1; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + msleep(100); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, + RT721_SDCA_CTL_FU_MUTE, CH_L), unmute); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, + RT721_SDCA_CTL_FU_MUTE, CH_R), unmute); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, + RT721_SDCA_CTL_FU_MUTE, CH_L), mute); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, + RT721_SDCA_CTL_FU_MUTE, CH_R), mute); + break; + } + return 0; +} + +static int rt721_sdca_fu21_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + unsigned char unmute = 0x0, mute = 0x1; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, + RT721_SDCA_CTL_FU_MUTE, CH_L), unmute); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, + RT721_SDCA_CTL_FU_MUTE, CH_R), unmute); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, + RT721_SDCA_CTL_FU_MUTE, CH_L), mute); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, + RT721_SDCA_CTL_FU_MUTE, CH_R), mute); + break; + } + return 0; +} + +static int rt721_sdca_fu23_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + unsigned char unmute = 0x0, mute = 0x1; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23, + RT721_SDCA_CTL_FU_MUTE, CH_L), unmute); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23, + RT721_SDCA_CTL_FU_MUTE, CH_R), unmute); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23, + RT721_SDCA_CTL_FU_MUTE, CH_L), mute); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23, + RT721_SDCA_CTL_FU_MUTE, CH_R), mute); + break; + } + return 0; +} + +static int rt721_sdca_fu113_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + rt721->fu1e_dapm_mute = false; + rt721_sdca_set_fu1e_capture_ctl(rt721); + break; + case SND_SOC_DAPM_PRE_PMD: + rt721->fu1e_dapm_mute = true; + rt721_sdca_set_fu1e_capture_ctl(rt721); + break; + } + return 0; +} + +static int rt721_sdca_fu36_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + rt721->fu0f_dapm_mute = false; + rt721_sdca_set_fu0f_capture_ctl(rt721); + break; + case SND_SOC_DAPM_PRE_PMD: + rt721->fu0f_dapm_mute = true; + rt721_sdca_set_fu0f_capture_ctl(rt721); + break; + } + return 0; +} + +static int rt721_sdca_pde47_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE40, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE40, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps3); + break; + } + return 0; +} + +static int rt721_sdca_pde41_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE41, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE41, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps3); + break; + } + return 0; +} + +static int rt721_sdca_pde11_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_PDE2A, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_PDE2A, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps3); + break; + } + return 0; +} + +static int rt721_sdca_pde34_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE12, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE12, + RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps3); + break; + } + return 0; +} + +static const struct snd_soc_dapm_widget rt721_sdca_dapm_widgets[] = { + SND_SOC_DAPM_OUTPUT("HP"), + SND_SOC_DAPM_OUTPUT("SPK"), + SND_SOC_DAPM_INPUT("MIC2"), + SND_SOC_DAPM_INPUT("LINE1"), + SND_SOC_DAPM_INPUT("LINE2"), + SND_SOC_DAPM_INPUT("DMIC1_2"), + SND_SOC_DAPM_INPUT("DMIC3_4"), + + SND_SOC_DAPM_SUPPLY("PDE 41", SND_SOC_NOPM, 0, 0, + rt721_sdca_pde41_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY("PDE 47", SND_SOC_NOPM, 0, 0, + rt721_sdca_pde47_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY("PDE 11", SND_SOC_NOPM, 0, 0, + rt721_sdca_pde11_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY("PDE 34", SND_SOC_NOPM, 0, 0, + rt721_sdca_pde34_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_DAC_E("FU 21", NULL, SND_SOC_NOPM, 0, 0, + rt721_sdca_fu21_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_DAC_E("FU 23", NULL, SND_SOC_NOPM, 0, 0, + rt721_sdca_fu23_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_DAC_E("FU 42", NULL, SND_SOC_NOPM, 0, 0, + rt721_sdca_fu42_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_ADC_E("FU 36", NULL, SND_SOC_NOPM, 0, 0, + rt721_sdca_fu36_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_ADC_E("FU 113", NULL, SND_SOC_NOPM, 0, 0, + rt721_sdca_fu113_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_MUX("ADC 09 Mux", SND_SOC_NOPM, 0, 0, + &rt721_sdca_adc09_mux), + SND_SOC_DAPM_MUX("ADC 08 R Mux", SND_SOC_NOPM, 0, 0, + &rt721_sdca_adc08_r_mux), + SND_SOC_DAPM_MUX("ADC 08 L Mux", SND_SOC_NOPM, 0, 0, + &rt721_sdca_adc08_l_mux), + SND_SOC_DAPM_MUX("ADC 10 R Mux", SND_SOC_NOPM, 0, 0, + &rt721_sdca_adc10_r_mux), + SND_SOC_DAPM_MUX("ADC 10 L Mux", SND_SOC_NOPM, 0, 0, + &rt721_sdca_adc10_l_mux), + SND_SOC_DAPM_MUX("ADC 07 R Mux", SND_SOC_NOPM, 0, 0, + &rt721_sdca_adc07_r_mux), + SND_SOC_DAPM_MUX("ADC 07 L Mux", SND_SOC_NOPM, 0, 0, + &rt721_sdca_adc07_l_mux), + + SND_SOC_DAPM_AIF_IN("DP1RX", "DP1 Headphone Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Headset Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Speaker Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DP6TX", "DP6 DMic Capture", 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route rt721_sdca_audio_map[] = { + {"FU 42", NULL, "DP1RX"}, + {"FU 21", NULL, "DP3RX"}, + {"FU 23", NULL, "DP3RX"}, + + {"ADC 09 Mux", "MIC2", "MIC2"}, + {"ADC 09 Mux", "LINE1", "LINE1"}, + {"ADC 09 Mux", "LINE2", "LINE2"}, + {"ADC 07 R Mux", "DMIC1 RE", "DMIC1_2"}, + {"ADC 07 R Mux", "DMIC1 FE", "DMIC1_2"}, + {"ADC 07 R Mux", "DMIC2 RE", "DMIC3_4"}, + {"ADC 07 R Mux", "DMIC2 FE", "DMIC3_4"}, + {"ADC 07 L Mux", "DMIC1 RE", "DMIC1_2"}, + {"ADC 07 L Mux", "DMIC1 FE", "DMIC1_2"}, + {"ADC 07 L Mux", "DMIC2 RE", "DMIC3_4"}, + {"ADC 07 L Mux", "DMIC2 FE", "DMIC3_4"}, + {"ADC 08 R Mux", "DMIC1 RE", "DMIC1_2"}, + {"ADC 08 R Mux", "DMIC1 FE", "DMIC1_2"}, + {"ADC 08 R Mux", "DMIC2 RE", "DMIC3_4"}, + {"ADC 08 R Mux", "DMIC2 FE", "DMIC3_4"}, + {"ADC 08 L Mux", "DMIC1 RE", "DMIC1_2"}, + {"ADC 08 L Mux", "DMIC1 FE", "DMIC1_2"}, + {"ADC 08 L Mux", "DMIC2 RE", "DMIC3_4"}, + {"ADC 08 L Mux", "DMIC2 FE", "DMIC3_4"}, + {"ADC 10 R Mux", "DMIC1 RE", "DMIC1_2"}, + {"ADC 10 R Mux", "DMIC1 FE", "DMIC1_2"}, + {"ADC 10 R Mux", "DMIC2 RE", "DMIC3_4"}, + {"ADC 10 R Mux", "DMIC2 FE", "DMIC3_4"}, + {"ADC 10 L Mux", "DMIC1 RE", "DMIC1_2"}, + {"ADC 10 L Mux", "DMIC1 FE", "DMIC1_2"}, + {"ADC 10 L Mux", "DMIC2 RE", "DMIC3_4"}, + {"ADC 10 L Mux", "DMIC2 FE", "DMIC3_4"}, + {"FU 36", NULL, "PDE 34"}, + {"FU 36", NULL, "ADC 09 Mux"}, + {"FU 113", NULL, "PDE 11"}, + {"FU 113", NULL, "ADC 07 R Mux"}, + {"FU 113", NULL, "ADC 07 L Mux"}, + {"FU 113", NULL, "ADC 10 R Mux"}, + {"FU 113", NULL, "ADC 10 L Mux"}, + {"DP2TX", NULL, "FU 36"}, + {"DP6TX", NULL, "FU 113"}, + + {"HP", NULL, "PDE 47"}, + {"HP", NULL, "FU 42"}, + {"SPK", NULL, "PDE 41"}, + {"SPK", NULL, "FU 21"}, + {"SPK", NULL, "FU 23"}, +}; + +static int rt721_sdca_parse_dt(struct rt721_sdca_priv *rt721, struct device *dev) +{ + device_property_read_u32(dev, "realtek,jd-src", &rt721->jd_src); + + return 0; +} + +static int rt721_sdca_probe(struct snd_soc_component *component) +{ + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + int ret; + + rt721_sdca_parse_dt(rt721, &rt721->slave->dev); + rt721->component = component; + + ret = pm_runtime_resume(component->dev); + if (ret < 0 && ret != -EACCES) + return ret; + + return 0; +} + +static const struct snd_soc_component_driver soc_sdca_dev_rt721 = { + .probe = rt721_sdca_probe, + .controls = rt721_sdca_controls, + .num_controls = ARRAY_SIZE(rt721_sdca_controls), + .dapm_widgets = rt721_sdca_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt721_sdca_dapm_widgets), + .dapm_routes = rt721_sdca_audio_map, + .num_dapm_routes = ARRAY_SIZE(rt721_sdca_audio_map), + .set_jack = rt721_sdca_set_jack_detect, + .endianness = 1, +}; + +static int rt721_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, + int direction) +{ + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); + + return 0; +} + +static void rt721_sdca_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + snd_soc_dai_set_dma_data(dai, substream, NULL); +} + +static int rt721_sdca_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct sdw_stream_runtime *sdw_stream; + int retval, port, num_channels; + unsigned int sampling_rate; + + dev_dbg(dai->dev, "%s %s", __func__, dai->name); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!sdw_stream) + return -EINVAL; + + if (!rt721->slave) + return -EINVAL; + + /* + * RT721_AIF1 with port = 1 for headphone playback + * RT721_AIF1 with port = 2 for headset-mic capture + * RT721_AIF2 with port = 3 for speaker playback + * RT721_AIF3 with port = 6 for digital-mic capture + */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + direction = SDW_DATA_DIR_RX; + if (dai->id == RT721_AIF1) + port = 1; + else if (dai->id == RT721_AIF2) + port = 3; + else + return -EINVAL; + } else { + direction = SDW_DATA_DIR_TX; + if (dai->id == RT721_AIF1) + port = 2; + else if (dai->id == RT721_AIF3) + port = 6; + else + return -EINVAL; + } + stream_config.frame_rate = params_rate(params); + stream_config.ch_count = params_channels(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + + num_channels = params_channels(params); + port_config.ch_mask = GENMASK(num_channels - 1, 0); + port_config.num = port; + + retval = sdw_stream_add_slave(rt721->slave, &stream_config, + &port_config, 1, sdw_stream); + if (retval) { + dev_err(dai->dev, "Unable to configure port\n"); + return retval; + } + + if (params_channels(params) > 16) { + dev_err(component->dev, "Unsupported channels %d\n", + params_channels(params)); + return -EINVAL; + } + + /* sampling rate configuration */ + switch (params_rate(params)) { + case 8000: + sampling_rate = RT721_SDCA_RATE_8000HZ; + break; + case 16000: + sampling_rate = RT721_SDCA_RATE_16000HZ; + break; + case 24000: + sampling_rate = RT721_SDCA_RATE_24000HZ; + break; + case 32000: + sampling_rate = RT721_SDCA_RATE_32000HZ; + break; + case 44100: + sampling_rate = RT721_SDCA_RATE_44100HZ; + break; + case 48000: + sampling_rate = RT721_SDCA_RATE_48000HZ; + break; + case 96000: + sampling_rate = RT721_SDCA_RATE_96000HZ; + break; + case 192000: + sampling_rate = RT721_SDCA_RATE_192000HZ; + break; + case 384000: + sampling_rate = RT721_SDCA_RATE_384000HZ; + break; + case 768000: + sampling_rate = RT721_SDCA_RATE_768000HZ; + break; + default: + dev_err(component->dev, "Rate %d is not supported\n", + params_rate(params)); + return -EINVAL; + } + + /* set sampling frequency */ + if (dai->id == RT721_AIF1) { + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_CS01, + RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), sampling_rate); + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_CS11, + RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), sampling_rate); + } + + if (dai->id == RT721_AIF2) + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_CS31, + RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), sampling_rate); + + if (dai->id == RT721_AIF3) + regmap_write(rt721->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_CS1F, + RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), sampling_rate); + + return 0; +} + +static int rt721_sdca_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component); + struct sdw_stream_runtime *sdw_stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!rt721->slave) + return -EINVAL; + + sdw_stream_remove_slave(rt721->slave, sdw_stream); + return 0; +} + +#define RT721_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define RT721_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE) + +static const struct snd_soc_dai_ops rt721_sdca_ops = { + .hw_params = rt721_sdca_pcm_hw_params, + .hw_free = rt721_sdca_pcm_hw_free, + .set_stream = rt721_sdca_set_sdw_stream, + .shutdown = rt721_sdca_shutdown, +}; + +static struct snd_soc_dai_driver rt721_sdca_dai[] = { + { + .name = "rt721-sdca-aif1", + .id = RT721_AIF1, + .playback = { + .stream_name = "DP1 Headphone Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT721_STEREO_RATES, + .formats = RT721_FORMATS, + }, + .capture = { + .stream_name = "DP2 Headset Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT721_STEREO_RATES, + .formats = RT721_FORMATS, + }, + .ops = &rt721_sdca_ops, + }, + { + .name = "rt721-sdca-aif2", + .id = RT721_AIF2, + .playback = { + .stream_name = "DP3 Speaker Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT721_STEREO_RATES, + .formats = RT721_FORMATS, + }, + .ops = &rt721_sdca_ops, + }, + { + .name = "rt721-sdca-aif3", + .id = RT721_AIF3, + .capture = { + .stream_name = "DP6 DMic Capture", + .channels_min = 1, + .channels_max = 4, + .rates = RT721_STEREO_RATES, + .formats = RT721_FORMATS, + }, + .ops = &rt721_sdca_ops, + } +}; + +int rt721_sdca_init(struct device *dev, struct regmap *regmap, + struct regmap *mbq_regmap, struct sdw_slave *slave) +{ + struct rt721_sdca_priv *rt721; + + rt721 = devm_kzalloc(dev, sizeof(*rt721), GFP_KERNEL); + if (!rt721) + return -ENOMEM; + + dev_set_drvdata(dev, rt721); + rt721->slave = slave; + rt721->regmap = regmap; + rt721->mbq_regmap = mbq_regmap; + + regcache_cache_only(rt721->regmap, true); + regcache_cache_only(rt721->mbq_regmap, true); + + mutex_init(&rt721->calibrate_mutex); + mutex_init(&rt721->disable_irq_lock); + + INIT_DELAYED_WORK(&rt721->jack_detect_work, rt721_sdca_jack_detect_handler); + INIT_DELAYED_WORK(&rt721->jack_btn_check_work, rt721_sdca_btn_check_handler); + + /* + * Mark hw_init to false + * HW init will be performed when device reports present + */ + rt721->hw_init = false; + rt721->first_hw_init = false; + rt721->fu1e_dapm_mute = true; + rt721->fu0f_dapm_mute = true; + rt721->fu0f_mixer_l_mute = rt721->fu0f_mixer_r_mute = true; + rt721->fu1e_mixer_mute[0] = rt721->fu1e_mixer_mute[1] = + rt721->fu1e_mixer_mute[2] = rt721->fu1e_mixer_mute[3] = true; + + return devm_snd_soc_register_component(dev, + &soc_sdca_dev_rt721, rt721_sdca_dai, ARRAY_SIZE(rt721_sdca_dai)); +} + +int rt721_sdca_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct rt721_sdca_priv *rt721 = dev_get_drvdata(dev); + + rt721->disable_irq = false; + + if (rt721->hw_init) + return 0; + + regcache_cache_only(rt721->regmap, false); + regcache_cache_only(rt721->mbq_regmap, false); + if (rt721->first_hw_init) { + regcache_cache_bypass(rt721->regmap, true); + regcache_cache_bypass(rt721->mbq_regmap, true); + } else { + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(&slave->dev, 3000); + pm_runtime_use_autosuspend(&slave->dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(&slave->dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(&slave->dev); + + pm_runtime_enable(&slave->dev); + } + + pm_runtime_get_noresume(&slave->dev); + rt721_sdca_dmic_preset(rt721); + rt721_sdca_amp_preset(rt721); + rt721_sdca_jack_preset(rt721); + if (rt721->first_hw_init) { + regcache_cache_bypass(rt721->regmap, false); + regcache_mark_dirty(rt721->regmap); + regcache_cache_bypass(rt721->mbq_regmap, false); + regcache_mark_dirty(rt721->mbq_regmap); + } else + rt721->first_hw_init = true; + + /* Mark Slave initialization complete */ + rt721->hw_init = true; + + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put_autosuspend(&slave->dev); + + dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); + return 0; +} + +MODULE_DESCRIPTION("ASoC RT721 SDCA SDW driver"); +MODULE_AUTHOR("Jack Yu "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt721-sdca.h b/sound/soc/codecs/rt721-sdca.h new file mode 100644 index 000000000000..e2f071909da8 --- /dev/null +++ b/sound/soc/codecs/rt721-sdca.h @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * rt721-sdca.h -- RT721 SDCA ALSA SoC audio driver header + * + * Copyright(c) 2024 Realtek Semiconductor Corp. + */ + +#ifndef __RT721_H__ +#define __RT721_H__ + +#include +#include +#include +#include +#include +#include + +struct rt721_sdca_priv { + struct regmap *regmap; + struct regmap *mbq_regmap; + struct snd_soc_component *component; + struct sdw_slave *slave; + struct sdw_bus_params params; + bool hw_init; + bool first_hw_init; + struct mutex calibrate_mutex; + struct mutex disable_irq_lock; + bool disable_irq; + /* For Headset jack & Headphone */ + unsigned int scp_sdca_stat1; + unsigned int scp_sdca_stat2; + struct snd_soc_jack *hs_jack; + struct delayed_work jack_detect_work; + struct delayed_work jack_btn_check_work; + int jack_type; + int jd_src; + bool fu0f_dapm_mute; + bool fu0f_mixer_l_mute; + bool fu0f_mixer_r_mute; + /* For DMIC */ + bool fu1e_dapm_mute; + bool fu1e_mixer_mute[4]; +}; + +struct rt721_sdca_dmic_kctrl_priv { + unsigned int reg_base; + unsigned int count; + unsigned int max; + unsigned int invert; +}; + +/* NID */ +#define RT721_ANA_POW_PART 0x01 +#define RT721_DAC_CTRL 0x04 +#define RT721_JD_CTRL 0x09 +#define RT721_CBJ_CTRL 0x0a +#define RT721_CAP_PORT_CTRL 0x0c +#define RT721_CLASD_AMP_CTRL 0x0d +#define RT721_VENDOR_REG 0x20 +#define RT721_RC_CALIB_CTRL 0x40 +#define RT721_VENDOR_EQ_L 0x53 +#define RT721_VENDOR_EQ_R 0x54 +#define RT721_VENDOR_HP_CALI 0x56 +#define RT721_VENDOR_CHARGE_PUMP 0x57 +#define RT721_VENDOR_CLASD_CALI 0x58 +#define RT721_VENDOR_IMS_DRE 0x5b +#define RT721_VENDOR_SPK_EFUSE 0x5c +#define RT721_VENDOR_LEVEL_CTRL 0x5d +#define RT721_VENDOR_ANA_CTL 0x5f +#define RT721_HDA_SDCA_FLOAT 0x61 + +/* Index (NID:01h) */ +#define RT721_MBIAS_LV_CTRL2 0x07 +#define RT721_VREF1_HV_CTRL1 0x0a +#define RT721_VREF2_LV_CTRL1 0x0b + +/* Index (NID:04h) */ +#define RT721_DAC_2CH_CTRL3 0x02 +#define RT721_DAC_2CH_CTRL4 0x03 + +/* Index (NID:09h) */ +#define RT721_JD_1PIN_GAT_CTRL2 0x07 + +/* Index (NID:0ah) */ +#define RT721_CBJ_A0_GAT_CTRL1 0x04 +#define RT721_CBJ_A0_GAT_CTRL2 0x05 + +/* Index (NID:0Ch) */ +#define RT721_HP_AMP_2CH_CAL1 0x05 +#define RT721_HP_AMP_2CH_CAL4 0x08 +#define RT721_HP_AMP_2CH_CAL18 0x1b + +/* Index (NID:0dh) */ +#define RT721_CLASD_AMP_2CH_CAL 0x14 + +/* Index (NID:20h) */ +#define RT721_JD_PRODUCT_NUM 0x00 +#define RT721_ANALOG_BIAS_CTL3 0x04 +#define RT721_JD_CTRL1 0x09 +#define RT721_LDO2_3_CTL1 0x0e +#define RT721_GPIO_PAD_CTRL5 0x13 +#define RT721_LDO1_CTL 0x1a +#define RT721_HP_JD_CTRL 0x24 +#define RT721_VD_HIDDEN_CTRL 0x26 +#define RT721_CLSD_CTRL6 0x3c +#define RT721_COMBO_JACK_AUTO_CTL1 0x45 +#define RT721_COMBO_JACK_AUTO_CTL2 0x46 +#define RT721_COMBO_JACK_AUTO_CTL3 0x47 +#define RT721_DIGITAL_MISC_CTRL4 0x4a +#define RT721_VREFO_GAT 0x63 +#define RT721_FSM_CTL 0x67 +#define RT721_SDCA_INTR_REC 0x82 +#define RT721_SW_CONFIG1 0x8a +#define RT721_SW_CONFIG2 0x8b + +/* Index (NID:40h) */ +#define RT721_RC_CALIB_CTRL0 0x00 + +/* Index (NID:58h) */ +#define RT721_DAC_DC_CALI_CTL1 0x01 +#define RT721_DAC_DC_CALI_CTL2 0x02 +#define RT721_DAC_DC_CALI_CTL3 0x03 + +/* Index (NID:5fh) */ +#define RT721_MISC_POWER_CTL0 0x00 +#define RT721_MISC_POWER_CTL31 0x31 +#define RT721_UAJ_TOP_TCON13 0x44 +#define RT721_UAJ_TOP_TCON14 0x45 +#define RT721_UAJ_TOP_TCON17 0x48 + +/* Index (NID:61h) */ +#define RT721_HDA_LEGACY_MUX_CTL0 0x00 +#define RT721_HDA_LEGACY_UAJ_CTL 0x02 +#define RT721_HDA_LEGACY_CTL1 0x05 +#define RT721_HDA_LEGACY_RESET_CTL 0x06 +#define RT721_GE_REL_CTRL1 0x0d +#define RT721_HDA_LEGACY_GPIO_WAKE_EN_CTL 0x0e +#define RT721_GE_SDCA_RST_CTRL 0x10 +#define RT721_INT_RST_EN_CTRL 0x11 +#define RT721_XU_EVENT_EN 0x13 +#define RT721_INLINE_CTL2 0x17 +#define RT721_UMP_HID_CTRL1 0x18 +#define RT721_UMP_HID_CTRL2 0x19 +#define RT721_UMP_HID_CTRL3 0x1a +#define RT721_UMP_HID_CTRL4 0x1b +#define RT721_UMP_HID_CTRL5 0x1c +#define RT721_FUNC_FLOAT_CTL0 0x22 +#define RT721_FUNC_FLOAT_CTL1 0x23 +#define RT721_FUNC_FLOAT_CTL2 0x24 +#define RT721_FUNC_FLOAT_CTL3 0x25 +#define RT721_ENT_FLOAT_CTL0 0x29 +#define RT721_ENT_FLOAT_CTL1 0x2c +#define RT721_ENT_FLOAT_CTL2 0x2d +#define RT721_ENT_FLOAT_CTL3 0x2e +#define RT721_ENT_FLOAT_CTL4 0x2f +#define RT721_CH_FLOAT_CTL1 0x45 +#define RT721_CH_FLOAT_CTL2 0x46 +#define RT721_ENT_FLOAT_CTL5 0x53 +#define RT721_ENT_FLOAT_CTL6 0x54 +#define RT721_ENT_FLOAT_CTL7 0x55 +#define RT721_ENT_FLOAT_CTL8 0x57 +#define RT721_ENT_FLOAT_CTL9 0x5a +#define RT721_ENT_FLOAT_CTL10 0x5b +#define RT721_CH_FLOAT_CTL3 0x6a +#define RT721_CH_FLOAT_CTL4 0x6d +#define RT721_CH_FLOAT_CTL5 0x70 +#define RT721_CH_FLOAT_CTL6 0x92 + +/* Parameter & Verb control 01 (0x26)(NID:20h) */ +#define RT721_HIDDEN_REG_SW_RESET (0x1 << 14) + +/* Buffer address for HID */ +#define RT721_BUF_ADDR_HID1 0x44030000 +#define RT721_BUF_ADDR_HID2 0x44030020 + +/* RT721 SDCA Control - function number */ +#define FUNC_NUM_JACK_CODEC 0x01 +#define FUNC_NUM_MIC_ARRAY 0x02 +#define FUNC_NUM_HID 0x03 +#define FUNC_NUM_AMP 0x04 + +/* RT721 SDCA entity */ +#define RT721_SDCA_ENT_HID01 0x01 +#define RT721_SDCA_ENT_XUV 0x03 +#define RT721_SDCA_ENT_GE49 0x49 +#define RT721_SDCA_ENT_USER_FU05 0x05 +#define RT721_SDCA_ENT_USER_FU06 0x06 +#define RT721_SDCA_ENT_USER_FU0F 0x0f +#define RT721_SDCA_ENT_USER_FU10 0x19 +#define RT721_SDCA_ENT_USER_FU1E 0x1e +#define RT721_SDCA_ENT_FU15 0x15 +#define RT721_SDCA_ENT_PDE23 0x23 +#define RT721_SDCA_ENT_PDE40 0x40 +#define RT721_SDCA_ENT_PDE41 0x41 +#define RT721_SDCA_ENT_PDE11 0x11 +#define RT721_SDCA_ENT_PDE12 0x12 +#define RT721_SDCA_ENT_PDE2A 0x2a +#define RT721_SDCA_ENT_CS01 0x01 +#define RT721_SDCA_ENT_CS11 0x11 +#define RT721_SDCA_ENT_CS1F 0x1f +#define RT721_SDCA_ENT_CS1C 0x1c +#define RT721_SDCA_ENT_CS31 0x31 +#define RT721_SDCA_ENT_OT23 0x42 +#define RT721_SDCA_ENT_IT26 0x26 +#define RT721_SDCA_ENT_IT09 0x09 +#define RT721_SDCA_ENT_PLATFORM_FU15 0x15 +#define RT721_SDCA_ENT_PLATFORM_FU44 0x44 +#define RT721_SDCA_ENT_XU03 0x03 +#define RT721_SDCA_ENT_XU0D 0x0d +#define RT721_SDCA_ENT_FU55 0x55 + +/* RT721 SDCA control */ +#define RT721_SDCA_CTL_SAMPLE_FREQ_INDEX 0x10 +#define RT721_SDCA_CTL_FU_MUTE 0x01 +#define RT721_SDCA_CTL_FU_VOLUME 0x02 +#define RT721_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10 +#define RT721_SDCA_CTL_HIDTX_SET_OWNER_TO_DEVICE 0x11 +#define RT721_SDCA_CTL_HIDTX_MESSAGE_OFFSET 0x12 +#define RT721_SDCA_CTL_HIDTX_MESSAGE_LENGTH 0x13 +#define RT721_SDCA_CTL_SELECTED_MODE 0x01 +#define RT721_SDCA_CTL_DETECTED_MODE 0x02 +#define RT721_SDCA_CTL_REQ_POWER_STATE 0x01 +#define RT721_SDCA_CTL_VENDOR_DEF 0x30 +#define RT721_SDCA_CTL_XUV 0x34 +#define RT721_SDCA_CTL_FU_CH_GAIN 0x0b + +/* RT721 SDCA channel */ +#define CH_L 0x01 +#define CH_R 0x02 +#define CH_01 0x01 +#define CH_02 0x02 +#define CH_03 0x03 +#define CH_04 0x04 +#define CH_08 0x08 +#define CH_09 0x09 +#define CH_0A 0x0a + +/* sample frequency index */ +#define RT721_SDCA_RATE_8000HZ 0x01 +#define RT721_SDCA_RATE_11025HZ 0x02 +#define RT721_SDCA_RATE_12000HZ 0x03 +#define RT721_SDCA_RATE_16000HZ 0x04 +#define RT721_SDCA_RATE_22050HZ 0x05 +#define RT721_SDCA_RATE_24000HZ 0x06 +#define RT721_SDCA_RATE_32000HZ 0x07 +#define RT721_SDCA_RATE_44100HZ 0x08 +#define RT721_SDCA_RATE_48000HZ 0x09 +#define RT721_SDCA_RATE_88200HZ 0x0a +#define RT721_SDCA_RATE_96000HZ 0x0b +#define RT721_SDCA_RATE_176400HZ 0x0c +#define RT721_SDCA_RATE_192000HZ 0x0d +#define RT721_SDCA_RATE_384000HZ 0x0e +#define RT721_SDCA_RATE_768000HZ 0x0f + +/* RT721 HID ID */ +#define RT721_SDCA_HID_ID 0x11 + +enum { + RT721_AIF1, /* For headset mic and headphone */ + RT721_AIF2, /* For speaker */ + RT721_AIF3, /* For dmic */ + RT721_AIFS, +}; + +int rt721_sdca_io_init(struct device *dev, struct sdw_slave *slave); +int rt721_sdca_init(struct device *dev, struct regmap *regmap, + struct regmap *mbq_regmap, struct sdw_slave *slave); +#endif /* __RT721_H__ */ From 38616a7fc5293dd744384a6d90343f1980d69afd Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:40 +0100 Subject: [PATCH 065/256] ALSA: scarlett2: Fix redeclaration of loop variable JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 5e7b782259fd396c7802948f5901bb2d769ddff8 Author: Geoffrey D. Bennett Date: Fri Oct 4 23:57:54 2024 +0930 ALSA: scarlett2: Fix redeclaration of loop variable Was using both "for (i = 0, ..." and "for (int i = 0, ..." in scarlett2_update_autogain(). Remove "int" to fix. Signed-off-by: Geoffrey D. Bennett Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/ecb0a8931c1883abd6c0e335c63961653bef85f0.1727971672.git.g@b4.vu Signed-off-by: Jaroslav Kysela --- sound/usb/mixer_scarlett2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c index 4cddf84db631..35dfd6e0563d 100644 --- a/sound/usb/mixer_scarlett2.c +++ b/sound/usb/mixer_scarlett2.c @@ -3409,7 +3409,7 @@ static int scarlett2_update_autogain(struct usb_mixer_interface *mixer) private->num_autogain_status_texts - 1; - for (int i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++) + for (i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++) if (scarlett2_has_config_item(private, scarlett2_ag_target_configs[i])) { err = scarlett2_usb_get_config( @@ -3420,7 +3420,7 @@ static int scarlett2_update_autogain(struct usb_mixer_interface *mixer) } /* convert from negative dBFS as used by the device */ - for (int i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++) + for (i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++) private->ag_targets[i] = -ag_target_values[i]; return 0; From 095c4a64ac2415fb6b33043522097ec64c88bb67 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:40 +0100 Subject: [PATCH 066/256] ALSA: scarlett2: Add support for device map retrieval JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9930c2606007d4e26efb1dc4d9e28158b585ccf2 Author: Geoffrey D. Bennett Date: Fri Oct 4 23:59:04 2024 +0930 ALSA: scarlett2: Add support for device map retrieval Add support for retrieving the device map from Focusrite Scarlett 4th Gen and Vocaster devices. The device map is a base64-encoded, zlib-compressed JSON description of the device's capabilities and configuration. This patch adds: - a has_devmap field to the scarlett2_device_info struct - a /proc/asound/cardX/device-map.json.zz.b64 file when supported Signed-off-by: Geoffrey D. Bennett Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/e86380c6792460d8d05a8ecc37c9ebd072be25a5.1727971672.git.g@b4.vu Signed-off-by: Jaroslav Kysela --- sound/usb/mixer_scarlett2.c | 139 +++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c index 35dfd6e0563d..5628bc78fde7 100644 --- a/sound/usb/mixer_scarlett2.c +++ b/sound/usb/mixer_scarlett2.c @@ -1079,6 +1079,9 @@ struct scarlett2_device_info { /* minimum firmware version required */ u16 min_firmware_version; + /* has a downloadable device map */ + u8 has_devmap; + /* support for main/alt speaker switching */ u8 has_speaker_switching; @@ -1773,6 +1776,7 @@ static const struct scarlett2_device_info s18i20_gen3_info = { static const struct scarlett2_device_info vocaster_one_info = { .config_set = &scarlett2_config_set_vocaster, .min_firmware_version = 1769, + .has_devmap = 1, .phantom_count = 1, .inputs_per_phantom = 1, @@ -1815,6 +1819,7 @@ static const struct scarlett2_device_info vocaster_one_info = { static const struct scarlett2_device_info vocaster_two_info = { .config_set = &scarlett2_config_set_vocaster, .min_firmware_version = 1769, + .has_devmap = 1, .phantom_count = 2, .inputs_per_phantom = 1, @@ -1858,6 +1863,7 @@ static const struct scarlett2_device_info vocaster_two_info = { static const struct scarlett2_device_info solo_gen4_info = { .config_set = &scarlett2_config_set_gen4_solo, .min_firmware_version = 2115, + .has_devmap = 1, .level_input_count = 1, .air_input_count = 1, @@ -1912,6 +1918,7 @@ static const struct scarlett2_device_info solo_gen4_info = { static const struct scarlett2_device_info s2i2_gen4_info = { .config_set = &scarlett2_config_set_gen4_2i2, .min_firmware_version = 2115, + .has_devmap = 1, .level_input_count = 2, .air_input_count = 2, @@ -1966,6 +1973,7 @@ static const struct scarlett2_device_info s2i2_gen4_info = { static const struct scarlett2_device_info s4i4_gen4_info = { .config_set = &scarlett2_config_set_gen4_4i4, .min_firmware_version = 2089, + .has_devmap = 1, .level_input_count = 2, .air_input_count = 2, @@ -2264,6 +2272,8 @@ static int scarlett2_get_port_start_num( #define SCARLETT2_USB_GET_DATA 0x00800000 #define SCARLETT2_USB_SET_DATA 0x00800001 #define SCARLETT2_USB_DATA_CMD 0x00800002 +#define SCARLETT2_USB_INFO_DEVMAP 0x0080000c +#define SCARLETT2_USB_GET_DEVMAP 0x0080000d #define SCARLETT2_USB_CONFIG_SAVE 6 @@ -2277,6 +2287,14 @@ static int scarlett2_get_port_start_num( #define SCARLETT2_SEGMENT_SETTINGS_NAME "App_Settings" #define SCARLETT2_SEGMENT_FIRMWARE_NAME "App_Upgrade" +/* Gen 4 device firmware provides access to a base64-encoded + * zlib-compressed JSON description of the device's capabilities and + * configuration. This device map is made available in + * /proc/asound/cardX/device-map.json.zz.b64 + */ +#define SCARLETT2_DEVMAP_BLOCK_SIZE 1024 +#define SCARLETT2_DEVMAP_FILENAME "device-map.json.zz.b64" + /* proprietary request/response format */ struct scarlett2_usb_packet { __le32 cmd; @@ -9591,6 +9609,116 @@ static int scarlett2_hwdep_init(struct usb_mixer_interface *mixer) return 0; } +/*** device-map file ***/ + +static ssize_t scarlett2_devmap_read( + struct snd_info_entry *entry, + void *file_private_data, + struct file *file, + char __user *buf, + size_t count, + loff_t pos) +{ + struct usb_mixer_interface *mixer = entry->private_data; + u8 *resp_buf; + const size_t block_size = SCARLETT2_DEVMAP_BLOCK_SIZE; + size_t copied = 0; + + if (pos >= entry->size) + return 0; + + if (pos + count > entry->size) + count = entry->size - pos; + + resp_buf = kmalloc(block_size, GFP_KERNEL); + if (!resp_buf) + return -ENOMEM; + + while (count > 0) { + /* SCARLETT2_USB_GET_DEVMAP reads only on block boundaries, + * so we need to read a whole block and copy the requested + * chunk to userspace. + */ + + __le32 req; + int err; + + /* offset within the block that we're reading */ + size_t offset = pos % block_size; + + /* read_size is block_size except for the last block */ + size_t block_start = pos - offset; + size_t read_size = min_t(size_t, + block_size, + entry->size - block_start); + + /* size of the chunk to copy to userspace */ + size_t copy_size = min_t(size_t, count, read_size - offset); + + /* request the block */ + req = cpu_to_le32(pos / block_size); + err = scarlett2_usb(mixer, SCARLETT2_USB_GET_DEVMAP, + &req, sizeof(req), resp_buf, read_size); + if (err < 0) { + kfree(resp_buf); + return copied ? copied : err; + } + + if (copy_to_user(buf, resp_buf + offset, copy_size)) { + kfree(resp_buf); + return -EFAULT; + } + + buf += copy_size; + pos += copy_size; + copied += copy_size; + count -= copy_size; + } + + kfree(resp_buf); + return copied; +} + +static const struct snd_info_entry_ops scarlett2_devmap_ops = { + .read = scarlett2_devmap_read, +}; + +static int scarlett2_devmap_init(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + __le16 config_len_buf[2]; + int config_len; + struct snd_info_entry *entry; + int err; + + /* If the device doesn't support the DEVMAP commands, don't + * create the /proc/asound/cardX/scarlett.json.zlib entry + */ + if (!info->has_devmap) + return 0; + + err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_DEVMAP, + NULL, 0, &config_len_buf, sizeof(config_len_buf)); + if (err < 0) + return err; + + config_len = le16_to_cpu(config_len_buf[1]); + + err = snd_card_proc_new(card, SCARLETT2_DEVMAP_FILENAME, &entry); + if (err < 0) + return err; + + entry->content = SNDRV_INFO_CONTENT_DATA; + entry->private_data = mixer; + entry->c.ops = &scarlett2_devmap_ops; + entry->size = config_len; + entry->mode = S_IFREG | 0444; + + return 0; +} + int snd_scarlett2_init(struct usb_mixer_interface *mixer) { struct snd_usb_audio *chip = mixer->chip; @@ -9641,11 +9769,20 @@ int snd_scarlett2_init(struct usb_mixer_interface *mixer) } err = scarlett2_hwdep_init(mixer); - if (err < 0) + if (err < 0) { usb_audio_err(mixer->chip, "Error creating %s hwdep device: %d", entry->series_name, err); + return err; + } + + err = scarlett2_devmap_init(mixer); + if (err < 0) + usb_audio_err(mixer->chip, + "Error creating %s devmap entry: %d", + entry->series_name, + err); return err; } From cfec2dadf29cdd1738046dc7e742b578f207b405 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:40 +0100 Subject: [PATCH 067/256] ALSA: scarlett2: Simplify linked channel handling JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 8eba063b5b2b498ddd01ea6f29fc9b12368c3d53 Author: Geoffrey D. Bennett Date: Fri Oct 4 23:58:51 2024 +0930 ALSA: scarlett2: Simplify linked channel handling The current handling of linked channels for the 4th Gen 2i2 and 4i4 models is more complicated than necessary. The firmware has a link control for each channel, and the channel selection can be any channel regardless of the channel link status. The driver can therefore be simplified by having it reflect the controls presented by the firmware, and complexities related to trying to reflect the channel link status in the Input Select Capture Enum control are not necessary. Signed-off-by: Geoffrey D. Bennett Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/9bf8a2ab35f243820d066319b7d407b45a61281b.1727971672.git.g@b4.vu Signed-off-by: Jaroslav Kysela --- sound/usb/mixer_scarlett2.c | 71 ++++++++++++------------------------- 1 file changed, 22 insertions(+), 49 deletions(-) diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c index 5628bc78fde7..7cb854d6cf83 100644 --- a/sound/usb/mixer_scarlett2.c +++ b/sound/usb/mixer_scarlett2.c @@ -11,7 +11,7 @@ * - Clarett 2Pre/4Pre/8Pre USB * - Clarett+ 2Pre/4Pre/8Pre * - * Copyright (c) 2018-2023 by Geoffrey D. Bennett + * Copyright (c) 2018-2024 by Geoffrey D. Bennett * Copyright (c) 2020-2021 by Vladimir Sadovnikov * Copyright (c) 2022 by Christian Colglazier * @@ -1256,7 +1256,7 @@ struct scarlett2_data { u8 phantom_switch[SCARLETT2_PHANTOM_SWITCH_MAX]; u8 phantom_persistence; u8 input_select_switch; - u8 input_link_switch[SCARLETT2_INPUT_GAIN_MAX / 2]; + u8 input_link_switch[SCARLETT2_INPUT_GAIN_MAX]; u8 gain[SCARLETT2_INPUT_GAIN_MAX]; u8 autogain_switch[SCARLETT2_INPUT_GAIN_MAX]; u8 autogain_status[SCARLETT2_INPUT_GAIN_MAX]; @@ -1287,7 +1287,7 @@ struct scarlett2_data { struct snd_kcontrol *input_mute_ctls[SCARLETT2_INPUT_MUTE_SWITCH_MAX]; struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX]; struct snd_kcontrol *input_select_ctl; - struct snd_kcontrol *input_link_ctls[SCARLETT2_INPUT_GAIN_MAX / 2]; + struct snd_kcontrol *input_link_ctls[SCARLETT2_INPUT_GAIN_MAX]; struct snd_kcontrol *input_gain_ctls[SCARLETT2_INPUT_GAIN_MAX]; struct snd_kcontrol *autogain_ctls[SCARLETT2_INPUT_GAIN_MAX]; struct snd_kcontrol *autogain_status_ctls[SCARLETT2_INPUT_GAIN_MAX]; @@ -3457,7 +3457,7 @@ static void scarlett2_autogain_update_access(struct usb_mixer_interface *mixer) scarlett2_set_ctl_access(private->input_select_ctl, val); if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_INPUT_LINK_SWITCH)) - for (i = 0; i < info->gain_input_count / 2; i++) + for (i = 0; i < info->gain_input_count; i++) scarlett2_set_ctl_access(private->input_link_ctls[i], val); for (i = 0; i < info->gain_input_count; i++) @@ -3498,7 +3498,7 @@ static void scarlett2_autogain_notify_access(struct usb_mixer_interface *mixer) &private->input_select_ctl->id); if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_INPUT_LINK_SWITCH)) - for (i = 0; i < info->gain_input_count / 2; i++) + for (i = 0; i < info->gain_input_count; i++) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, &private->input_link_ctls[i]->id); for (i = 0; i < info->gain_input_count; i++) @@ -3843,7 +3843,7 @@ static int scarlett2_update_input_select(struct usb_mixer_interface *mixer) { struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - int link_count = info->gain_input_count / 2; + int link_count = info->gain_input_count; int err; private->input_select_updated = 0; @@ -3865,10 +3865,6 @@ static int scarlett2_update_input_select(struct usb_mixer_interface *mixer) if (err < 0) return err; - /* simplified because no model yet has link_count > 1 */ - if (private->input_link_switch[0]) - private->input_select_switch = 0; - return 0; } @@ -3905,9 +3901,9 @@ static int scarlett2_input_select_ctl_put( struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; int oval, val, err; - int max_val = private->input_link_switch[0] ? 0 : 1; mutex_lock(&private->data_mutex); @@ -3925,19 +3921,18 @@ static int scarlett2_input_select_ctl_put( if (val < 0) val = 0; - else if (val > max_val) - val = max_val; + else if (val >= info->gain_input_count) + val = info->gain_input_count - 1; if (oval == val) goto unlock; private->input_select_switch = val; - /* Send switch change to the device if inputs not linked */ - if (!private->input_link_switch[0]) - err = scarlett2_usb_set_config( - mixer, SCARLETT2_CONFIG_INPUT_SELECT_SWITCH, - 1, val); + /* Send new value to the device */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_INPUT_SELECT_SWITCH, + 0, val); if (err == 0) err = 1; @@ -3954,8 +3949,7 @@ static int scarlett2_input_select_ctl_info( struct scarlett2_data *private = mixer->private_data; int inputs = private->info->gain_input_count; - int i, j; - int err; + int i, err; char **values = kcalloc(inputs, sizeof(char *), GFP_KERNEL); if (!values) @@ -3972,21 +3966,11 @@ static int scarlett2_input_select_ctl_info( if (err < 0) goto unlock; - /* Loop through each input - * Linked inputs have one value for the pair - */ - for (i = 0, j = 0; i < inputs; i++) { - if (private->input_link_switch[i / 2]) { - values[j++] = kasprintf( - GFP_KERNEL, "Input %d-%d", i + 1, i + 2); - i++; - } else { - values[j++] = kasprintf( - GFP_KERNEL, "Input %d", i + 1); - } - } + /* Loop through each input */ + for (i = 0; i < inputs; i++) + values[i] = kasprintf(GFP_KERNEL, "Input %d", i + 1); - err = snd_ctl_enum_info(uinfo, 1, j, + err = snd_ctl_enum_info(uinfo, 1, i, (const char * const *)values); unlock: @@ -4095,18 +4079,8 @@ static int scarlett2_input_link_ctl_put( private->input_link_switch[index] = val; - /* Notify of change in input select options available */ - snd_ctl_notify(mixer->chip->card, - SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, - &private->input_select_ctl->id); - private->input_select_updated = 1; - - /* Send switch change to the device - * Link for channels 1-2 is at index 1 - * No device yet has more than 2 channels linked - */ err = scarlett2_usb_set_config( - mixer, SCARLETT2_CONFIG_INPUT_LINK_SWITCH, index + 1, val); + mixer, SCARLETT2_CONFIG_INPUT_LINK_SWITCH, index, val); if (err == 0) err = 1; @@ -6934,10 +6908,9 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_INPUT_LINK_SWITCH)) { - for (i = 0; i < info->gain_input_count / 2; i++) { + for (i = 0; i < info->gain_input_count; i++) { scnprintf(s, sizeof(s), - "Line In %d-%d Link Capture Switch", - (i * 2) + 1, (i * 2) + 2); + "Line In %d Link Capture Switch", i + 1); err = scarlett2_add_new_ctl( mixer, &scarlett2_input_link_ctl, i, 1, s, &private->input_link_ctls[i]); @@ -8264,7 +8237,7 @@ static void scarlett2_notify_input_select(struct usb_mixer_interface *mixer) SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, &private->input_select_ctl->id); - for (i = 0; i < info->gain_input_count / 2; i++) + for (i = 0; i < info->gain_input_count; i++) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &private->input_link_ctls[i]->id); } From 753477d9b516d2bd72ddb88603a3a7ad2ab8fd88 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:40 +0100 Subject: [PATCH 068/256] ALSA: scarlett2: Return ENOSPC for out-of-bounds flash writes JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 74641bfcbf4e698b770b1b62a74e73934843e90e Author: Geoffrey D. Bennett Date: Fri Oct 4 23:58:39 2024 +0930 ALSA: scarlett2: Return ENOSPC for out-of-bounds flash writes When writing to flash, return ENOSPC instead of EINVAL if the requested write would exceed the size of the flash segment. Signed-off-by: Geoffrey D. Bennett Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/3a4af07b0329bed5ffb6994594e4f7bd202aad0f.1727971672.git.g@b4.vu Signed-off-by: Jaroslav Kysela --- sound/usb/mixer_scarlett2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c index 7cb854d6cf83..8b5d8ad38522 100644 --- a/sound/usb/mixer_scarlett2.c +++ b/sound/usb/mixer_scarlett2.c @@ -9509,7 +9509,7 @@ static long scarlett2_hwdep_write(struct snd_hwdep *hw, SCARLETT2_FLASH_BLOCK_SIZE; if (count < 0 || *offset < 0 || *offset + count >= flash_size) - return -EINVAL; + return -ENOSPC; if (!count) return 0; From 4604789937a5e411ae7ad32b80e39e99a2bc72cc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:40 +0100 Subject: [PATCH 069/256] ALSA: scarlett2: Fix mixed declarations and code warning JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 5c293089af7de1393af9efd2eb3354b10703670e Author: Geoffrey D. Bennett Date: Fri Oct 4 23:58:12 2024 +0930 ALSA: scarlett2: Fix mixed declarations and code warning In scarlett2_compressor_ctl_put(), move the declaration of param to the beginning of the function to avoid mixed declarations and code. Signed-off-by: Geoffrey D. Bennett Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/ede84092737fa2ca7e94371135cc1e42f1731e84.1727971672.git.g@b4.vu Signed-off-by: Jaroslav Kysela --- sound/usb/mixer_scarlett2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c index 8b5d8ad38522..7f595c1752a5 100644 --- a/sound/usb/mixer_scarlett2.c +++ b/sound/usb/mixer_scarlett2.c @@ -5377,6 +5377,8 @@ static int scarlett2_compressor_ctl_put( int index = elem->control; int channel = index / SCARLETT2_COMPRESSOR_PARAM_COUNT; int param_index = index % SCARLETT2_COMPRESSOR_PARAM_COUNT; + const struct compressor_param *param = &compressor_params[param_index]; + int oval, val, err; s32 scaled_val; @@ -5398,8 +5400,6 @@ static int scarlett2_compressor_ctl_put( private->compressor_values[index] = val; - const struct compressor_param *param = &compressor_params[param_index]; - scaled_val = val << param->scale_bits; /* Send change to the device */ From 88c06b13ecdfbc83f11168ce2be7fc89943172ab Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:40 +0100 Subject: [PATCH 070/256] ALSA: dbri: Fix formatting issue in dbri.c JIRA: https://issues.redhat.com/browse/RHEL-80681 commit f762b71b7a8f8b898303aa982320d6e60b817b2d Author: Zhu Jun Date: Mon Oct 7 22:51:55 2024 -0700 ALSA: dbri: Fix formatting issue in dbri.c Changed sprintf format specifier for rp->start from %016Lx to %016llx to correctly handle unsigned long long values. Signed-off-by: Zhu Jun Link: https://patch.msgid.link/20241008055155.11798-1-zhujun2@cmss.chinamobile.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/sparc/dbri.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index fe35cef511dd..11d23bbaf7f2 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2616,7 +2616,7 @@ static int dbri_probe(struct platform_device *op) strcpy(card->driver, "DBRI"); strcpy(card->shortname, "Sun DBRI"); rp = &op->resource[0]; - sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d", + sprintf(card->longname, "%s at 0x%02lx:0x%016llx, irq %d", card->shortname, rp->flags & 0xffL, (unsigned long long)rp->start, irq); From f3fee49654f83030dc4978f74592d822c47d1142 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:41 +0100 Subject: [PATCH 071/256] ALSA: aica: Remove unused variable JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1ceb43eb60355eed600951248d962c107cd9ba49 Author: Zhu Jun Date: Mon Oct 7 23:13:57 2024 -0700 ALSA: aica: Remove unused variable The variable is never referenced in the code, just remove it Signed-off-by: Zhu Jun Link: https://patch.msgid.link/20241008061357.12042-1-zhujun2@cmss.chinamobile.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/sh/aica.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/sh/aica.c b/sound/sh/aica.c index cf199c117fc5..9428d712c734 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -312,8 +312,6 @@ static void aica_period_elapsed(struct timer_list *t) static void spu_begin_dma(struct snd_pcm_substream *substream) { struct snd_card_aica *dreamcastcard; - struct snd_pcm_runtime *runtime; - runtime = substream->runtime; dreamcastcard = substream->pcm->private_data; /*get the queue to do the work */ schedule_work(&(dreamcastcard->spu_dma_work)); From 5d2932d2e9b0bd84ffc2737b80d8c05b2cc1e085 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:41 +0100 Subject: [PATCH 072/256] ASoC: rt721-sdca: Fix issue of warning message JIRA: https://issues.redhat.com/browse/RHEL-80681 commit e5553cb6612989d18229c2b03948d6b4ba5d45f2 Author: Jack Yu Date: Tue Oct 8 08:57:36 2024 +0000 ASoC: rt721-sdca: Fix issue of warning message Fix issue of warning messages caused by some variables. Signed-off-by: Jack Yu Link: https://patch.msgid.link/065c0b7d84cf47d3a9186235447521c5@realtek.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/rt-sdw-common.c | 2 +- sound/soc/codecs/rt721-sdca.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt-sdw-common.c b/sound/soc/codecs/rt-sdw-common.c index 9ed0e9855699..a422da6cf702 100644 --- a/sound/soc/codecs/rt-sdw-common.c +++ b/sound/soc/codecs/rt-sdw-common.c @@ -108,7 +108,7 @@ EXPORT_SYMBOL_GPL(rt_sdca_index_update_bits); int rt_sdca_btn_type(unsigned char *buffer) { u8 btn_type = 0; - int ret; + int ret = 0; btn_type |= buffer[0] & 0xf; btn_type |= (buffer[0] >> 4) & 0xf; diff --git a/sound/soc/codecs/rt721-sdca.c b/sound/soc/codecs/rt721-sdca.c index 36056cb7a3ca..201cb667c8c1 100644 --- a/sound/soc/codecs/rt721-sdca.c +++ b/sound/soc/codecs/rt721-sdca.c @@ -30,7 +30,7 @@ static void rt721_sdca_jack_detect_handler(struct work_struct *work) { struct rt721_sdca_priv *rt721 = container_of(work, struct rt721_sdca_priv, jack_detect_work.work); - int btn_type = 0, ret; + int btn_type = 0; if (!rt721->hs_jack) return; @@ -42,7 +42,7 @@ static void rt721_sdca_jack_detect_handler(struct work_struct *work) if (rt721->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_6) { rt721->jack_type = rt_sdca_headset_detect(rt721->regmap, RT721_SDCA_ENT_GE49); - if (ret < 0) + if (rt721->jack_type < 0) return; } From af2b3b3237010bf8050d83b8b33de629355fe6e6 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:41 +0100 Subject: [PATCH 073/256] ASoC: SOF: ipc4-topology: Drop the 'index' from 'Pin index' of format print JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 76733db0f5560efa0c6514329620b9cbc8b1ca42 Author: Peter Ujfalusi Date: Tue Oct 8 14:09:29 2024 +0300 ASoC: SOF: ipc4-topology: Drop the 'index' from 'Pin index' of format print Printing the word `index` does not give extra information over printing: `Pin #%d` which tells that the format line is for a specific pin. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241008110936.22534-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc4-topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 240fee2166d1..3f8f5d90f821 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -195,7 +195,7 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_fo for (i = 0; i < num_formats; i++) { struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt; dev_dbg(dev, - "Pin index #%d: %uHz, %ubit, %luch (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n", + "Pin #%d: %uHz, %ubit, %luch (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n", pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth, SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg), fmt->ch_map, fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg, From 734dc50a13a197f8d2031e8f773a463a1b2e1610 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:41 +0100 Subject: [PATCH 074/256] ASoC: SOF: ipc4-topology: Use local variables in sof_ipc4_init_input_audio_fmt() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 3b54c1cd69d04bbdafc5542d11c6cab685fc13bd Author: Peter Ujfalusi Date: Tue Oct 8 14:09:30 2024 +0300 ASoC: SOF: ipc4-topology: Use local variables in sof_ipc4_init_input_audio_fmt() We have local copies of available_fmt->input_pin_fmts and available_fmt->num_input_formats, use them in the function. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241008110936.22534-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc4-topology.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 3f8f5d90f821..dc604331233e 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1278,13 +1278,12 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, int sample_valid_bits; int i = 0; - if (!available_fmt->num_input_formats) { + if (!pin_fmts_size) { dev_err(sdev->dev, "no input formats for %s\n", swidget->widget->name); return -EINVAL; } - single_format = sof_ipc4_is_single_format(sdev, available_fmt->input_pin_fmts, - available_fmt->num_input_formats); + single_format = sof_ipc4_is_single_format(sdev, pin_fmts, pin_fmts_size); if (single_format) goto in_fmt; @@ -1321,15 +1320,15 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, in_fmt: /* copy input format */ - if (available_fmt->num_input_formats && i < available_fmt->num_input_formats) { - memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt, + if (pin_fmts_size && i < pin_fmts_size) { + memcpy(&base_config->audio_fmt, &pin_fmts[i].audio_fmt, sizeof(struct sof_ipc4_audio_format)); /* set base_cfg ibs/obs */ - base_config->ibs = available_fmt->input_pin_fmts[i].buffer_size; + base_config->ibs = pin_fmts[i].buffer_size; dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1); + sof_ipc4_dbg_audio_format(sdev->dev, &pin_fmts[i], 1); } return i; From c1f1ac3296ff02d416e10c1bfc33f1aaec8bb76d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:41 +0100 Subject: [PATCH 075/256] ASoC: SOF: ipc4-topology: Remove redundant check in sof_ipc4_init_input_audio_fmt() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 2d9635b57b1bbbece2a8d30103fcd1ebfbbe0178 Author: Peter Ujfalusi Date: Tue Oct 8 14:09:31 2024 +0300 ASoC: SOF: ipc4-topology: Remove redundant check in sof_ipc4_init_input_audio_fmt() At label in_fmt the if (pin_fmts_size && i < pin_fmts_size) is guarantied to be true all the time, drop the check completely. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241008110936.22534-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc4-topology.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index dc604331233e..5a4ab19176aa 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1320,16 +1320,14 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, in_fmt: /* copy input format */ - if (pin_fmts_size && i < pin_fmts_size) { - memcpy(&base_config->audio_fmt, &pin_fmts[i].audio_fmt, - sizeof(struct sof_ipc4_audio_format)); + memcpy(&base_config->audio_fmt, &pin_fmts[i].audio_fmt, + sizeof(struct sof_ipc4_audio_format)); - /* set base_cfg ibs/obs */ - base_config->ibs = pin_fmts[i].buffer_size; + /* set base_cfg ibs/obs */ + base_config->ibs = pin_fmts[i].buffer_size; - dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, &pin_fmts[i], 1); - } + dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); + sof_ipc4_dbg_audio_format(sdev->dev, &pin_fmts[i], 1); return i; } From 9c3e104e163fb0e213eaa62b61bc2d998b2a02c0 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:41 +0100 Subject: [PATCH 076/256] ASoC: SOF: ipc4-topology: Simplify match format print in sof_ipc4_init_input_audio_fmt() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0126a659fd517103e8ce4d432fbe9b06f0a20510 Author: Peter Ujfalusi Date: Tue Oct 8 14:09:32 2024 +0300 ASoC: SOF: ipc4-topology: Simplify match format print in sof_ipc4_init_input_audio_fmt() Print out the information line for the found input format once to avoid duplicated prints in case when multiple formats are available. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241008110936.22534-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc4-topology.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 5a4ab19176aa..f34c800d6591 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1305,11 +1305,8 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); if (params_rate(params) == rate && params_channels(params) == channels && - sample_valid_bits == valid_bits) { - dev_dbg(sdev->dev, "matched audio format index for %uHz, %ubit, %u channels: %d\n", - rate, valid_bits, channels, i); + sample_valid_bits == valid_bits) break; - } } if (i == pin_fmts_size) { @@ -1326,7 +1323,14 @@ in_fmt: /* set base_cfg ibs/obs */ base_config->ibs = pin_fmts[i].buffer_size; - dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); + if (single_format) + dev_dbg(sdev->dev, "Input audio format for %s:\n", + swidget->widget->name); + else + dev_dbg(sdev->dev, + "Input audio format (format index: %d) for %s:\n", i, + swidget->widget->name); + sof_ipc4_dbg_audio_format(sdev->dev, &pin_fmts[i], 1); return i; From 02cbdc79d331f04755b3a7295b8b302736dfe69e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:42 +0100 Subject: [PATCH 077/256] ASoC: SOF: ipc4-topology: Simplify code to deal with process modules without output JIRA: https://issues.redhat.com/browse/RHEL-80681 commit fdaf2291524c6a220bb051ad1a8d3c99b177b6f1 Author: Peter Ujfalusi Date: Tue Oct 8 14:09:34 2024 +0300 ASoC: SOF: ipc4-topology: Simplify code to deal with process modules without output Process modules are allowed to have zero outputs, thus zero output formats. In this case there is no need for complicated if expressions to handle such cases, we can just use a single if for the number of output formats and the rest can be simplified. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241008110936.22534-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc4-topology.c | 68 +++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index f34c800d6591..414ec9189a1f 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -2356,10 +2356,7 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_process *process = swidget->private; struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt; - struct sof_ipc4_audio_format *in_fmt; - u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; void *cfg = process->ipc_config_data; - int output_fmt_index; int ret; ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &process->base_config, @@ -2367,36 +2364,47 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, if (ret < 0) return ret; - in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; - out_ref_rate = in_fmt->sampling_frequency; - out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); - out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); + /* Configure output audio format only if the module supports output */ + if (available_fmt->num_output_formats) { + u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, fmt_index; + struct sof_ipc4_audio_format *in_fmt; + struct sof_ipc4_pin_format *pin_fmt; - output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, &process->base_config, - available_fmt, out_ref_rate, - out_ref_channels, out_ref_valid_bits); - if (output_fmt_index < 0 && available_fmt->num_output_formats) { - dev_err(sdev->dev, "Failed to initialize output format for %s", - swidget->widget->name); - return output_fmt_index; - } + in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; - /* copy Pin 0 output format */ - if (available_fmt->num_output_formats && - output_fmt_index < available_fmt->num_output_formats && - !available_fmt->output_pin_fmts[output_fmt_index].pin_index) { - memcpy(&process->output_format, - &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt, - sizeof(struct sof_ipc4_audio_format)); + out_ref_rate = in_fmt->sampling_frequency; + out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); + out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); - /* modify the pipeline params with the pin 0 output format */ - ret = sof_ipc4_update_hw_params(sdev, pipeline_params, - &process->output_format, - BIT(SNDRV_PCM_HW_PARAM_FORMAT) | - BIT(SNDRV_PCM_HW_PARAM_CHANNELS) | - BIT(SNDRV_PCM_HW_PARAM_RATE)); - if (ret) - return ret; + fmt_index = sof_ipc4_init_output_audio_fmt(sdev, + &process->base_config, + available_fmt, + out_ref_rate, + out_ref_channels, + out_ref_valid_bits); + if (fmt_index < 0) { + dev_err(sdev->dev, + "Failed to initialize output format for %s", + swidget->widget->name); + return fmt_index; + } + + pin_fmt = &available_fmt->output_pin_fmts[fmt_index]; + + /* copy Pin output format for Pin 0 only */ + if (pin_fmt->pin_index == 0) { + memcpy(&process->output_format, &pin_fmt->audio_fmt, + sizeof(struct sof_ipc4_audio_format)); + + /* modify the pipeline params with the output format */ + ret = sof_ipc4_update_hw_params(sdev, pipeline_params, + &process->output_format, + BIT(SNDRV_PCM_HW_PARAM_FORMAT) | + BIT(SNDRV_PCM_HW_PARAM_CHANNELS) | + BIT(SNDRV_PCM_HW_PARAM_RATE)); + if (ret) + return ret; + } } /* update pipeline memory usage */ From 6ba496e7c4223089a3400accd9f77664bbe97819 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:42 +0100 Subject: [PATCH 078/256] ASoC: SOF: ipc4-topology: Use local variables in sof_ipc4_init_output_audio_fmt() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7a4c41e4778342b0ceda2e16127fefa808de3c57 Author: Peter Ujfalusi Date: Tue Oct 8 14:09:33 2024 +0300 ASoC: SOF: ipc4-topology: Use local variables in sof_ipc4_init_output_audio_fmt() Use local variables for available_fmt->output_pin_fmts and available_fmt->num_output_formats similarly to the input format selection to make the two functions easier to understand and help with readability. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241008110936.22534-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc4-topology.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 414ec9189a1f..88cef901b237 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1210,19 +1210,19 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, u32 out_ref_rate, u32 out_ref_channels, u32 out_ref_valid_bits) { - struct sof_ipc4_audio_format *out_fmt; + struct sof_ipc4_pin_format *pin_fmts = available_fmt->output_pin_fmts; + u32 pin_fmts_size = available_fmt->num_output_formats; bool single_format; int i; - if (!available_fmt->num_output_formats) + if (!pin_fmts_size) return -EINVAL; - single_format = sof_ipc4_is_single_format(sdev, available_fmt->output_pin_fmts, - available_fmt->num_output_formats); + single_format = sof_ipc4_is_single_format(sdev, pin_fmts, pin_fmts_size); /* pick the first format if there's only one available or if all formats are the same */ if (single_format) { - base_config->obs = available_fmt->output_pin_fmts[0].buffer_size; + base_config->obs = pin_fmts[0].buffer_size; return 0; } @@ -1230,17 +1230,18 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, * if there are multiple output formats, then choose the output format that matches * the reference params */ - for (i = 0; i < available_fmt->num_output_formats; i++) { + for (i = 0; i < pin_fmts_size; i++) { + struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt; + u32 _out_rate, _out_channels, _out_valid_bits; - out_fmt = &available_fmt->output_pin_fmts[i].audio_fmt; - _out_rate = out_fmt->sampling_frequency; - _out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(out_fmt->fmt_cfg); - _out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg); + _out_rate = fmt->sampling_frequency; + _out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); + _out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); if (_out_rate == out_ref_rate && _out_channels == out_ref_channels && _out_valid_bits == out_ref_valid_bits) { - base_config->obs = available_fmt->output_pin_fmts[i].buffer_size; + base_config->obs = pin_fmts[i].buffer_size; return i; } } From b5c8f2a6f6b31696e6d72f1aacc0255cfcd0ef0f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:42 +0100 Subject: [PATCH 079/256] ASoC: SOF: ipc4-topology: Concentrate prints inside of sof_ipc4_init_output_audio_fmt() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 22408b8f625d85b5453fde8627aa6dd49f87c281 Author: Peter Ujfalusi Date: Tue Oct 8 14:09:35 2024 +0300 ASoC: SOF: ipc4-topology: Concentrate prints inside of sof_ipc4_init_output_audio_fmt() Similarly to sof_ipc4_init_input_audio_fmt(), move all output format selection related prints (success or failure) inside of the sof_ipc4_init_output_audio_fmt() function. To do this, we need to pass swidget also, like with the input counterpart. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241008110936.22534-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc4-topology.c | 87 ++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 88cef901b237..18ee24022470 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1205,6 +1205,7 @@ static bool sof_ipc4_is_single_format(struct snd_sof_dev *sdev, } static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, + struct snd_sof_widget *swidget, struct sof_ipc4_base_module_cfg *base_config, struct sof_ipc4_available_audio_format *available_fmt, u32 out_ref_rate, u32 out_ref_channels, @@ -1213,18 +1214,19 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, struct sof_ipc4_pin_format *pin_fmts = available_fmt->output_pin_fmts; u32 pin_fmts_size = available_fmt->num_output_formats; bool single_format; - int i; + int i = 0; - if (!pin_fmts_size) + if (!pin_fmts_size) { + dev_err(sdev->dev, "no output formats for %s\n", + swidget->widget->name); return -EINVAL; + } single_format = sof_ipc4_is_single_format(sdev, pin_fmts, pin_fmts_size); /* pick the first format if there's only one available or if all formats are the same */ - if (single_format) { - base_config->obs = pin_fmts[0].buffer_size; - return 0; - } + if (single_format) + goto out_fmt; /* * if there are multiple output formats, then choose the output format that matches @@ -1240,13 +1242,29 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, _out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); if (_out_rate == out_ref_rate && _out_channels == out_ref_channels && - _out_valid_bits == out_ref_valid_bits) { - base_config->obs = pin_fmts[i].buffer_size; - return i; - } + _out_valid_bits == out_ref_valid_bits) + goto out_fmt; } + dev_err(sdev->dev, "%s: Unsupported audio format: %uHz, %ubit, %u channels\n", + __func__, out_ref_rate, out_ref_valid_bits, out_ref_channels); + return -EINVAL; + +out_fmt: + base_config->obs = pin_fmts[i].buffer_size; + + if (single_format) + dev_dbg(sdev->dev, "Output audio format for %s:\n", + swidget->widget->name); + else + dev_dbg(sdev->dev, + "Output audio format (format index: %d) for %s:\n", i, + swidget->widget->name); + + sof_ipc4_dbg_audio_format(sdev->dev, &pin_fmts[i], 1); + + return i; } static int sof_ipc4_get_valid_bits(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params) @@ -1906,17 +1924,12 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg); } - dev_dbg(sdev->dev, "copier %s: reference output rate %d, channels %d valid_bits %d\n", - swidget->widget->name, out_ref_rate, out_ref_channels, out_ref_valid_bits); - - output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, &copier_data->base_config, + output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, + &copier_data->base_config, available_fmt, out_ref_rate, out_ref_channels, out_ref_valid_bits); - if (output_fmt_index < 0) { - dev_err(sdev->dev, "Failed to initialize output format for %s", - swidget->widget->name); + if (output_fmt_index < 0) return output_fmt_index; - } /* * Set the output format. Current topology defines pin 0 input and output formats in pairs. @@ -1928,8 +1941,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, memcpy(&copier_data->out_format, &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt, sizeof(struct sof_ipc4_audio_format)); - dev_dbg(sdev->dev, "Output audio format for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->output_pin_fmts[output_fmt_index], 1); switch (swidget->id) { case snd_soc_dapm_dai_in: @@ -2153,13 +2164,11 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); - ret = sof_ipc4_init_output_audio_fmt(sdev, &gain->data.base_config, available_fmt, - out_ref_rate, out_ref_channels, out_ref_valid_bits); - if (ret < 0) { - dev_err(sdev->dev, "Failed to initialize output format for %s", - swidget->widget->name); + ret = sof_ipc4_init_output_audio_fmt(sdev, swidget, &gain->data.base_config, + available_fmt, out_ref_rate, + out_ref_channels, out_ref_valid_bits); + if (ret < 0) return ret; - } /* update pipeline memory usage */ sof_ipc4_update_resource_usage(sdev, swidget, &gain->data.base_config); @@ -2190,13 +2199,11 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); - ret = sof_ipc4_init_output_audio_fmt(sdev, &mixer->base_config, available_fmt, - out_ref_rate, out_ref_channels, out_ref_valid_bits); - if (ret < 0) { - dev_err(sdev->dev, "Failed to initialize output format for %s", - swidget->widget->name); + ret = sof_ipc4_init_output_audio_fmt(sdev, swidget, &mixer->base_config, + available_fmt, out_ref_rate, + out_ref_channels, out_ref_valid_bits); + if (ret < 0) return ret; - } /* update pipeline memory usage */ sof_ipc4_update_resource_usage(sdev, swidget, &mixer->base_config); @@ -2248,14 +2255,12 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, */ out_ref_rate = params_rate(fe_params); - output_format_index = sof_ipc4_init_output_audio_fmt(sdev, &src->data.base_config, + output_format_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, + &src->data.base_config, available_fmt, out_ref_rate, out_ref_channels, out_ref_valid_bits); - if (output_format_index < 0) { - dev_err(sdev->dev, "Failed to initialize output format for %s", - swidget->widget->name); + if (output_format_index < 0) return output_format_index; - } /* update pipeline memory usage */ sof_ipc4_update_resource_usage(sdev, swidget, &src->data.base_config); @@ -2377,18 +2382,14 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); - fmt_index = sof_ipc4_init_output_audio_fmt(sdev, + fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, &process->base_config, available_fmt, out_ref_rate, out_ref_channels, out_ref_valid_bits); - if (fmt_index < 0) { - dev_err(sdev->dev, - "Failed to initialize output format for %s", - swidget->widget->name); + if (fmt_index < 0) return fmt_index; - } pin_fmt = &available_fmt->output_pin_fmts[fmt_index]; From 83f0c583162309cdf38d0d49bb2f2570cb202f23 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:30:42 +0100 Subject: [PATCH 080/256] ASoC: SOF: ipc4-topology: Add helper function to print the module's in/out audio format JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 47701a85af0c0d655e06dd23f6b8761848147450 Author: Peter Ujfalusi Date: Tue Oct 8 14:09:36 2024 +0300 ASoC: SOF: ipc4-topology: Add helper function to print the module's in/out audio format Introduce a helper function to print out the audio format(s) used by a module in a consistent way. The printed text depends on the module format configuration, taking into account if they have both input and output support, the format is changed by the module and the number of formats supported on input/output. For example, if a module does not change format, there is no point of printing both in and out format, it is adequate to just state the format the module is using. While the function to generate the print is fairly complex (but not too much), it will create a cleaner experience on the reader side by handling the filtering of the information and present it in a way that it - I hope - makes the developer's live a bit more easier when tracking format changes. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241008110936.22534-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc4-topology.c | 262 ++++++++++++++++++++++++---------- 1 file changed, 186 insertions(+), 76 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 18ee24022470..1fcf4692a21f 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -203,6 +203,101 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_fo } } +static void +sof_ipc4_dbg_module_audio_format(struct device *dev, + struct snd_sof_widget *swidget, + struct sof_ipc4_available_audio_format *available_fmt, + int in_fmt_index, int out_fmt_index) +{ + struct sof_ipc4_audio_format *in_fmt, *out_fmt; + u32 out_rate, out_channels, out_valid_bits; + u32 in_rate, in_channels, in_valid_bits; + struct sof_ipc4_pin_format *pin_fmt; + + if (!available_fmt->num_input_formats && + !available_fmt->num_output_formats) + return; + + /* Only input or output is supported by the module */ + if (!available_fmt->num_input_formats) { + if (available_fmt->num_output_formats == 1) + dev_dbg(dev, "Output audio format for %s:\n", + swidget->widget->name); + else + dev_dbg(dev, + "Output audio format (format index: %d) for %s:\n", + out_fmt_index, swidget->widget->name); + + pin_fmt = &available_fmt->output_pin_fmts[out_fmt_index]; + sof_ipc4_dbg_audio_format(dev, pin_fmt, 1); + + return; + } else if (!available_fmt->num_output_formats) { + if (available_fmt->num_input_formats == 1) + dev_dbg(dev, "Input audio format for %s:\n", + swidget->widget->name); + else + dev_dbg(dev, + "Input audio format (format index: %d) for %s:\n", + out_fmt_index, swidget->widget->name); + + pin_fmt = &available_fmt->input_pin_fmts[in_fmt_index]; + sof_ipc4_dbg_audio_format(dev, pin_fmt, 1); + + return; + } + + in_fmt = &available_fmt->input_pin_fmts[in_fmt_index].audio_fmt; + out_fmt = &available_fmt->output_pin_fmts[out_fmt_index].audio_fmt; + + in_rate = in_fmt->sampling_frequency; + in_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); + in_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); + + out_rate = out_fmt->sampling_frequency; + out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(out_fmt->fmt_cfg); + out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg); + + if (!(in_valid_bits != out_valid_bits || in_rate != out_rate || + in_channels != out_channels)) { + /* There is no change in format */ + if (available_fmt->num_input_formats == 1 && + available_fmt->num_output_formats == 1) + dev_dbg(dev, "Audio format for %s:\n", + swidget->widget->name); + else + dev_dbg(dev, + "Audio format (in/out format index: %d/%d) for %s:\n", + in_fmt_index, out_fmt_index, swidget->widget->name); + + pin_fmt = &available_fmt->input_pin_fmts[in_fmt_index]; + sof_ipc4_dbg_audio_format(dev, pin_fmt, 1); + + return; + } + + /* The format is changed by the module */ + if (available_fmt->num_input_formats == 1) + dev_dbg(dev, "Input audio format for %s:\n", + swidget->widget->name); + else + dev_dbg(dev, "Input audio format (format index: %d) for %s:\n", + in_fmt_index, swidget->widget->name); + + pin_fmt = &available_fmt->input_pin_fmts[in_fmt_index]; + sof_ipc4_dbg_audio_format(dev, pin_fmt, 1); + + if (available_fmt->num_output_formats == 1) + dev_dbg(dev, "Output audio format for %s:\n", + swidget->widget->name); + else + dev_dbg(dev, "Output audio format (format index: %d) for %s:\n", + out_fmt_index, swidget->widget->name); + + pin_fmt = &available_fmt->output_pin_fmts[out_fmt_index]; + sof_ipc4_dbg_audio_format(dev, pin_fmt, 1); +} + static const struct sof_ipc4_audio_format * sof_ipc4_get_input_pin_audio_fmt(struct snd_sof_widget *swidget, int pin_index) { @@ -1254,16 +1349,6 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, out_fmt: base_config->obs = pin_fmts[i].buffer_size; - if (single_format) - dev_dbg(sdev->dev, "Output audio format for %s:\n", - swidget->widget->name); - else - dev_dbg(sdev->dev, - "Output audio format (format index: %d) for %s:\n", i, - swidget->widget->name); - - sof_ipc4_dbg_audio_format(sdev->dev, &pin_fmts[i], 1); - return i; } @@ -1342,16 +1427,6 @@ in_fmt: /* set base_cfg ibs/obs */ base_config->ibs = pin_fmts[i].buffer_size; - if (single_format) - dev_dbg(sdev->dev, "Input audio format for %s:\n", - swidget->widget->name); - else - dev_dbg(sdev->dev, - "Input audio format (format index: %d) for %s:\n", i, - swidget->widget->name); - - sof_ipc4_dbg_audio_format(sdev->dev, &pin_fmts[i], 1); - return i; } @@ -1726,6 +1801,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_copier_data *copier_data; + int input_fmt_index, output_fmt_index; struct snd_pcm_hw_params ref_params; struct sof_ipc4_copier *ipc4_copier; struct snd_sof_dai *dai; @@ -1737,7 +1813,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, int ipc_size, ret, out_ref_valid_bits; u32 out_ref_rate, out_ref_channels; u32 deep_buffer_dma_ms = 0; - int output_fmt_index; bool single_output_bitdepth; int i; @@ -1869,10 +1944,11 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, } /* set input and output audio formats */ - ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &copier_data->base_config, - &ref_params, available_fmt); - if (ret < 0) - return ret; + input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, + &copier_data->base_config, + &ref_params, available_fmt); + if (input_fmt_index < 0) + return input_fmt_index; /* set the reference params for output format selection */ single_output_bitdepth = sof_ipc4_copier_is_single_bitdepth(sdev, @@ -1885,7 +1961,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, { struct sof_ipc4_audio_format *in_fmt; - in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; + in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; out_ref_rate = in_fmt->sampling_frequency; out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); @@ -2117,6 +2193,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, *ipc_config_size = ipc_size; + sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt, + input_fmt_index, output_fmt_index); + /* update pipeline memory usage */ sof_ipc4_update_resource_usage(sdev, swidget, &copier_data->base_config); @@ -2152,23 +2231,31 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; struct sof_ipc4_audio_format *in_fmt; u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; - int ret; + int input_fmt_index, output_fmt_index; - ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &gain->data.base_config, - pipeline_params, available_fmt); - if (ret < 0) - return ret; + input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, + &gain->data.base_config, + pipeline_params, + available_fmt); + if (input_fmt_index < 0) + return input_fmt_index; - in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; + in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; out_ref_rate = in_fmt->sampling_frequency; out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); - ret = sof_ipc4_init_output_audio_fmt(sdev, swidget, &gain->data.base_config, - available_fmt, out_ref_rate, - out_ref_channels, out_ref_valid_bits); - if (ret < 0) - return ret; + output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, + &gain->data.base_config, + available_fmt, + out_ref_rate, + out_ref_channels, + out_ref_valid_bits); + if (output_fmt_index < 0) + return output_fmt_index; + + sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt, + input_fmt_index, output_fmt_index); /* update pipeline memory usage */ sof_ipc4_update_resource_usage(sdev, swidget, &gain->data.base_config); @@ -2187,23 +2274,31 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt; struct sof_ipc4_audio_format *in_fmt; u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; - int ret; + int input_fmt_index, output_fmt_index; - ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &mixer->base_config, - pipeline_params, available_fmt); - if (ret < 0) - return ret; + input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, + &mixer->base_config, + pipeline_params, + available_fmt); + if (input_fmt_index < 0) + return input_fmt_index; - in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; + in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; out_ref_rate = in_fmt->sampling_frequency; out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); - ret = sof_ipc4_init_output_audio_fmt(sdev, swidget, &mixer->base_config, - available_fmt, out_ref_rate, - out_ref_channels, out_ref_valid_bits); - if (ret < 0) - return ret; + output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, + &mixer->base_config, + available_fmt, + out_ref_rate, + out_ref_channels, + out_ref_valid_bits); + if (output_fmt_index < 0) + return output_fmt_index; + + sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt, + input_fmt_index, output_fmt_index); /* update pipeline memory usage */ sof_ipc4_update_resource_usage(sdev, swidget, &mixer->base_config); @@ -2223,12 +2318,14 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, struct sof_ipc4_audio_format *out_audio_fmt; struct sof_ipc4_audio_format *in_audio_fmt; u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; - int output_format_index, input_format_index; + int output_fmt_index, input_fmt_index; - input_format_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, &src->data.base_config, - pipeline_params, available_fmt); - if (input_format_index < 0) - return input_format_index; + input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, + &src->data.base_config, + pipeline_params, + available_fmt); + if (input_fmt_index < 0) + return input_fmt_index; /* * For playback, the SRC sink rate will be configured based on the requested output @@ -2244,7 +2341,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, * SRC does not perform format conversion, so the output channels and valid bit depth must * be the same as that of the input. */ - in_audio_fmt = &available_fmt->input_pin_fmts[input_format_index].audio_fmt; + in_audio_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_audio_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg); @@ -2255,17 +2352,22 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, */ out_ref_rate = params_rate(fe_params); - output_format_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, - &src->data.base_config, - available_fmt, out_ref_rate, - out_ref_channels, out_ref_valid_bits); - if (output_format_index < 0) - return output_format_index; + output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, + &src->data.base_config, + available_fmt, + out_ref_rate, + out_ref_channels, + out_ref_valid_bits); + if (output_fmt_index < 0) + return output_fmt_index; + + sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt, + input_fmt_index, output_fmt_index); /* update pipeline memory usage */ sof_ipc4_update_resource_usage(sdev, swidget, &src->data.base_config); - out_audio_fmt = &available_fmt->output_pin_fmts[output_format_index].audio_fmt; + out_audio_fmt = &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt; src->data.sink_rate = out_audio_fmt->sampling_frequency; /* update pipeline_params for sink widgets */ @@ -2363,35 +2465,40 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, struct sof_ipc4_process *process = swidget->private; struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt; void *cfg = process->ipc_config_data; + int output_fmt_index = 0; + int input_fmt_index = 0; int ret; - ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &process->base_config, - pipeline_params, available_fmt); - if (ret < 0) - return ret; + input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, + &process->base_config, + pipeline_params, + available_fmt); + if (input_fmt_index < 0) + return input_fmt_index; /* Configure output audio format only if the module supports output */ if (available_fmt->num_output_formats) { - u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, fmt_index; struct sof_ipc4_audio_format *in_fmt; struct sof_ipc4_pin_format *pin_fmt; + u32 out_ref_rate, out_ref_channels; + int out_ref_valid_bits; - in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; + in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; out_ref_rate = in_fmt->sampling_frequency; out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); - fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, - &process->base_config, - available_fmt, - out_ref_rate, - out_ref_channels, - out_ref_valid_bits); - if (fmt_index < 0) - return fmt_index; + output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, + &process->base_config, + available_fmt, + out_ref_rate, + out_ref_channels, + out_ref_valid_bits); + if (output_fmt_index < 0) + return output_fmt_index; - pin_fmt = &available_fmt->output_pin_fmts[fmt_index]; + pin_fmt = &available_fmt->output_pin_fmts[output_fmt_index]; /* copy Pin output format for Pin 0 only */ if (pin_fmt->pin_index == 0) { @@ -2409,6 +2516,9 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, } } + sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt, + input_fmt_index, output_fmt_index); + /* update pipeline memory usage */ sof_ipc4_update_resource_usage(sdev, swidget, &process->base_config); From 68bac406cd8b5efbd62062f929c77e40afdceb5d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:31:44 +0100 Subject: [PATCH 081/256] ASoC: Intel: Add rt721-sdca support for PTL platform JIRA: https://issues.redhat.com/browse/RHEL-80681 commit f8199bbca5c5a6de9b8ca70f90811f2eefe413aa Author: Jack Yu Date: Tue Oct 8 08:57:30 2024 +0000 ASoC: Intel: Add rt721-sdca support for PTL platform Add rt721-sdca support for PTL platform. Signed-off-by: Jack Yu Reviewed-by: Bard Liao Link: https://patch.msgid.link/cc2158ad467f45068bb3556ecb5a814d@realtek.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/intel/boards/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index fbdc2a2cb12b..f4310e4f1d1b 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -688,6 +688,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH select SND_SOC_RT712_SDCA_DMIC_SDW select SND_SOC_RT715_SDW select SND_SOC_RT715_SDCA_SDW + select SND_SOC_RT721_SDCA_SDW select SND_SOC_RT722_SDCA_SDW select SND_SOC_RT1308_SDW select SND_SOC_RT1308 From 639535a2cbcbd7c75cb53d577bcceaadd2933212 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:31:44 +0100 Subject: [PATCH 082/256] ASoC: qcom: sm8250: correct typo in shutdown function name JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 2aab7d186bf10d1591e7645ca32cddeeb4dcaf20 Author: Krzysztof Kozlowski Date: Thu Oct 10 07:04:51 2024 +0200 ASoC: qcom: sm8250: correct typo in shutdown function name The function is for sm8250, so fix the odd number in "sm2450" prefix for soc ops shutdown callback. No functional impact. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20241010050451.11913-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/qcom/sm8250.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c index 2169ef3acec3..a1ff8d770958 100644 --- a/sound/soc/qcom/sm8250.c +++ b/sound/soc/qcom/sm8250.c @@ -79,7 +79,7 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream) return qcom_snd_sdw_startup(substream); } -static void sm2450_snd_shutdown(struct snd_pcm_substream *substream) +static void sm8250_snd_shutdown(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); @@ -124,7 +124,7 @@ static int sm8250_snd_hw_free(struct snd_pcm_substream *substream) static const struct snd_soc_ops sm8250_be_ops = { .startup = sm8250_snd_startup, - .shutdown = sm2450_snd_shutdown, + .shutdown = sm8250_snd_shutdown, .hw_params = sm8250_snd_hw_params, .hw_free = sm8250_snd_hw_free, .prepare = sm8250_snd_prepare, From 6dcff9abc9f006f9976ba3e9587d788947389d39 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:31:44 +0100 Subject: [PATCH 083/256] ASoC: rt721-sdca: Clean logically deadcode in rt721-sdca.c JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 8658c4eb9d6b76311322c1b74b3d4e0dec3599d8 Author: Everest K.C Date: Tue Oct 8 17:44:20 2024 -0600 ASoC: rt721-sdca: Clean logically deadcode in rt721-sdca.c As the same condition was checked in inner and outer if statements. The code never reaches the inner else statement. This issue was reported by Coverity Scan with CID = 1600271. Signed-off-by: Everest K.C. Link: https://patch.msgid.link/20241008234422.5274-1-everestkc@everestkc.com.np Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/rt721-sdca.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt721-sdca.c b/sound/soc/codecs/rt721-sdca.c index 201cb667c8c1..bdd160b80b64 100644 --- a/sound/soc/codecs/rt721-sdca.c +++ b/sound/soc/codecs/rt721-sdca.c @@ -611,12 +611,8 @@ static int rt721_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol, if (!adc_vol_flag) /* boost gain */ ctl = regvalue / boost_step; - else { /* ADC gain */ - if (adc_vol_flag) - ctl = p->max - (((vol_max - regvalue) & 0xffff) / interval_offset); - else - ctl = p->max - (((0 - regvalue) & 0xffff) / interval_offset); - } + else /* ADC gain */ + ctl = p->max - (((vol_max - regvalue) & 0xffff) / interval_offset); ucontrol->value.integer.value[i] = ctl; } From fbd112c08ff59fdbcf206616df4180fd5535f3fd Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:04 +0100 Subject: [PATCH 084/256] soundwire: cadence: clear MCP BLOCK_WAKEUP in init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 830f1aa53c0287eae667fa5f0a690bec34a10a3f Author: Pierre-Louis Bossart Date: Thu Oct 3 17:48:30 2024 +0800 soundwire: cadence: clear MCP BLOCK_WAKEUP in init Follow recommended programming flows. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003094830.119673-3-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/cadence_master.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 05652e983539..c7bd9a839052 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -1400,6 +1400,11 @@ int sdw_cdns_init(struct sdw_cdns *cdns) cdns_ip_updatel(cdns, CDNS_IP_MCP_CONTROL, CDNS_IP_MCP_CONTROL_CMD_ACCEPT, CDNS_IP_MCP_CONTROL_CMD_ACCEPT); + /* disable wakeup */ + cdns_ip_updatel(cdns, CDNS_IP_MCP_CONTROL, + CDNS_IP_MCP_CONTROL_BLOCK_WAKEUP, + 0); + /* Configure mcp config */ val = cdns_readl(cdns, CDNS_MCP_CONFIG); From f06446a1df8ecf6eb4bca5246c731fe9491c1c69 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:04 +0100 Subject: [PATCH 085/256] soundwire: cadence: add soft-reset on startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 6124a4063b8083e4d973f60c09ddb7abdbabe57f Author: Pierre-Louis Bossart Date: Thu Oct 3 17:48:29 2024 +0800 soundwire: cadence: add soft-reset on startup Follow the recommended programming flows. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20241003094830.119673-2-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- drivers/soundwire/cadence_master.c | 25 +++++++++++++++++++++++++ drivers/soundwire/cadence_master.h | 1 + drivers/soundwire/intel_bus_common.c | 6 ++++++ 3 files changed, 32 insertions(+) diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index c7bd9a839052..f367670ea991 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -1377,6 +1377,31 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, ssp_interval); } +/** + * sdw_cdns_soft_reset() - Cadence soft-reset + * @cdns: Cadence instance + */ +int sdw_cdns_soft_reset(struct sdw_cdns *cdns) +{ + int ret; + + cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_SOFT_RST, + CDNS_MCP_CONTROL_SOFT_RST); + + ret = cdns_config_update(cdns); + if (ret < 0) { + dev_err(cdns->dev, "%s: config update failed\n", __func__); + return ret; + } + + ret = cdns_set_wait(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_SOFT_RST, 0); + if (ret < 0) + dev_err(cdns->dev, "%s: Soft Reset timed out\n", __func__); + + return ret; +} +EXPORT_SYMBOL(sdw_cdns_soft_reset); + /** * sdw_cdns_init() - Cadence initialization * @cdns: Cadence instance diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h index e1d7969ba48a..c34fb050fe4f 100644 --- a/drivers/soundwire/cadence_master.h +++ b/drivers/soundwire/cadence_master.h @@ -168,6 +168,7 @@ int sdw_cdns_probe(struct sdw_cdns *cdns); irqreturn_t sdw_cdns_irq(int irq, void *dev_id); irqreturn_t sdw_cdns_thread(int irq, void *dev_id); +int sdw_cdns_soft_reset(struct sdw_cdns *cdns); int sdw_cdns_init(struct sdw_cdns *cdns); int sdw_cdns_pdi_init(struct sdw_cdns *cdns, struct sdw_cdns_stream_config config); diff --git a/drivers/soundwire/intel_bus_common.c b/drivers/soundwire/intel_bus_common.c index d3ff6c65b64c..ad1f8ebdbfc9 100644 --- a/drivers/soundwire/intel_bus_common.c +++ b/drivers/soundwire/intel_bus_common.c @@ -16,6 +16,12 @@ int intel_start_bus(struct sdw_intel *sdw) struct sdw_bus *bus = &cdns->bus; int ret; + ret = sdw_cdns_soft_reset(cdns); + if (ret < 0) { + dev_err(dev, "%s: unable to soft-reset Cadence IP: %d\n", __func__, ret); + return ret; + } + /* * follow recommended programming flows to avoid timeouts when * gsync is enabled From f00724a3abeaa713bb918e224ec7544ab396a057 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:04 +0100 Subject: [PATCH 086/256] ALSA: firewire: Remove unused cmp_connection_update JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1e280053dd4d8fb63eba7cff23105d76cc338f7d Author: Dr. David Alan Gilbert Date: Wed Oct 9 01:36:53 2024 +0100 ALSA: firewire: Remove unused cmp_connection_update cmp_connection_update() has been unused since 2019's commit 7eb7b18e9fc7 ("ALSA: fireworks: code refactoring for bus reset handler") Remove it. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Takashi Sakamoto Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20241009003653.254753-1-linux@treblig.org Signed-off-by: Jaroslav Kysela --- sound/firewire/cmp.c | 47 -------------------------------------------- sound/firewire/cmp.h | 1 - 2 files changed, 48 deletions(-) diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c index b596bec19774..f5028a061a91 100644 --- a/sound/firewire/cmp.c +++ b/sound/firewire/cmp.c @@ -333,53 +333,6 @@ retry_after_bus_reset: } EXPORT_SYMBOL(cmp_connection_establish); -/** - * cmp_connection_update - update the connection after a bus reset - * @c: the connection manager - * - * This function must be called from the driver's .update handler to - * reestablish any connection that might have been active. - * - * Returns zero on success, or a negative error code. On an error, the - * connection is broken and the caller must stop transmitting iso packets. - */ -int cmp_connection_update(struct cmp_connection *c) -{ - int err; - - mutex_lock(&c->mutex); - - if (!c->connected) { - mutex_unlock(&c->mutex); - return 0; - } - - err = fw_iso_resources_update(&c->resources); - if (err < 0) - goto err_unconnect; - - if (c->direction == CMP_OUTPUT) - err = pcr_modify(c, opcr_set_modify, pcr_set_check, - SUCCEED_ON_BUS_RESET); - else - err = pcr_modify(c, ipcr_set_modify, pcr_set_check, - SUCCEED_ON_BUS_RESET); - - if (err < 0) - goto err_unconnect; - - mutex_unlock(&c->mutex); - - return 0; - -err_unconnect: - c->connected = false; - mutex_unlock(&c->mutex); - - return err; -} -EXPORT_SYMBOL(cmp_connection_update); - static __be32 pcr_break_modify(struct cmp_connection *c, __be32 pcr) { return pcr & ~cpu_to_be32(PCR_BCAST_CONN | PCR_P2P_CONN_MASK); diff --git a/sound/firewire/cmp.h b/sound/firewire/cmp.h index 26ab88000e34..66fc08b742d2 100644 --- a/sound/firewire/cmp.h +++ b/sound/firewire/cmp.h @@ -47,7 +47,6 @@ int cmp_connection_reserve(struct cmp_connection *connection, void cmp_connection_release(struct cmp_connection *connection); int cmp_connection_establish(struct cmp_connection *connection); -int cmp_connection_update(struct cmp_connection *connection); void cmp_connection_break(struct cmp_connection *connection); #endif From 4549d2cc8562ca8098bedd1509a8ba680b907a44 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:05 +0100 Subject: [PATCH 087/256] ALSA: ice1712: Remove redundant code in stac9460_dac_vol_put JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0498a04e399c6e720bb991db992174e19b2fe980 Author: Zhu Jun Date: Tue Oct 8 23:53:45 2024 -0700 ALSA: ice1712: Remove redundant code in stac9460_dac_vol_put The variable 'ovol' is never referenced in the code, just remove it. Signed-off-by: Zhu Jun Link: https://patch.msgid.link/20241009065345.6669-1-zhujun2@cmss.chinamobile.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/ice1712/prodigy192.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index 096ec76f5304..a12dafbf53ab 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c @@ -170,14 +170,9 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el tmp = stac9460_get(ice, idx); ovol = 0x7f - (tmp & 0x7f); change = (ovol != nvol); - if (change) { - ovol = (0x7f - nvol) | (tmp & 0x80); - /* - dev_dbg(ice->card->dev, "DAC Volume: reg 0x%02x: 0x%02x\n", - idx, ovol); - */ + if (change) stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); - } + return change; } From 109488793c9ffb6c5b0a30445f5c75d40a6e5188 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:05 +0100 Subject: [PATCH 088/256] ALSA: usb-audio: Use snprintf instead of sprintf in build_mixer_unit_ctl JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0845b3e0d5c1a8ddf2056a0f2672ddf769dc446c Author: Zhu Jun Date: Wed Oct 9 00:09:44 2024 -0700 ALSA: usb-audio: Use snprintf instead of sprintf in build_mixer_unit_ctl Simplified code by removing redundant assignment of sprintf return value and improved safety by replacing sprintf with snprintf. Signed-off-by: Zhu Jun Link: https://patch.msgid.link/20241009070944.6937-1-zhujun2@cmss.chinamobile.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/usb/mixer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 0591da283926..66976be06bc0 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2197,7 +2197,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state, len = get_term_name(state->chip, iterm, kctl->id.name, sizeof(kctl->id.name), 0); if (!len) - len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); + snprintf(kctl->id.name, sizeof(kctl->id.name), "Mixer Source %d", in_ch + 1); + append_ctl_name(kctl, " Volume"); usb_audio_dbg(state->chip, "[%d] MU [%s] ch = %d, val = %d/%d\n", From 1ae8865de6e36cf2deec709c692f65714e46fc4b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:05 +0100 Subject: [PATCH 089/256] ASoC: imx-card: Set mclk for codec JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 892373e4de626c61e91816e3d3970d82beb50c4b Author: Chancel Liu Date: Wed Oct 9 15:46:43 2024 +0800 ASoC: imx-card: Set mclk for codec In some cases, ASoC machine driver may modify the mclk frequency according to sample rate but the value in codec is still initial frequency which should be replaced. For example, we should update mclk before setup for cs42xx8 mclk relating registers. Signed-off-by: Chancel Liu Signed-off-by: Shengjiu Wang Reviewed-by: Iuliana Prodan Link: https://patch.msgid.link/1728460004-364-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/fsl/imx-card.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index a7215bad6484..2f3dbbd15791 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -370,6 +370,11 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, dev_err(dev, "failed to set cpui dai mclk1 rate (%lu): %d\n", mclk_freq, ret); return ret; } + ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) { + dev_err(dev, "failed to set codec dai mclk rate (%lu): %d\n", mclk_freq, ret); + return ret; + } return 0; } From c96ab94ca7b5cc242089ccf7b3fd1ec8dc7f08a5 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:05 +0100 Subject: [PATCH 090/256] ASoC: imx-card: Add CS42888 support JIRA: https://issues.redhat.com/browse/RHEL-80681 commit b39eec95b84d5dc326c3d7c89e4e08b898dbc73c Author: Chancel Liu Date: Wed Oct 9 15:46:44 2024 +0800 ASoC: imx-card: Add CS42888 support CS42888 codec provides 4 multi-bit ADC and 8 multi-bit DAC. Add support for this codec in imx-card ASoC machine driver. Signed-off-by: Chancel Liu Signed-off-by: Shengjiu Wang Reviewed-by: Iuliana Prodan Link: https://patch.msgid.link/1728460004-364-3-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/fsl/imx-card.c | 54 ++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index 2f3dbbd15791..306168b164d3 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -25,6 +25,7 @@ enum codec_type { CODEC_AK4458, CODEC_AK4497, CODEC_AK5552, + CODEC_CS42888, }; /* @@ -185,6 +186,16 @@ static struct imx_akcodec_tdm_fs_mul ak5558_tdm_fs_mul[] = { { .min = 512, .max = 512, .mul = 1024 }, }; +static struct imx_akcodec_fs_mul cs42888_fs_mul[] = { + { .rmin = 8000, .rmax = 48000, .wmin = 256, .wmax = 1024, }, + { .rmin = 64000, .rmax = 96000, .wmin = 128, .wmax = 512, }, + { .rmin = 176400, .rmax = 192000, .wmin = 64, .wmax = 256, }, +}; + +static struct imx_akcodec_tdm_fs_mul cs42888_tdm_fs_mul[] = { + { .min = 256, .max = 256, .mul = 256 }, +}; + static const u32 akcodec_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, 705600, 768000, @@ -210,6 +221,14 @@ static const u32 ak5558_tdm_channels[] = { 1, 2, 3, 4, 5, 6, 7, 8, }; +static const u32 cs42888_channels[] = { + 1, 2, 4, 6, 8, +}; + +static const u32 cs42888_tdm_channels[] = { + 1, 2, 3, 4, 5, 6, 7, 8, +}; + static bool format_is_dsd(struct snd_pcm_hw_params *params) { snd_pcm_format_t format = params_format(params); @@ -241,6 +260,7 @@ static bool codec_is_akcodec(unsigned int type) case CODEC_AK4497: case CODEC_AK5558: case CODEC_AK5552: + case CODEC_CS42888: return true; default: break; @@ -340,13 +360,15 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, return ret; } - ret = snd_soc_dai_set_tdm_slot(codec_dai, - BIT(slots) - 1, - BIT(slots) - 1, - slots, slot_width); - if (ret && ret != -ENOTSUPP) { - dev_err(dev, "failed to set codec dai[%d] tdm slot: %d\n", i, ret); - return ret; + if (format_is_tdm(link_data)) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, + BIT(slots) - 1, + BIT(slots) - 1, + slots, slot_width); + if (ret && ret != -ENOTSUPP) { + dev_err(dev, "failed to set codec dai[%d] tdm slot: %d\n", i, ret); + return ret; + } } } @@ -609,6 +631,8 @@ static int imx_card_parse_of(struct imx_card_data *data) plat_data->type = CODEC_AK5558; else if (!strcmp(link->codecs->dai_name, "ak5552-aif")) plat_data->type = CODEC_AK5552; + else if (!strcmp(link->codecs->dai_name, "cs42888")) + plat_data->type = CODEC_CS42888; } else { link->codecs = &snd_soc_dummy_dlc; @@ -766,6 +790,12 @@ static int imx_card_probe(struct platform_device *pdev) data->dapm_routes[i].sink = "ASRC-Capture"; data->dapm_routes[i].source = "CPU-Capture"; break; + case CODEC_CS42888: + data->dapm_routes[0].sink = "Playback"; + data->dapm_routes[0].source = "CPU-Playback"; + data->dapm_routes[1].sink = "CPU-Capture"; + data->dapm_routes[1].source = "Capture"; + break; default: break; } @@ -805,6 +835,16 @@ static int imx_card_probe(struct platform_device *pdev) plat_data->support_tdm_channels = ak5558_tdm_channels; plat_data->num_tdm_channels = ARRAY_SIZE(ak5558_tdm_channels); break; + case CODEC_CS42888: + plat_data->fs_mul = cs42888_fs_mul; + plat_data->num_fs_mul = ARRAY_SIZE(cs42888_fs_mul); + plat_data->tdm_fs_mul = cs42888_tdm_fs_mul; + plat_data->num_tdm_fs_mul = ARRAY_SIZE(cs42888_tdm_fs_mul); + plat_data->support_channels = cs42888_channels; + plat_data->num_channels = ARRAY_SIZE(cs42888_channels); + plat_data->support_tdm_channels = cs42888_tdm_channels; + plat_data->num_tdm_channels = ARRAY_SIZE(cs42888_tdm_channels); + break; default: break; } From 148cd5b8d5af32bf6df0a6cee981308445b9ac4c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:05 +0100 Subject: [PATCH 091/256] ASoC: SOF: Intel: hda-mlink: expose unlocked interrupt enable routine JIRA: https://issues.redhat.com/browse/RHEL-80681 commit eac79786c7397925149a1bfc4bb704777cd42a99 Author: Pierre-Louis Bossart Date: Mon Oct 7 20:12:40 2024 +0800 ASoC: SOF: Intel: hda-mlink: expose unlocked interrupt enable routine When the eml_lock is already taken, we need an unlocked version. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Liam Girdwood Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241007121241.30914-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/hda-mlink.h | 4 ++++ sound/soc/sof/intel/hda-mlink.c | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index 9ced94686ce3..6774f4b9e5fc 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -15,6 +15,7 @@ int hda_bus_ml_init(struct hdac_bus *bus); void hda_bus_ml_free(struct hdac_bus *bus); int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid); +void hdac_bus_eml_enable_interrupt_unlocked(struct hdac_bus *bus, bool alt, int elid, bool enable); void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable); bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid); @@ -71,6 +72,9 @@ static inline void hda_bus_ml_free(struct hdac_bus *bus) { } static inline int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) { return 0; } +static inline void +hdac_bus_eml_enable_interrupt_unlocked(struct hdac_bus *bus, bool alt, int elid, bool enable) { } + static inline void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable) { } diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 9a3559c78b62..46f89d6d06f8 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -481,6 +481,24 @@ int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) } EXPORT_SYMBOL_NS(hdac_bus_eml_get_count, SND_SOC_SOF_HDA_MLINK); +void hdac_bus_eml_enable_interrupt_unlocked(struct hdac_bus *bus, bool alt, int elid, bool enable) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return; + + if (!h2link->intc) + return; + + hlink = &h2link->hext_link; + + hdaml_link_enable_interrupt(hlink->ml_addr + AZX_REG_ML_LCTL, enable); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_enable_interrupt_unlocked, SND_SOC_SOF_HDA_MLINK); + void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable) { struct hdac_ext2_link *h2link; From 4abfd262beeab45d950732df2b332eddaa13d267 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:06 +0100 Subject: [PATCH 092/256] ASoC/SoundWire: Intel: lnl: enable interrupts after first power-up/before last power-down JIRA: https://issues.redhat.com/browse/RHEL-80681 commit e0941775e6bdcf45e6e20b7ff3bb87dbb7d92fbb Author: Pierre-Louis Bossart Date: Mon Oct 7 20:12:41 2024 +0800 ASoC/SoundWire: Intel: lnl: enable interrupts after first power-up/before last power-down The HDaudio mlink support makes it more logical to couple interrupt enabling/disabling with power-up/down sequences. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Liam Girdwood Signed-off-by: Bard Liao Acked-by: Vinod Koul Link: https://patch.msgid.link/20241007121241.30914-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- drivers/soundwire/intel_ace2x.c | 7 +++++++ sound/soc/sof/intel/hda-dsp.c | 5 ----- sound/soc/sof/intel/hda.c | 2 -- sound/soc/sof/intel/lnl.c | 10 ---------- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c index 4f3dd70d6a1a..a005b63582e9 100644 --- a/drivers/soundwire/intel_ace2x.c +++ b/drivers/soundwire/intel_ace2x.c @@ -175,6 +175,9 @@ static int intel_link_power_up(struct sdw_intel *sdw) __func__, ret); goto out; } + + hdac_bus_eml_enable_interrupt_unlocked(sdw->link_res->hbus, true, + AZX_REG_ML_LEPTR_ID_SDW, true); } *shim_mask |= BIT(link_id); @@ -201,6 +204,10 @@ static int intel_link_power_down(struct sdw_intel *sdw) *shim_mask &= ~BIT(link_id); + if (!*shim_mask) + hdac_bus_eml_enable_interrupt_unlocked(sdw->link_res->hbus, true, + AZX_REG_ML_LEPTR_ID_SDW, false); + ret = hdac_bus_eml_sdw_power_down_unlocked(sdw->link_res->hbus, link_id); if (ret < 0) { dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_power_down failed: %d\n", diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 4c88522d4048..6028a80418bb 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -858,7 +858,6 @@ skip_dsp: static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) { - const struct sof_intel_dsp_desc *chip; int ret; /* display codec must be powered before link reset */ @@ -891,10 +890,6 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) hda_dsp_ctrl_ppcap_int_enable(sdev, true); } - chip = get_chip_info(sdev->pdata); - if (chip && chip->hw_ip_version >= SOF_INTEL_ACE_2_0) - hda_sdw_int_enable(sdev, true); - cleanup: /* display codec can powered off after controller init */ hda_codec_i915_display_power(sdev, false); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index d0a41e8e6334..b901a9c66c3f 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -866,8 +866,6 @@ skip_dsp_setup: dev_err(sdev->dev, "could not startup SoundWire links\n"); goto disable_pp_cap; } - - hda_sdw_int_enable(sdev, true); } init_waitqueue_head(&hdev->waitq); diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 3d5a1f8b17e5..e3c4b4a0d705 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -192,16 +192,8 @@ static bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev) return hdac_bus_eml_check_interrupt(bus, true, AZX_REG_ML_LEPTR_ID_SDW); } -static void lnl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) -{ - struct hdac_bus *bus = sof_to_bus(sdev); - - hdac_bus_eml_enable_interrupt(bus, true, AZX_REG_ML_LEPTR_ID_SDW, enable); -} - static int lnl_dsp_disable_interrupts(struct snd_sof_dev *sdev) { - lnl_enable_sdw_irq(sdev, false); mtl_disable_ipc_interrupts(sdev); return mtl_enable_interrupts(sdev, false); } @@ -237,7 +229,6 @@ const struct sof_intel_dsp_desc lnl_chip_info = { .ssp_count = MTL_SSP_COUNT, .d0i3_offset = MTL_HDA_VS_D0I3C, .read_sdw_lcount = hda_sdw_check_lcount_ext, - .enable_sdw_irq = lnl_enable_sdw_irq, .check_sdw_irq = lnl_dsp_check_sdw_irq, .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, .sdw_process_wakeen = hda_sdw_process_wakeen_common, @@ -262,7 +253,6 @@ const struct sof_intel_dsp_desc ptl_chip_info = { .ssp_count = MTL_SSP_COUNT, .d0i3_offset = MTL_HDA_VS_D0I3C, .read_sdw_lcount = hda_sdw_check_lcount_ext, - .enable_sdw_irq = lnl_enable_sdw_irq, .check_sdw_irq = lnl_dsp_check_sdw_irq, .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, .check_ipc_irq = mtl_dsp_check_ipc_irq, From 304aa8cc9351ff1fedb6a28991de76575269d113 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:33 +0100 Subject: [PATCH 093/256] ALSA: hda: Fix all stream interrupts definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 52345d35622026b99271edc1c58ad7cfef3b7567 Author: Amadeusz SÅ‚awiÅ„ski Date: Mon Oct 14 11:49:58 2024 +0200 ALSA: hda: Fix all stream interrupts definition It is defined in header to 0xFF, which only allows to set values for 8 streams. In specification it is defined as bits from 0 to 29. In practice there is no HW with 29 streams, but as the only place where the value is used is chip initialization, it is best to make sure that all bits are reset properly. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz SÅ‚awiÅ„ski Link: https://patch.msgid.link/20241014094958.708563-1-amadeuszx.slawinski@linux.intel.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/hda_register.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h index 5ff31e6d41c1..db1cc0b897fd 100644 --- a/include/sound/hda_register.h +++ b/include/sound/hda_register.h @@ -180,7 +180,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ /* INTCTL and INTSTS */ -#define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */ +#define AZX_INT_ALL_STREAM 0x3fffffff /* all stream interrupts */ #define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ #define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ From f8c43b0973b2b0dfae624e75543986024453785c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:33 +0100 Subject: [PATCH 094/256] ASoC: rt-sdw-common: Enhance switch case to prevent uninitialized variable JIRA: https://issues.redhat.com/browse/RHEL-80681 commit c6631ceea573ae364e4fe913045f2aad10a10784 Author: Jack Yu Date: Mon Oct 14 09:55:20 2024 +0000 ASoC: rt-sdw-common: Enhance switch case to prevent uninitialized variable If det_mode is not 0, 3 or 5 then function will return jack_type with an uninitialzed value. Enhance switch case to prevent uninitialized variable issue. Signed-off-by: Jack Yu Link: https://patch.msgid.link/8631337239d744088d56caab2d8f39cb@realtek.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/rt-sdw-common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt-sdw-common.c b/sound/soc/codecs/rt-sdw-common.c index a422da6cf702..9f51fec383f9 100644 --- a/sound/soc/codecs/rt-sdw-common.c +++ b/sound/soc/codecs/rt-sdw-common.c @@ -150,15 +150,15 @@ int rt_sdca_headset_detect(struct regmap *map, unsigned int entity_id) goto io_error; switch (det_mode) { - case 0x00: - jack_type = 0; - break; case 0x03: jack_type = SND_JACK_HEADPHONE; break; case 0x05: jack_type = SND_JACK_HEADSET; break; + default: + jack_type = 0; + break; } /* write selected_mode */ From 4512d4dbadb375fd70f3081c14ef0cc87908ccad Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:34 +0100 Subject: [PATCH 095/256] mfd: cs42l43: Fix issues in probe error paths JIRA: https://issues.redhat.com/browse/RHEL-80681 commit e59148b784fbab0354e72dc4fd454def6f160810 Author: Charles Keepax Date: Wed Oct 2 13:13:11 2024 +0100 mfd: cs42l43: Fix issues in probe error paths The error path in cs42l43_boot_work() will lead to an unbalanced regulator put, when the driver is removed. Fix this by relying on remove to power down the device. Also the boot work needs to be synchronised with driver remove, to ensure the work is not still running after the driver has been removed. Add the required cancel_work_sync(). Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20241002121311.162691-1-ckeepax@opensource.cirrus.com Signed-off-by: Lee Jones Signed-off-by: Jaroslav Kysela --- drivers/mfd/cs42l43.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/cs42l43.c b/drivers/mfd/cs42l43.c index ae8fd37afb75..3b4efb294471 100644 --- a/drivers/mfd/cs42l43.c +++ b/drivers/mfd/cs42l43.c @@ -967,7 +967,6 @@ static void cs42l43_boot_work(struct work_struct *work) err: pm_runtime_put_sync(cs42l43->dev); - cs42l43_dev_remove(cs42l43); } static int cs42l43_power_up(struct cs42l43 *cs42l43) @@ -1101,6 +1100,8 @@ EXPORT_SYMBOL_NS_GPL(cs42l43_dev_probe, MFD_CS42L43); void cs42l43_dev_remove(struct cs42l43 *cs42l43) { + cancel_work_sync(&cs42l43->boot_work); + cs42l43_power_down(cs42l43); } EXPORT_SYMBOL_NS_GPL(cs42l43_dev_remove, MFD_CS42L43); From e8240288a21252e1dd82088f52c2c466821f58db Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:34 +0100 Subject: [PATCH 096/256] ASoC: makes snd_soc_set_runtime_hwparams() inline JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0d3039f4d2f4a79798d97f2ac1a9656b055b561f Author: Kuninori Morimoto Date: Wed Oct 16 01:35:27 2024 +0000 ASoC: makes snd_soc_set_runtime_hwparams() inline snd_soc_set_runtime_hwparams() is now doing very simple things. We can makes it simply inline function, without having EXPORT_SYMBOL_GPL() Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cyk0eso0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/soc.h | 9 +++++++-- sound/soc/soc-pcm.c | 16 ---------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 61e05cc8cbb3..1d015a47c4ce 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -531,8 +531,13 @@ int snd_soc_tdm_params_to_bclk(const struct snd_pcm_hw_params *params, int tdm_width, int tdm_slots, int slot_multiple); /* set runtime hw params */ -int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, - const struct snd_pcm_hardware *hw); +static inline int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, + const struct snd_pcm_hardware *hw) +{ + substream->runtime->hw = *hw; + + return 0; +} struct snd_ac97 *snd_soc_alloc_ac97_component(struct snd_soc_component *component); struct snd_ac97 *snd_soc_new_ac97_component(struct snd_soc_component *component, diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7a59121fc323..e2c5300df0f2 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -416,22 +416,6 @@ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) return true; } -/** - * snd_soc_set_runtime_hwparams - set the runtime hardware parameters - * @substream: the pcm substream - * @hw: the hardware parameters - * - * Sets the substream runtime hardware parameters. - */ -int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, - const struct snd_pcm_hardware *hw) -{ - substream->runtime->hw = *hw; - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams); - /* DPCM stream event, send event to FE and all active BEs. */ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event) From e6523babeffe4bfb59accb696702f8d659af16c3 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:34 +0100 Subject: [PATCH 097/256] ASoC: codecs: Remove unneeded semicolon JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7bc18a78157997575d8260bd922fff11fb5f21df Author: Yang Li Date: Thu Oct 17 13:19:09 2024 +0800 ASoC: codecs: Remove unneeded semicolon This patch removes an unneeded semicolon after a switch statement. ./sound/soc/codecs/ntp8835.c:280:2-3: Unneeded semicolon Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=11404 Signed-off-by: Yang Li Link: https://patch.msgid.link/20241017051909.4638-1-yang.lee@linux.alibaba.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/ntp8835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/ntp8835.c b/sound/soc/codecs/ntp8835.c index 97056d8de2bb..800bda6b49dd 100644 --- a/sound/soc/codecs/ntp8835.c +++ b/sound/soc/codecs/ntp8835.c @@ -277,7 +277,7 @@ static int ntp8835_set_component_sysclk(struct snd_soc_component *component, ntp8835->mclk_rate = 0; dev_err(component->dev, "Unsupported MCLK value: %u", freq); return -EINVAL; - }; + } return 0; } From 5004b06700bd84d19dab9ca10e8e7d86f3d7abda Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:59 +0100 Subject: [PATCH 098/256] soundwire: sdw_intel: include linux/acpi.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit f35533a0e60946ee3fb8adccf8a36024c6f1fe40 Author: Bard Liao Date: Wed Oct 16 18:23:23 2024 +0800 soundwire: sdw_intel: include linux/acpi.h For the acpi_handle stuff. Signed-off-by: Bard Liao Reviewed-by: Péter Ujfalusi Acked-by: Vinod Koul Link: https://patch.msgid.link/20241016102333.294448-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/linux/soundwire/sdw_intel.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h index 734dc1fa3b5b..1019ea0376b4 100644 --- a/include/linux/soundwire/sdw_intel.h +++ b/include/linux/soundwire/sdw_intel.h @@ -4,6 +4,7 @@ #ifndef __SDW_INTEL_H #define __SDW_INTEL_H +#include #include #include From 9482b44ff1f597519d817f136d3883da8e9fa8ec Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:59 +0100 Subject: [PATCH 099/256] ASoC/soundwire: remove sdw_slave_extended_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 4b224ff80d6609811ec6ab5406a16c92825cfb1a Author: Pierre-Louis Bossart Date: Wed Oct 16 18:23:24 2024 +0800 ASoC/soundwire: remove sdw_slave_extended_id This structure is used to copy information from the 'sdw_slave' structures, it's better to create a flexible array of 'sdw_slave' pointers and directly access the information. This will also help access additional information stored in the 'sdw_slave' structure, such as an SDCA context. This patch does not add new functionality, it only modified how the information is retrieved. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241016102333.294448-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- drivers/soundwire/amd_init.c | 12 ++++++------ drivers/soundwire/intel_init.c | 13 ++++++------- include/linux/soundwire/sdw.h | 6 +++--- include/linux/soundwire/sdw_amd.h | 7 ++----- include/linux/soundwire/sdw_intel.h | 7 ++----- include/sound/soc-acpi.h | 3 +-- sound/soc/amd/ps/pci-ps.c | 3 +-- sound/soc/soc-acpi.c | 30 +++++++++++++++-------------- sound/soc/sof/amd/acp-common.c | 3 +-- sound/soc/sof/intel/hda.c | 16 ++++++++------- 10 files changed, 47 insertions(+), 53 deletions(-) diff --git a/drivers/soundwire/amd_init.c b/drivers/soundwire/amd_init.c index 4f6e356e6bd2..d11b60efda33 100644 --- a/drivers/soundwire/amd_init.c +++ b/drivers/soundwire/amd_init.c @@ -178,7 +178,7 @@ EXPORT_SYMBOL_NS(sdw_amd_probe, SOUNDWIRE_AMD_INIT); void sdw_amd_exit(struct sdw_amd_ctx *ctx) { sdw_amd_cleanup(ctx); - kfree(ctx->ids); + kfree(ctx->peripherals); kfree(ctx); } EXPORT_SYMBOL_NS(sdw_amd_exit, SOUNDWIRE_AMD_INIT); @@ -205,10 +205,11 @@ int sdw_amd_get_slave_info(struct sdw_amd_ctx *ctx) num_slaves++; } - ctx->ids = kcalloc(num_slaves, sizeof(*ctx->ids), GFP_KERNEL); - if (!ctx->ids) + ctx->peripherals = kmalloc(struct_size(ctx->peripherals, array, num_slaves), + GFP_KERNEL); + if (!ctx->peripherals) return -ENOMEM; - ctx->num_slaves = num_slaves; + ctx->peripherals->num_peripherals = num_slaves; for (index = 0; index < ctx->count; index++) { if (!(ctx->link_mask & BIT(index))) continue; @@ -216,8 +217,7 @@ int sdw_amd_get_slave_info(struct sdw_amd_ctx *ctx) if (amd_manager) { bus = &amd_manager->bus; list_for_each_entry(slave, &bus->slaves, node) { - ctx->ids[i].id = slave->id; - ctx->ids[i].link_id = bus->link_id; + ctx->peripherals->array[i] = slave; i++; } } diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c index a09134b97cd6..12e7a98f319f 100644 --- a/drivers/soundwire/intel_init.c +++ b/drivers/soundwire/intel_init.c @@ -252,17 +252,16 @@ static struct sdw_intel_ctx num_slaves++; } - ctx->ids = kcalloc(num_slaves, sizeof(*ctx->ids), GFP_KERNEL); - if (!ctx->ids) + ctx->peripherals = kmalloc(struct_size(ctx->peripherals, array, num_slaves), + GFP_KERNEL); + if (!ctx->peripherals) goto err; - - ctx->num_slaves = num_slaves; + ctx->peripherals->num_peripherals = num_slaves; i = 0; list_for_each_entry(link, &ctx->link_list, list) { bus = &link->cdns->bus; list_for_each_entry(slave, &bus->slaves, node) { - ctx->ids[i].id = slave->id; - ctx->ids[i].link_id = bus->link_id; + ctx->peripherals->array[i] = slave; i++; } } @@ -371,7 +370,7 @@ void sdw_intel_exit(struct sdw_intel_ctx *ctx) } sdw_intel_cleanup(ctx); - kfree(ctx->ids); + kfree(ctx->peripherals); kfree(ctx->ldev); kfree(ctx); } diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 73f655334fe9..cacc3f431766 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -467,9 +467,9 @@ struct sdw_slave_id { __u8 sdw_version:4; }; -struct sdw_extended_slave_id { - int link_id; - struct sdw_slave_id id; +struct sdw_peripherals { + int num_peripherals; + struct sdw_slave *array[]; }; /* diff --git a/include/linux/soundwire/sdw_amd.h b/include/linux/soundwire/sdw_amd.h index c9586f22c5a9..799f8578137b 100644 --- a/include/linux/soundwire/sdw_amd.h +++ b/include/linux/soundwire/sdw_amd.h @@ -119,19 +119,16 @@ struct sdw_amd_acpi_info { * struct sdw_amd_ctx - context allocated by the controller driver probe * * @count: link count - * @num_slaves: total number of devices exposed across all enabled links * @link_mask: bit-wise mask listing SoundWire links reported by the * Controller - * @ids: array of slave_id, representing Slaves exposed across all enabled - * links * @pdev: platform device structure + * @peripherals: array representing Peripherals exposed across all enabled links */ struct sdw_amd_ctx { int count; - int num_slaves; u32 link_mask; - struct sdw_extended_slave_id *ids; struct platform_device *pdev[AMD_SDW_MAX_MANAGER_COUNT]; + struct sdw_peripherals *peripherals; }; /** diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h index 1019ea0376b4..580086417e4b 100644 --- a/include/linux/soundwire/sdw_intel.h +++ b/include/linux/soundwire/sdw_intel.h @@ -287,31 +287,28 @@ struct hdac_bus; * hardware capabilities after all power dependencies are settled. * @link_mask: bit-wise mask listing SoundWire links reported by the * Controller - * @num_slaves: total number of devices exposed across all enabled links * @handle: ACPI parent handle * @ldev: information for each link (controller-specific and kept * opaque here) - * @ids: array of slave_id, representing Slaves exposed across all enabled - * links * @link_list: list to handle interrupts across all links * @shim_lock: mutex to handle concurrent rmw access to shared SHIM registers. * @shim_mask: flags to track initialization of SHIM shared registers * @shim_base: sdw shim base. * @alh_base: sdw alh base. + * @peripherals: array representing Peripherals exposed across all enabled links */ struct sdw_intel_ctx { int count; void __iomem *mmio_base; u32 link_mask; - int num_slaves; acpi_handle handle; struct sdw_intel_link_dev **ldev; - struct sdw_extended_slave_id *ids; struct list_head link_list; struct mutex shim_lock; /* lock for access to shared SHIM registers */ u32 shim_mask; u32 shim_base; u32 alh_base; + struct sdw_peripherals *peripherals; }; /** diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index c1552bc6e31c..b80313e4b331 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -235,7 +235,6 @@ static inline bool snd_soc_acpi_sof_parent(struct device *dev) bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev, const struct snd_soc_acpi_link_adr *link, - struct sdw_extended_slave_id *ids, - int num_slaves); + struct sdw_peripherals *peripherals); #endif diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 9872c7597d71..cec97bcc98b6 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -303,8 +303,7 @@ static struct snd_soc_acpi_mach *acp63_sdw_machine_select(struct device *dev) link = mach->links; for (i = 0; i < acp_data->info.count && link->num_adr; link++, i++) { if (!snd_soc_acpi_sdw_link_slaves_found(dev, link, - acp_data->sdw->ids, - acp_data->sdw->num_slaves)) + acp_data->sdw->peripherals)) break; } if (i == acp_data->info.count || !link->num_adr) diff --git a/sound/soc/soc-acpi.c b/sound/soc/soc-acpi.c index 6d693b2ad5a3..270f9777942f 100644 --- a/sound/soc/soc-acpi.c +++ b/sound/soc/soc-acpi.c @@ -131,8 +131,7 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_codec_list); /* Check if all Slaves defined on the link can be found */ bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev, const struct snd_soc_acpi_link_adr *link, - struct sdw_extended_slave_id *ids, - int num_slaves) + struct sdw_peripherals *peripherals) { unsigned int part_id, link_id, unique_id, mfg_id, version; int i, j, k; @@ -146,22 +145,25 @@ bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev, link_id = SDW_DISCO_LINK_ID(adr); version = SDW_VERSION(adr); - for (j = 0; j < num_slaves; j++) { + for (j = 0; j < peripherals->num_peripherals; j++) { + struct sdw_slave *peripheral = peripherals->array[j]; + /* find out how many identical parts were reported on that link */ - if (ids[j].link_id == link_id && - ids[j].id.part_id == part_id && - ids[j].id.mfg_id == mfg_id && - ids[j].id.sdw_version == version) + if (peripheral->bus->link_id == link_id && + peripheral->id.part_id == part_id && + peripheral->id.mfg_id == mfg_id && + peripheral->id.sdw_version == version) reported_part_count++; } - for (j = 0; j < num_slaves; j++) { + for (j = 0; j < peripherals->num_peripherals; j++) { + struct sdw_slave *peripheral = peripherals->array[j]; int expected_part_count = 0; - if (ids[j].link_id != link_id || - ids[j].id.part_id != part_id || - ids[j].id.mfg_id != mfg_id || - ids[j].id.sdw_version != version) + if (peripheral->bus->link_id != link_id || + peripheral->id.part_id != part_id || + peripheral->id.mfg_id != mfg_id || + peripheral->id.sdw_version != version) continue; /* find out how many identical parts are expected */ @@ -180,7 +182,7 @@ bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev, */ unique_id = SDW_UNIQUE_ID(adr); if (reported_part_count == 1 || - ids[j].id.unique_id == unique_id) { + peripheral->id.unique_id == unique_id) { dev_dbg(dev, "found part_id %#x at link %d\n", part_id, link_id); break; } @@ -189,7 +191,7 @@ bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev, part_id, reported_part_count, expected_part_count, link_id); } } - if (j == num_slaves) { + if (j == peripherals->num_peripherals) { dev_dbg(dev, "Slave part_id %#x not found\n", part_id); return false; } diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c index dbcaac84cb73..fc792956bb97 100644 --- a/sound/soc/sof/amd/acp-common.c +++ b/sound/soc/sof/amd/acp-common.c @@ -145,8 +145,7 @@ static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev * link = mach->links; for (i = 0; i < acp_data->info.count && link->num_adr; link++, i++) { if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link, - acp_data->sdw->ids, - acp_data->sdw->num_slaves)) + acp_data->sdw->peripherals)) break; } if (i == acp_data->info.count || !link->num_adr) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index b901a9c66c3f..af53bc1936b3 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1065,7 +1065,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev { struct snd_sof_pdata *pdata = sdev->pdata; const struct snd_soc_acpi_link_adr *link; - struct sdw_extended_slave_id *ids; + struct sdw_peripherals *peripherals; struct snd_soc_acpi_mach *mach; struct sof_intel_hda_dev *hdev; u32 link_mask; @@ -1084,7 +1084,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev return NULL; } - if (!hdev->sdw->num_slaves) { + if (!hdev->sdw->peripherals || !hdev->sdw->peripherals->num_peripherals) { dev_warn(sdev->dev, "No SoundWire peripheral detected in ACPI tables\n"); return NULL; } @@ -1120,8 +1120,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev * are not found on this link. */ if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link, - hdev->sdw->ids, - hdev->sdw->num_slaves)) + hdev->sdw->peripherals)) break; } /* Found if all Slaves are checked */ @@ -1137,10 +1136,13 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev } dev_info(sdev->dev, "No SoundWire machine driver found for the ACPI-reported configuration:\n"); - ids = hdev->sdw->ids; - for (i = 0; i < hdev->sdw->num_slaves; i++) + peripherals = hdev->sdw->peripherals; + for (i = 0; i < peripherals->num_peripherals; i++) dev_info(sdev->dev, "link %d mfg_id 0x%04x part_id 0x%04x version %#x\n", - ids[i].link_id, ids[i].id.mfg_id, ids[i].id.part_id, ids[i].id.sdw_version); + peripherals->array[i]->bus->link_id, + peripherals->array[i]->id.mfg_id, + peripherals->array[i]->id.part_id, + peripherals->array[i]->id.sdw_version); return NULL; } From 5ac5ce69fbe02acd348bdd443434c73b02a179d6 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:32:59 +0100 Subject: [PATCH 100/256] ASoC: SDCA: add initial module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 3a513da1ae33972e59efeef7908061f1f24af480 Author: Pierre-Louis Bossart Date: Wed Oct 16 18:23:25 2024 +0800 ASoC: SDCA: add initial module Add new module for SDCA (SoundWire Device Class for Audio) support. For now just add a parser to identify the SDCA revision and the function mask. Note that the SDCA definitions and related MIPI DisCo properties are defined only for ACPI platforms and extracted with _DSD helpers. There is currently no support for Device Tree in the specification, the 'depends on ACPI' reflects this design limitation. This might change in a future revision of the specification but for SDCA 1.0 ACPI is the only supported type of platform firmware. The SDCA library is defined with static inline fallbacks, which will allow for unconditional addition of SDCA support in common parts of the code. The design follows a four-step process: 1) Basic information related to Functions is extracted from MIPI DisCo tables and stored in the 'struct sdw_slave'. Devm_ based memory allocation is not allowed at this point prior to a driver probe, so we only store the function node, address and type. 2) When a codec driver probes, it will register subdevices for each Function identified in phase 1) 3) a driver will probe for each subdevice and addition parsing/memory allocation takes place at this level. devm_ based allocation is highly encouraged to make error handling manageable. 4) Before the peripheral device becomes physically attached, register access is not permitted and the regmaps are cache-only. When peripheral device is enumerated, the bus level uses the 'update_status' notification; after optional device-level initialization, the codec driver will notify each of the subdevices so that they can start interacting with the hardware. Note that the context extracted in 1) should be arguably be handled completely in the codec driver probe. That would however make it difficult to use the ACPI information for machine quirks, and e.g. select different machine driver and topologies as done for the RT712_VB handling later in the series. To make the implementation of quirks simpler, this patchset extracts a minimal amount of context (interface revision and number/type of Functions) before the codec driver probe, and stores this context in the scope of the 'struct sdw_slave'. The SDCA library can also be used in a vendor-specific driver without creating subdevices, e.g. to retrieve the 'initialization-table' values to write platform-specific values as needed. For more technical details, the SDCA specification is available for public downloads at https://www.mipi.org/mipi-sdca-v1-0-download Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241016102333.294448-4-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/linux/soundwire/sdw.h | 3 + include/sound/sdca.h | 54 ++++++++++ include/sound/sdca_function.h | 55 ++++++++++ sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/sdca/Kconfig | 11 ++ sound/soc/sdca/Makefile | 5 + sound/soc/sdca/sdca_device.c | 24 +++++ sound/soc/sdca/sdca_functions.c | 173 ++++++++++++++++++++++++++++++++ 9 files changed, 327 insertions(+) create mode 100644 include/sound/sdca.h create mode 100644 include/sound/sdca_function.h create mode 100644 sound/soc/sdca/Kconfig create mode 100644 sound/soc/sdca/Makefile create mode 100644 sound/soc/sdca/sdca_device.c create mode 100644 sound/soc/sdca/sdca_functions.c diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index cacc3f431766..25db2b191e8f 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -10,6 +10,7 @@ #include #include #include +#include struct sdw_bus; struct sdw_slave; @@ -642,6 +643,7 @@ struct sdw_slave_ops { * @is_mockup_device: status flag used to squelch errors in the command/control * protocol for SoundWire mockup devices * @sdw_dev_lock: mutex used to protect callbacks/remove races + * @sdca_data: structure containing all device data for SDCA helpers */ struct sdw_slave { struct sdw_slave_id id; @@ -665,6 +667,7 @@ struct sdw_slave { bool first_interrupt_done; bool is_mockup_device; struct mutex sdw_dev_lock; /* protect callbacks/remove races */ + struct sdca_device_data sdca_data; }; #define dev_to_sdw_dev(_dev) container_of(_dev, struct sdw_slave, dev) diff --git a/include/sound/sdca.h b/include/sound/sdca.h new file mode 100644 index 000000000000..34473ca4c789 --- /dev/null +++ b/include/sound/sdca.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + * Copyright(c) 2024 Intel Corporation + */ + +#ifndef __SDCA_H__ +#define __SDCA_H__ + +struct sdw_slave; + +#define SDCA_MAX_FUNCTION_COUNT 8 + +/** + * sdca_device_desc - short descriptor for an SDCA Function + * @adr: ACPI address (used for SDCA register access) + * @type: Function topology type + * @name: human-readable string + */ +struct sdca_function_desc { + u64 adr; + u32 type; + const char *name; +}; + +/** + * sdca_device_data - structure containing all SDCA related information + * @sdca_interface_revision: value read from _DSD property, mainly to check + * for changes between silicon versions + * @num_functions: total number of supported SDCA functions. Invalid/unsupported + * functions will be skipped. + * @sdca_func: array of function descriptors + */ +struct sdca_device_data { + u32 interface_revision; + int num_functions; + struct sdca_function_desc sdca_func[SDCA_MAX_FUNCTION_COUNT]; +}; + +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA) + +void sdca_lookup_functions(struct sdw_slave *slave); +void sdca_lookup_interface_revision(struct sdw_slave *slave); + +#else + +static inline void sdca_lookup_functions(struct sdw_slave *slave) {} +static inline void sdca_lookup_interface_revision(struct sdw_slave *slave) {} + +#endif + +#endif diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h new file mode 100644 index 000000000000..a01eec86b9a6 --- /dev/null +++ b/include/sound/sdca_function.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + * Copyright(c) 2024 Intel Corporation + */ + +#ifndef __SDCA_FUNCTION_H__ +#define __SDCA_FUNCTION_H__ + +/* + * SDCA Function Types from SDCA specification v1.0a Section 5.1.2 + * all Function types not described are reserved + * Note that SIMPLE_AMP, SIMPLE_MIC and SIMPLE_JACK Function Types + * are NOT defined in SDCA 1.0a, but they were defined in earlier + * drafts and are planned for 1.1. + */ + +enum sdca_function_type { + SDCA_FUNCTION_TYPE_SMART_AMP = 0x01, /* Amplifier with protection features */ + SDCA_FUNCTION_TYPE_SIMPLE_AMP = 0x02, /* subset of SmartAmp */ + SDCA_FUNCTION_TYPE_SMART_MIC = 0x03, /* Smart microphone with acoustic triggers */ + SDCA_FUNCTION_TYPE_SIMPLE_MIC = 0x04, /* subset of SmartMic */ + SDCA_FUNCTION_TYPE_SPEAKER_MIC = 0x05, /* Combination of SmartMic and SmartAmp */ + SDCA_FUNCTION_TYPE_UAJ = 0x06, /* 3.5mm Universal Audio jack */ + SDCA_FUNCTION_TYPE_RJ = 0x07, /* Retaskable jack */ + SDCA_FUNCTION_TYPE_SIMPLE_JACK = 0x08, /* Subset of UAJ */ + SDCA_FUNCTION_TYPE_HID = 0x0A, /* Human Interface Device, for e.g. buttons */ + SDCA_FUNCTION_TYPE_IMP_DEF = 0x1F, /* Implementation-defined function */ +}; + +/* Human-readable names used for kernel logs and Function device registration/bind */ +#define SDCA_FUNCTION_TYPE_SMART_AMP_NAME "SmartAmp" +#define SDCA_FUNCTION_TYPE_SIMPLE_AMP_NAME "SimpleAmp" +#define SDCA_FUNCTION_TYPE_SMART_MIC_NAME "SmartMic" +#define SDCA_FUNCTION_TYPE_SIMPLE_MIC_NAME "SimpleMic" +#define SDCA_FUNCTION_TYPE_SPEAKER_MIC_NAME "SpeakerMic" +#define SDCA_FUNCTION_TYPE_UAJ_NAME "UAJ" +#define SDCA_FUNCTION_TYPE_RJ_NAME "RJ" +#define SDCA_FUNCTION_TYPE_SIMPLE_NAME "SimpleJack" +#define SDCA_FUNCTION_TYPE_HID_NAME "HID" + +enum sdca_entity0_controls { + SDCA_CONTROL_ENTITY_0_COMMIT_GROUP_MASK = 0x01, + SDCA_CONTROL_ENTITY_0_INTSTAT_CLEAR = 0x02, + SDCA_CONTROL_ENTITY_0_INT_ENABLE = 0x03, + SDCA_CONTROL_ENTITY_0_FUNCTION_SDCA_VERSION = 0x04, + SDCA_CONTROL_ENTITY_0_FUNCTION_TOPOLOGY = 0x05, + SDCA_CONTROL_ENTITY_0_FUNCTION_MANUFACTURER_ID = 0x06, + SDCA_CONTROL_ENTITY_0_FUNCTION_ID = 0x07, + SDCA_CONTROL_ENTITY_0_FUNCTION_VERSION = 0x08 +}; + +#endif diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index b19410544081..c7ad5626ba48 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -95,6 +95,7 @@ source "sound/soc/pxa/Kconfig" source "sound/soc/qcom/Kconfig" source "sound/soc/rockchip/Kconfig" source "sound/soc/samsung/Kconfig" +source "sound/soc/sdca/Kconfig" source "sound/soc/sh/Kconfig" source "sound/soc/sof/Kconfig" source "sound/soc/spear/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 6b0258938633..ab06c57ce7c6 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_SND_SOC) += pxa/ obj-$(CONFIG_SND_SOC) += qcom/ obj-$(CONFIG_SND_SOC) += rockchip/ obj-$(CONFIG_SND_SOC) += samsung/ +obj-$(CONFIG_SND_SOC) += sdca/ obj-$(CONFIG_SND_SOC) += sh/ obj-$(CONFIG_SND_SOC) += sof/ obj-$(CONFIG_SND_SOC) += spear/ diff --git a/sound/soc/sdca/Kconfig b/sound/soc/sdca/Kconfig new file mode 100644 index 000000000000..07f6822fa614 --- /dev/null +++ b/sound/soc/sdca/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config SND_SOC_SDCA + tristate "ASoC SDCA library" + depends on ACPI + help + This option enables support for the MIPI SoundWire Device + Class for Audio (SDCA). + +config SND_SOC_SDCA_OPTIONAL + def_tristate SND_SOC_SDCA || !SND_SOC_SDCA diff --git a/sound/soc/sdca/Makefile b/sound/soc/sdca/Makefile new file mode 100644 index 000000000000..c296bd5a0a7c --- /dev/null +++ b/sound/soc/sdca/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +snd-soc-sdca-objs := sdca_functions.o sdca_device.o + +obj-$(CONFIG_SND_SOC_SDCA) += snd-soc-sdca.o diff --git a/sound/soc/sdca/sdca_device.c b/sound/soc/sdca/sdca_device.c new file mode 100644 index 000000000000..58f5f6f0f723 --- /dev/null +++ b/sound/soc/sdca/sdca_device.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2024 Intel Corporation + +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + */ + +#include +#include +#include + +void sdca_lookup_interface_revision(struct sdw_slave *slave) +{ + struct fwnode_handle *fwnode = slave->dev.fwnode; + + /* + * if this property is not present, then the sdca_interface_revision will + * remain zero, which will be considered as 'not defined' or 'invalid'. + */ + fwnode_property_read_u32(fwnode, "mipi-sdw-sdca-interface-revision", + &slave->sdca_data.interface_revision); +} +EXPORT_SYMBOL_NS(sdca_lookup_interface_revision, SND_SOC_SDCA); diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c new file mode 100644 index 000000000000..a6ad57430dd4 --- /dev/null +++ b/sound/soc/sdca/sdca_functions.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2024 Intel Corporation + +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + */ + +#include +#include +#include +#include + +static int patch_sdca_function_type(struct device *dev, + u32 interface_revision, + u32 *function_type, + const char **function_name) +{ + unsigned long function_type_patch = 0; + + /* + * Unfortunately early SDCA specifications used different indices for Functions, + * for backwards compatibility we have to reorder the values found + */ + if (interface_revision >= 0x0801) + goto skip_early_draft_order; + + switch (*function_type) { + case 1: + function_type_patch = SDCA_FUNCTION_TYPE_SMART_AMP; + break; + case 2: + function_type_patch = SDCA_FUNCTION_TYPE_SMART_MIC; + break; + case 3: + function_type_patch = SDCA_FUNCTION_TYPE_SPEAKER_MIC; + break; + case 4: + function_type_patch = SDCA_FUNCTION_TYPE_UAJ; + break; + case 5: + function_type_patch = SDCA_FUNCTION_TYPE_RJ; + break; + case 6: + function_type_patch = SDCA_FUNCTION_TYPE_HID; + break; + default: + dev_warn(dev, "%s: SDCA version %#x unsupported function type %d, skipped\n", + __func__, interface_revision, *function_type); + return -EINVAL; + } + +skip_early_draft_order: + if (function_type_patch) + *function_type = function_type_patch; + + /* now double-check the values */ + switch (*function_type) { + case SDCA_FUNCTION_TYPE_SMART_AMP: + *function_name = SDCA_FUNCTION_TYPE_SMART_AMP_NAME; + break; + case SDCA_FUNCTION_TYPE_SMART_MIC: + *function_name = SDCA_FUNCTION_TYPE_SMART_MIC_NAME; + break; + case SDCA_FUNCTION_TYPE_UAJ: + *function_name = SDCA_FUNCTION_TYPE_UAJ_NAME; + break; + case SDCA_FUNCTION_TYPE_HID: + *function_name = SDCA_FUNCTION_TYPE_HID_NAME; + break; + case SDCA_FUNCTION_TYPE_SIMPLE_AMP: + case SDCA_FUNCTION_TYPE_SIMPLE_MIC: + case SDCA_FUNCTION_TYPE_SPEAKER_MIC: + case SDCA_FUNCTION_TYPE_RJ: + case SDCA_FUNCTION_TYPE_IMP_DEF: + dev_warn(dev, "%s: found unsupported SDCA function type %d, skipped\n", + __func__, *function_type); + return -EINVAL; + default: + dev_err(dev, "%s: found invalid SDCA function type %d, skipped\n", + __func__, *function_type); + return -EINVAL; + } + + dev_info(dev, "%s: found SDCA function %s (type %d)\n", + __func__, *function_name, *function_type); + + return 0; +} + +static int find_sdca_function(struct acpi_device *adev, void *data) +{ + struct fwnode_handle *function_node = acpi_fwnode_handle(adev); + struct sdca_device_data *sdca_data = data; + struct device *dev = &adev->dev; + struct fwnode_handle *control5; /* used to identify function type */ + const char *function_name; + u32 function_type; + int func_index; + u64 addr; + int ret; + + if (sdca_data->num_functions >= SDCA_MAX_FUNCTION_COUNT) { + dev_err(dev, "%s: maximum number of functions exceeded\n", __func__); + return -EINVAL; + } + + /* + * The number of functions cannot exceed 8, we could use + * acpi_get_local_address() but the value is stored as u64 so + * we might as well avoid casts and intermediate levels + */ + ret = acpi_get_local_u64_address(adev->handle, &addr); + if (ret < 0) + return ret; + + if (!addr) { + dev_err(dev, "%s: no addr\n", __func__); + return -ENODEV; + } + + /* + * Extracting the topology type for an SDCA function is a + * convoluted process. + * The Function type is only visible as a result of a read + * from a control. In theory this would mean reading from the hardware, + * but the SDCA/DisCo specs defined the notion of "DC value" - a constant + * represented with a DSD subproperty. + * Drivers have to query the properties for the control + * SDCA_CONTROL_ENTITY_0_FUNCTION_TOPOLOGY (0x05) + */ + control5 = fwnode_get_named_child_node(function_node, + "mipi-sdca-control-0x5-subproperties"); + if (!control5) + return -ENODEV; + + ret = fwnode_property_read_u32(control5, "mipi-sdca-control-dc-value", + &function_type); + + fwnode_handle_put(control5); + + if (ret < 0) { + dev_err(dev, "%s: the function type can only be determined from ACPI information\n", + __func__); + return ret; + } + + ret = patch_sdca_function_type(dev, sdca_data->interface_revision, + &function_type, &function_name); + if (ret < 0) + return ret; + + /* store results */ + func_index = sdca_data->num_functions; + sdca_data->sdca_func[func_index].adr = addr; + sdca_data->sdca_func[func_index].type = function_type; + sdca_data->sdca_func[func_index].name = function_name; + sdca_data->num_functions++; + + return 0; +} + +void sdca_lookup_functions(struct sdw_slave *slave) +{ + struct device *dev = &slave->dev; + struct acpi_device *adev = to_acpi_device_node(dev->fwnode); + + acpi_dev_for_each_child(adev, find_sdca_function, &slave->sdca_data); +} +EXPORT_SYMBOL_NS(sdca_lookup_functions, SND_SOC_SDCA); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("SDCA library"); From f4c7a0dbd60748caa8f362e19ef8cbe27af96837 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:02 +0100 Subject: [PATCH 101/256] soundwire: slave: lookup SDCA version and functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0c673d2862534955241f339d7331f384b5ea44af Author: Pierre-Louis Bossart Date: Wed Oct 16 18:23:26 2024 +0800 soundwire: slave: lookup SDCA version and functions Use SDCA helpers to get the basic information and store it in the slave context. The information will be optionally be used in codec drivers to register sub-devices for each Function. When platforms are not based on ACPI the helpers do absolutely nothing. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Acked-by: Vinod Koul Link: https://patch.msgid.link/20241016102333.294448-5-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- drivers/soundwire/Kconfig | 1 + drivers/soundwire/slave.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/soundwire/Kconfig b/drivers/soundwire/Kconfig index 4d8f3b7024ae..f66f869dff2e 100644 --- a/drivers/soundwire/Kconfig +++ b/drivers/soundwire/Kconfig @@ -6,6 +6,7 @@ menuconfig SOUNDWIRE tristate "SoundWire support" depends on ACPI || OF + depends on SND_SOC_SDCA_OPTIONAL help SoundWire is a 2-Pin interface with data and clock line ratified by the MIPI Alliance. SoundWire is used for transporting data diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index f1a4df6cfebd..97cf8bcca047 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "bus.h" #include "sysfs_local.h" @@ -70,6 +71,17 @@ int sdw_slave_add(struct sdw_bus *bus, list_add_tail(&slave->node, &bus->slaves); mutex_unlock(&bus->bus_lock); + /* + * The Soundwire driver probe may optionally register SDCA + * sub-devices, one per Function. This means the information + * on the SDCA revision and the number/type of Functions need + * to be extracted from platform firmware before the SoundWire + * driver probe, and as a consequence before the SoundWire + * device_register() below. + */ + sdca_lookup_interface_revision(slave); + sdca_lookup_functions(slave); + ret = device_register(&slave->dev); if (ret) { dev_err(bus->dev, "Failed to add slave: ret %d\n", ret); @@ -259,3 +271,5 @@ int sdw_of_find_slaves(struct sdw_bus *bus) return 0; } + +MODULE_IMPORT_NS(SND_SOC_SDCA); From 2a6d3c4bc40bd585af4623afea1cfa2daa77f60d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:02 +0100 Subject: [PATCH 102/256] ASoC: SDCA: add quirk function for RT712_VB match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit fdb220399177177917dce52063b326a191a35a02 Author: Pierre-Louis Bossart Date: Wed Oct 16 18:23:27 2024 +0800 ASoC: SDCA: add quirk function for RT712_VB match Add a generic match function for quirks, chances are we are going to have lots of those... Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241016102333.294448-6-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/sdca.h | 10 ++++++++- sound/soc/sdca/sdca_device.c | 43 ++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/include/sound/sdca.h b/include/sound/sdca.h index 34473ca4c789..7e138229e8f3 100644 --- a/include/sound/sdca.h +++ b/include/sound/sdca.h @@ -39,16 +39,24 @@ struct sdca_device_data { struct sdca_function_desc sdca_func[SDCA_MAX_FUNCTION_COUNT]; }; +enum sdca_quirk { + SDCA_QUIRKS_RT712_VB, +}; + #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA) void sdca_lookup_functions(struct sdw_slave *slave); void sdca_lookup_interface_revision(struct sdw_slave *slave); +bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk); #else static inline void sdca_lookup_functions(struct sdw_slave *slave) {} static inline void sdca_lookup_interface_revision(struct sdw_slave *slave) {} - +static inline bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk) +{ + return false; +} #endif #endif diff --git a/sound/soc/sdca/sdca_device.c b/sound/soc/sdca/sdca_device.c index 58f5f6f0f723..c44dc21cb634 100644 --- a/sound/soc/sdca/sdca_device.c +++ b/sound/soc/sdca/sdca_device.c @@ -9,6 +9,7 @@ #include #include #include +#include void sdca_lookup_interface_revision(struct sdw_slave *slave) { @@ -22,3 +23,45 @@ void sdca_lookup_interface_revision(struct sdw_slave *slave) &slave->sdca_data.interface_revision); } EXPORT_SYMBOL_NS(sdca_lookup_interface_revision, SND_SOC_SDCA); + +static bool sdca_device_quirk_rt712_vb(struct sdw_slave *slave) +{ + struct sdw_slave_id *id = &slave->id; + int i; + + /* + * The RT712_VA relies on the v06r04 draft, and the + * RT712_VB on a more recent v08r01 draft. + */ + if (slave->sdca_data.interface_revision < 0x0801) + return false; + + if (id->mfg_id != 0x025d) + return false; + + if (id->part_id != 0x712 && + id->part_id != 0x713 && + id->part_id != 0x716 && + id->part_id != 0x717) + return false; + + for (i = 0; i < slave->sdca_data.num_functions; i++) { + if (slave->sdca_data.sdca_func[i].type == + SDCA_FUNCTION_TYPE_SMART_MIC) + return true; + } + + return false; +} + +bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk) +{ + switch (quirk) { + case SDCA_QUIRKS_RT712_VB: + return sdca_device_quirk_rt712_vb(slave); + default: + break; + } + return false; +} +EXPORT_SYMBOL_NS(sdca_device_quirk_match, SND_SOC_SDCA); From 88165c4287283223a0b3efdf0e8d33054d8ac78b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:02 +0100 Subject: [PATCH 103/256] ASoC: soc-acpi: introduce new 'machine check' callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit dcf4694f200a67784e053eb5d1d70a191761ff4f Author: Pierre-Louis Bossart Date: Wed Oct 16 18:23:29 2024 +0800 ASoC: soc-acpi: introduce new 'machine check' callback The existing machine_quirk() returns a pointer to a soc_acpi_mach structure. For SoundWire/SDCA support, we need a slightly different functionality where a quirk function either validates or NACKs an initial selection, based on additional firmware/DMI information. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241016102333.294448-8-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/soc-acpi.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index b80313e4b331..468b754224db 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -187,6 +187,10 @@ struct snd_soc_acpi_link_adr { * ACPI ID alone is not sufficient, wrong or misleading * @quirk_data: data used to uniquely identify a machine, usually a list of * audio codecs whose presence if checked with ACPI + * @machine_check: pointer to quirk function. The functionality is similar to + * the use of @machine_quirk, except that the return value is a boolean: the intent + * is to skip a machine if the additional hardware/firmware verification invalidates + * the initial selection in the snd_soc_acpi_mach table. * @pdata: intended for platform data or machine specific-ops. This structure * is not constant since this field may be updated at run-time * @sof_tplg_filename: Sound Open Firmware topology file name, if enabled @@ -205,6 +209,7 @@ struct snd_soc_acpi_mach { const char *board; struct snd_soc_acpi_mach * (*machine_quirk)(void *arg); const void *quirk_data; + bool (*machine_check)(void *arg); void *pdata; struct snd_soc_acpi_mach_params mach_params; const char *sof_tplg_filename; From 09f0ebdf9219e9d9ff644fa78d985198cdc75e3a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:02 +0100 Subject: [PATCH 104/256] ASoC: rt712-sdca: detect the SMART_MIC function during the probe stage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9aa6df9cb82e8fd44132c481afc76eb7a7dbc398 Author: Pierre-Louis Bossart Date: Wed Oct 16 18:23:28 2024 +0800 ASoC: rt712-sdca: detect the SMART_MIC function during the probe stage We shouldn't do any devm_ based allocation in the io_init(), this need to happen in the probe(). Luckily, we now have an SDCA helper to look in ACPI tables if a SMART_MIC function is exposed. FIXME: the registers are not well handled today, the regmap lists registers which are not really supported in all platforms. The regmap needs to throw an error if those registers are accessed without existing. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241016102333.294448-7-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/rt712-sdca-sdw.c | 1 + sound/soc/codecs/rt712-sdca.c | 40 +++++++++++++++++++++++-------- sound/soc/codecs/rt712-sdca.h | 1 + 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c index 90d5aaddbd5b..549aa31faed4 100644 --- a/sound/soc/codecs/rt712-sdca-sdw.c +++ b/sound/soc/codecs/rt712-sdca-sdw.c @@ -507,3 +507,4 @@ module_sdw_driver(rt712_sdca_sdw_driver); MODULE_DESCRIPTION("ASoC RT712 SDCA SDW driver"); MODULE_AUTHOR("Shuming Fan "); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_SDCA); diff --git a/sound/soc/codecs/rt712-sdca.c b/sound/soc/codecs/rt712-sdca.c index e210c574bb74..78dbf9eed494 100644 --- a/sound/soc/codecs/rt712-sdca.c +++ b/sound/soc/codecs/rt712-sdca.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -1652,6 +1653,17 @@ int rt712_sdca_init(struct device *dev, struct regmap *regmap, if (ret < 0) return ret; + /* only add the dmic component if a SMART_MIC function is exposed in ACPI */ + if (sdca_device_quirk_match(slave, SDCA_QUIRKS_RT712_VB)) { + ret = devm_snd_soc_register_component(dev, + &soc_sdca_dev_rt712_dmic, + rt712_sdca_dmic_dai, + ARRAY_SIZE(rt712_sdca_dmic_dai)); + if (ret < 0) + return ret; + rt712->dmic_function_found = true; + } + /* set autosuspend parameters */ pm_runtime_set_autosuspend_delay(dev, 3000); pm_runtime_use_autosuspend(dev); @@ -1799,7 +1811,6 @@ static void rt712_sdca_vb_io_init(struct rt712_sdca_priv *rt712) int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave) { struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev); - int ret = 0; unsigned int val; struct sdw_slave_prop *prop = &slave->prop; @@ -1829,15 +1840,22 @@ int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave) rt712->version_id = (val & 0x0f00) >> 8; dev_dbg(&slave->dev, "%s hw_id=0x%x, version_id=0x%x\n", __func__, rt712->hw_id, rt712->version_id); - if (rt712->version_id == RT712_VA) - rt712_sdca_va_io_init(rt712); - else { - /* multilanes and DMIC are supported by rt712vb */ - ret = devm_snd_soc_register_component(dev, - &soc_sdca_dev_rt712_dmic, rt712_sdca_dmic_dai, ARRAY_SIZE(rt712_sdca_dmic_dai)); - if (ret < 0) - return ret; + if (rt712->version_id == RT712_VA) { + if (rt712->dmic_function_found) { + dev_err(&slave->dev, "%s RT712 VA detected but SMART_MIC function exposed in ACPI\n", + __func__); + goto suspend; + } + rt712_sdca_va_io_init(rt712); + } else { + if (!rt712->dmic_function_found) { + dev_err(&slave->dev, "%s RT712 VB detected but no SMART_MIC function exposed in ACPI\n", + __func__); + goto suspend; + } + + /* multilanes and DMIC are supported by rt712vb */ prop->lane_control_support = true; rt712_sdca_vb_io_init(rt712); } @@ -1862,10 +1880,12 @@ int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave) /* Mark Slave initialization complete */ rt712->hw_init = true; + dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); + +suspend: pm_runtime_mark_last_busy(&slave->dev); pm_runtime_put_autosuspend(&slave->dev); - dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); return 0; } diff --git a/sound/soc/codecs/rt712-sdca.h b/sound/soc/codecs/rt712-sdca.h index 2169f2f726b9..a08491496d90 100644 --- a/sound/soc/codecs/rt712-sdca.h +++ b/sound/soc/codecs/rt712-sdca.h @@ -36,6 +36,7 @@ struct rt712_sdca_priv { unsigned int scp_sdca_stat2; unsigned int hw_id; unsigned int version_id; + bool dmic_function_found; bool fu0f_dapm_mute; bool fu0f_mixer_l_mute; bool fu0f_mixer_r_mute; From e8cdf890eb42f3b82e60118c7a50f537dbf65ee5 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:02 +0100 Subject: [PATCH 105/256] ASoC: sdw_utils: add SmartMic DAI for RT712 VB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9489db97f6f0d78c26eef8e7fc9c1371cef97b82 Author: Pierre-Louis Bossart Date: Wed Oct 16 18:23:30 2024 +0800 ASoC: sdw_utils: add SmartMic DAI for RT712 VB In theory the dailinks are created based on the number of endpoints reported in ACPI match tables, so it should harmless to add a new dailink: RT712 VA would not use it since it has only 2 endpoints. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241016102333.294448-9-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sdw_utils/soc_sdw_utils.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index c8f933bf891a..8130bf0e9415 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -144,8 +144,15 @@ struct asoc_sdw_codec_info codec_info_list[] = { .widgets = generic_spk_widgets, .num_widgets = ARRAY_SIZE(generic_spk_widgets), }, + { + .direction = {false, true}, + .dai_name = "rt712-sdca-aif3", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_rt_dmic_rtd_init, + }, }, - .dai_num = 2, + .dai_num = 3, }, { .part_id = 0x1712, From 7359624e5c750fa85450bb549ea95810f155c640 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:03 +0100 Subject: [PATCH 106/256] ASoC: sdw_utils: add SmartMic DAI for RT713 VB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7d6f2d5254b1786c8b3bd64c6295b14e1607965d Author: Pierre-Louis Bossart Date: Wed Oct 16 18:23:31 2024 +0800 ASoC: sdw_utils: add SmartMic DAI for RT713 VB In theory the dailinks are created based on the number of endpoints reported in ACPI match tables, so it should harmless to add a new dailink: RT713 VA would not use it since it has only 2 endpoints. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241016102333.294448-10-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sdw_utils/soc_sdw_utils.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index 8130bf0e9415..6610efe8af18 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -185,8 +185,15 @@ struct asoc_sdw_codec_info codec_info_list[] = { .widgets = generic_jack_widgets, .num_widgets = ARRAY_SIZE(generic_jack_widgets), }, + { + .direction = {false, true}, + .dai_name = "rt712-sdca-aif3", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_rt_dmic_rtd_init, + }, }, - .dai_num = 1, + .dai_num = 2, }, { .part_id = 0x1713, From 7a44ed9d9e21bb84ea7123a71ccc6936b5958b12 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:03 +0100 Subject: [PATCH 107/256] ASoC: Intel: soc-acpi: add is_device_rt712_vb() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 Conflicts: Makefile - do not remove sst ipc module commit 5703ab86ff7bf079aa1ddf7a65b9727d0249383a Author: Pierre-Louis Bossart Date: Wed Oct 16 18:23:32 2024 +0800 ASoC: Intel: soc-acpi: add is_device_rt712_vb() helper Add a filter to skip the RT172 VB configuration if a SmartMic Function is not found in the SDCA descriptors. If the ACPI information is incorrect this can only be quirked further with DMI information. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241016102333.294448-11-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/intel/Kconfig | 5 ++ sound/soc/intel/common/Makefile | 4 ++ .../intel/common/soc-acpi-intel-mtl-match.c | 51 +++++++++++++++++++ .../intel/common/soc-acpi-intel-sdca-quirks.c | 42 +++++++++++++++ .../intel/common/soc-acpi-intel-sdca-quirks.h | 14 +++++ 5 files changed, 116 insertions(+) create mode 100644 sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c create mode 100644 sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 38b61dfd1487..7fa191851e9b 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -194,9 +194,14 @@ if SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL config SND_SOC_ACPI_INTEL_MATCH tristate select SND_SOC_ACPI if ACPI + select SND_SOC_ACPI_INTEL_SDCA_QUIRKS # this option controls the compilation of ACPI matching tables and # helpers and is not meant to be selected by the user. +config SND_SOC_ACPI_INTEL_SDCA_QUIRKS + tristate + imply SND_SOC_SDCA + endif ## SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL config SND_SOC_INTEL_KEEMBAY diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index 91e146e2487d..a0ed0bc15aa4 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -18,5 +18,9 @@ snd-soc-acpi-intel-match-y := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-matc snd-soc-acpi-intel-match-y += soc-acpi-intel-ssp-common.o +snd-soc-acpi-intel-sdca-quirks-y += soc-acpi-intel-sdca-quirks.o + obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o + obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o +obj-$(CONFIG_SND_SOC_ACPI_INTEL_SDCA_QUIRKS) += snd-soc-acpi-intel-sdca-quirks.o diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index fd02c864e25e..0b37465b6c53 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -6,9 +6,12 @@ * */ +#include +#include #include #include #include +#include "soc-acpi-intel-sdca-quirks.h" #include "soc-acpi-intel-sdw-mockup-match.h" static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = { @@ -133,6 +136,27 @@ static const struct snd_soc_acpi_endpoint rt712_endpoints[] = { }, }; +static const struct snd_soc_acpi_endpoint rt712_vb_endpoints[] = { + { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + /* * RT722 is a multi-function codec, three endpoints are created for * its headset, amp and dmic functions. @@ -190,6 +214,15 @@ static const struct snd_soc_acpi_adr_device rt712_0_single_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt712_vb_0_single_adr[] = { + { + .adr = 0x000030025D071201ull, + .num_endpoints = ARRAY_SIZE(rt712_vb_endpoints), + .endpoints = rt712_vb_endpoints, + .name_prefix = "rt712" + } +}; + static const struct snd_soc_acpi_adr_device rt1712_3_single_adr[] = { { .adr = 0x000330025D171201ull, @@ -363,6 +396,15 @@ static const struct snd_soc_acpi_link_adr mtl_712_l0[] = { {} }; +static const struct snd_soc_acpi_link_adr mtl_712_vb_l0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt712_vb_0_single_adr), + .adr_d = rt712_vb_0_single_adr, + }, + {} +}; + static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { { /* Jack Playback Endpoint */ .num = 0, @@ -774,6 +816,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-mtl-rt712-l0-rt1712-l3.tplg", }, + { + .link_mask = BIT(0), + .links = mtl_712_vb_l0, + .drv_name = "sof_sdw", + .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb, + .sof_tplg_filename = "sof-mtl-rt712-vb-l0.tplg", + }, { .link_mask = BIT(0), .links = mtl_712_l0, @@ -843,3 +892,5 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_sdw_machines); + +MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_SDCA_QUIRKS); diff --git a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c new file mode 100644 index 000000000000..0b7076606d66 --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * soc-acpi-intel-sdca-quirks.c - tables and support for SDCA quirks + * + * Copyright (c) 2024, Intel Corporation. + * + */ + +#include +#include +#include +#include "soc-acpi-intel-sdca-quirks.h" + +/* + * Pretend machine quirk. The argument type is not the traditional + * 'struct snd_soc_acpi_mach' pointer but instead the sdw_intel_ctx + * which contains the peripheral information required for the + * SoundWire/SDCA filter on the SMART_MIC setup and interface + * revision. When the return value is false, the entry in the + * 'snd_soc_acpi_mach' table needs to be skipped. + */ +bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg) +{ + struct sdw_intel_ctx *ctx = arg; + int i; + + if (!ctx) + return false; + + for (i = 0; i < ctx->peripherals->num_peripherals; i++) { + if (sdca_device_quirk_match(ctx->peripherals->array[i], + SDCA_QUIRKS_RT712_VB)) + return true; + } + + return false; +} +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_sdca_is_device_rt712_vb, SND_SOC_ACPI_INTEL_SDCA_QUIRKS); + +MODULE_DESCRIPTION("ASoC ACPI Intel SDCA quirks"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_SDCA); diff --git a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h new file mode 100644 index 000000000000..bead5ec6243f --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * soc-acpi-intel-sdca-quirks.h - tables and support for SDCA quirks + * + * Copyright (c) 2024, Intel Corporation. + * + */ + +#ifndef _SND_SOC_ACPI_INTEL_SDCA_QUIRKS +#define _SND_SOC_ACPI_INTEL_SDCA_QUIRKS + +bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg); + +#endif From 4295cb4e8a50d195651a2a5bedfe64379a926f16 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:03 +0100 Subject: [PATCH 108/256] ASoC: SOF: Intel: hda: use machine_check() for SoundWire MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit e92edcf8023d425c7abcf1d7abb5dcac53d106f5 Author: Pierre-Louis Bossart Date: Wed Oct 16 18:23:33 2024 +0800 ASoC: SOF: Intel: hda: use machine_check() for SoundWire Use the new machine_check() callback to select an alternate topology for RT712-VB devices. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://patch.msgid.link/20241016102333.294448-12-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/intel/hda.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index af53bc1936b3..2d021d7bff3f 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1125,7 +1125,8 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev } /* Found if all Slaves are checked */ if (i == hdev->info.count || !link->num_adr) - break; + if (!mach->machine_check || mach->machine_check(hdev->sdw)) + break; } if (mach && mach->link_mask) { mach->mach_params.links = mach->links; From 03a2660c58fe54a51ef828b51d8a9f74f689b78d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:03 +0100 Subject: [PATCH 109/256] ASoC: rx651: Use card->dev in replace of the &pdev->dev argument in the dev_err function JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 4d003b81f46737620c7f9194d305617dfdfce8fb Author: Liu Jing Date: Tue Oct 15 15:49:38 2024 +0800 ASoC: rx651: Use card->dev in replace of the &pdev->dev argument in the dev_err function Because card->dev = &pdev->dev is already defined in the rx51_soc_probe function, and then &pdev->dev is still used. Signed-off-by: Liu Jing Link: https://patch.msgid.link/20241015074938.6247-1-liujing@cmss.chinamobile.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/ti/rx51.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index 322c398d209b..e7d05e71badd 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -374,7 +374,7 @@ static int rx51_soc_probe(struct platform_device *pdev) dai_node = of_parse_phandle(np, "nokia,cpu-dai", 0); if (!dai_node) { - dev_err(&pdev->dev, "McBSP node is not provided\n"); + dev_err(card->dev, "McBSP node is not provided\n"); return -EINVAL; } rx51_dai[0].cpus->dai_name = NULL; @@ -384,7 +384,7 @@ static int rx51_soc_probe(struct platform_device *pdev) dai_node = of_parse_phandle(np, "nokia,audio-codec", 0); if (!dai_node) { - dev_err(&pdev->dev, "Codec node is not provided\n"); + dev_err(card->dev, "Codec node is not provided\n"); return -EINVAL; } rx51_dai[0].codecs->name = NULL; @@ -392,7 +392,7 @@ static int rx51_soc_probe(struct platform_device *pdev) dai_node = of_parse_phandle(np, "nokia,audio-codec", 1); if (!dai_node) { - dev_err(&pdev->dev, "Auxiliary Codec node is not provided\n"); + dev_err(card->dev, "Auxiliary Codec node is not provided\n"); return -EINVAL; } rx51_aux_dev[0].dlc.name = NULL; @@ -402,7 +402,7 @@ static int rx51_soc_probe(struct platform_device *pdev) dai_node = of_parse_phandle(np, "nokia,headphone-amplifier", 0); if (!dai_node) { - dev_err(&pdev->dev, "Headphone amplifier node is not provided\n"); + dev_err(card->dev, "Headphone amplifier node is not provided\n"); return -EINVAL; } rx51_aux_dev[1].dlc.name = NULL; @@ -411,7 +411,7 @@ static int rx51_soc_probe(struct platform_device *pdev) rx51_codec_conf[1].dlc.of_node = dai_node; } - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + pdata = devm_kzalloc(card->dev, sizeof(*pdata), GFP_KERNEL); if (pdata == NULL) return -ENOMEM; @@ -450,7 +450,7 @@ static int rx51_soc_probe(struct platform_device *pdev) err = devm_snd_soc_register_card(card->dev, card); if (err) { - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", err); + dev_err(card->dev, "snd_soc_register_card failed (%d)\n", err); return err; } From 26cc1ebbfd950c8ad41ab2e8018db6b5f34be851 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:03 +0100 Subject: [PATCH 110/256] ASoC: amd: acp: Add stream name to ACP PDM DMIC devices JIRA: https://issues.redhat.com/browse/RHEL-80681 commit b2385de2ae11bdd34855276e0a254109469227eb Author: Mario Limonciello Date: Thu Oct 17 16:09:52 2024 -0500 ASoC: amd: acp: Add stream name to ACP PDM DMIC devices Add for sof and legacy dai links to dummy DMIC codec. Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20241017210952.3586713-1-superm1@kernel.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-mach-common.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index 2394aa061265..e38b478e15f3 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -1567,6 +1567,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) if (drv_data->dmic_cpu_id == DMIC) { links[i].name = "acp-dmic-codec"; + links[i].stream_name = "DMIC capture"; links[i].id = DMIC_BE_ID; links[i].codecs = dmic_codec; links[i].num_codecs = ARRAY_SIZE(dmic_codec); @@ -1759,6 +1760,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) if (drv_data->dmic_cpu_id == DMIC) { links[i].name = "acp-dmic-codec"; + links[i].stream_name = "DMIC capture"; links[i].id = DMIC_BE_ID; if (drv_data->dmic_codec_id == DMIC) { links[i].codecs = dmic_codec; From d589ca2b1ce3bd78040512365e456a4da18774d6 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:03 +0100 Subject: [PATCH 111/256] ASoC: nau8821: check regmap_raw_read/regmap_raw_write for failure JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1b9971a4e01b80afbf061ad7cdf84ac6fbbbde8d Author: Vitaliy Shevtsov Date: Fri Oct 18 16:07:41 2024 +0500 ASoC: nau8821: check regmap_raw_read/regmap_raw_write for failure The return values from both regmap_raw_read() and regmap_raw_write() are not checked despite they can fail. Propagate possible errors to caller. Found by Linux Verification Center (linuxtesting.org) with Svace. Signed-off-by: Vitaliy Shevtsov Link: https://patch.msgid.link/20241018110743.18786-1-v.shevtsov@maxima.ru Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/nau8821.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c index 9dfcefbc4fcc..4485c10acff2 100644 --- a/sound/soc/codecs/nau8821.c +++ b/sound/soc/codecs/nau8821.c @@ -287,10 +287,8 @@ static int nau8821_biq_coeff_get(struct snd_kcontrol *kcontrol, if (!component->regmap) return -EINVAL; - regmap_raw_read(component->regmap, NAU8821_R21_BIQ0_COF1, + return regmap_raw_read(component->regmap, NAU8821_R21_BIQ0_COF1, ucontrol->value.bytes.data, params->max); - - return 0; } static int nau8821_biq_coeff_put(struct snd_kcontrol *kcontrol, @@ -299,6 +297,7 @@ static int nau8821_biq_coeff_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_bytes_ext *params = (void *)kcontrol->private_value; void *data; + int ret; if (!component->regmap) return -EINVAL; @@ -308,12 +307,12 @@ static int nau8821_biq_coeff_put(struct snd_kcontrol *kcontrol, if (!data) return -ENOMEM; - regmap_raw_write(component->regmap, NAU8821_R21_BIQ0_COF1, + ret = regmap_raw_write(component->regmap, NAU8821_R21_BIQ0_COF1, data, params->max); kfree(data); - return 0; + return ret; } static const char * const nau8821_adc_decimation[] = { From 5b9a60c0a95d731bf93bb82aefab389f76bb3511 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:04 +0100 Subject: [PATCH 112/256] ASoC: soc-utils: Remove PAGE_SIZE compile-time constant assumption JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 5337ff41d37d4171868bb7b34dade68e269743f0 Author: Ryan Roberts Date: Mon Oct 21 14:03:07 2024 +0100 ASoC: soc-utils: Remove PAGE_SIZE compile-time constant assumption In pursuit of the goal of supporting boot-time page size selection, remove use of PAGE_SIZE from the dummy_dma_hardware struct definition, since the value is not known at compile-time for this config. Given the previous parameters were "essentially random", let's just hardcode them as 4K and 4K*2 to sidestep the need to boot-time patch the structure with the selected PAGE_SIZE. Signed-off-by: Ryan Roberts Link: https://patch.msgid.link/20241021130308.3616451-1-ryan.roberts@arm.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/soc-utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 303823dc45d7..aa93e77ac937 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -103,8 +103,8 @@ static const struct snd_pcm_hardware dummy_dma_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER, .buffer_bytes_max = 128*1024, - .period_bytes_min = PAGE_SIZE, - .period_bytes_max = PAGE_SIZE*2, + .period_bytes_min = 4096, + .period_bytes_max = 4096*2, .periods_min = 2, .periods_max = 128, }; From b2d7621c7892386afac8d4206b78f497e8d0ea5d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:04 +0100 Subject: [PATCH 113/256] ASoC: codecs: adau1372: add match table JIRA: https://issues.redhat.com/browse/RHEL-80681 commit cca8824838a59aba31e182525175e5659c33034f Author: Nuno Sa Date: Mon Oct 21 16:00:49 2024 +0200 ASoC: codecs: adau1372: add match table Add an of_device_id table for both the I2C and SPI drivers. Signed-off-by: Nuno Sa Link: https://patch.msgid.link/20241021-adau1372-of-table-v1-1-6efbc7946957@analog.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/adau1372-i2c.c | 1 + sound/soc/codecs/adau1372-spi.c | 1 + sound/soc/codecs/adau1372.c | 8 ++++++++ sound/soc/codecs/adau1372.h | 1 + 4 files changed, 11 insertions(+) diff --git a/sound/soc/codecs/adau1372-i2c.c b/sound/soc/codecs/adau1372-i2c.c index 4cdd0aa11684..96f409a26e69 100644 --- a/sound/soc/codecs/adau1372-i2c.c +++ b/sound/soc/codecs/adau1372-i2c.c @@ -29,6 +29,7 @@ MODULE_DEVICE_TABLE(i2c, adau1372_i2c_ids); static struct i2c_driver adau1372_i2c_driver = { .driver = { .name = "adau1372", + .of_match_table = adau1372_of_match, }, .probe_new = adau1372_i2c_probe, .id_table = adau1372_i2c_ids, diff --git a/sound/soc/codecs/adau1372-spi.c b/sound/soc/codecs/adau1372-spi.c index 51298e00fbd6..656bd1fabeb3 100644 --- a/sound/soc/codecs/adau1372-spi.c +++ b/sound/soc/codecs/adau1372-spi.c @@ -47,6 +47,7 @@ MODULE_DEVICE_TABLE(spi, adau1372_spi_id); static struct spi_driver adau1372_spi_driver = { .driver = { .name = "adau1372", + .of_match_table = adau1372_of_match, }, .probe = adau1372_spi_probe, .id_table = adau1372_spi_id, diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c index 98380a7ce64d..fdee689cae53 100644 --- a/sound/soc/codecs/adau1372.c +++ b/sound/soc/codecs/adau1372.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -1060,6 +1061,13 @@ const struct regmap_config adau1372_regmap_config = { }; EXPORT_SYMBOL_GPL(adau1372_regmap_config); +const struct of_device_id adau1372_of_match[] = { + { .compatible = "adi,adau1372" }, + { } +}; +EXPORT_SYMBOL_GPL(adau1372_of_match); +MODULE_DEVICE_TABLE(of, adau1372_of_match); + MODULE_DESCRIPTION("ASoC ADAU1372 CODEC driver"); MODULE_AUTHOR("Lars-Peter Clausen "); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/adau1372.h b/sound/soc/codecs/adau1372.h index a9d2c59b73a9..c55b1c24fe39 100644 --- a/sound/soc/codecs/adau1372.h +++ b/sound/soc/codecs/adau1372.h @@ -13,6 +13,7 @@ struct device; +extern const struct of_device_id adau1372_of_match[]; int adau1372_probe(struct device *dev, struct regmap *regmap, void (*switch_mode)(struct device *dev)); From 986764fd827c24847a0c464e119cf3094e394e75 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:04 +0100 Subject: [PATCH 114/256] ASoC: tegra: Add support for S24_LE audio format JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 4204eccc7b2a4fb372ea6bafc80a765c98657a99 Author: Ritu Chaudhary Date: Tue Oct 22 04:13:30 2024 +0000 ASoC: tegra: Add support for S24_LE audio format Add support for S24_LE format for all internal and IO AHUB modules, except for ASRC (which is already supported). The data flow happens as mentioned below: - ADMAIF picks 24-bit valid data and converts it to 32-bit before sending to internal AHUB modules. This makes the driver change simpler for internal AHUB modules. - IO modules CIF converts the 32-bit data to 24-bit before sending it to the external world. - To maintain consistency across modules, conversions between 24-bit and 32-bit occur either at ADMAIF or at the IO modules CIF. This feature has been thoroughly tested and verified with all internal AHUB modules on the Jetson AGX Orin Platform, as well as with the external RT5640 codec. Signed-off-by: Ritu Chaudhary Signed-off-by: Sheetal Reviewed-by: Sameer Pujar Link: https://patch.msgid.link/20241022041330.3421765-1-sheetal@nvidia.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/tegra/tegra186_dspk.c | 3 +++ sound/soc/tegra/tegra210_admaif.c | 11 +++++++++-- sound/soc/tegra/tegra210_adx.c | 9 +++++++-- sound/soc/tegra/tegra210_amx.c | 9 +++++++-- sound/soc/tegra/tegra210_dmic.c | 7 +++++-- sound/soc/tegra/tegra210_i2s.c | 14 ++++++++++++-- sound/soc/tegra/tegra210_i2s.h | 9 +++++---- sound/soc/tegra/tegra210_mixer.c | 9 +++++++-- sound/soc/tegra/tegra210_mvc.c | 9 +++++++-- sound/soc/tegra/tegra210_ope.c | 9 +++++++-- sound/soc/tegra/tegra210_sfc.c | 9 +++++++-- 11 files changed, 76 insertions(+), 22 deletions(-) diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c index 18105fab8bc2..993f197b9454 100644 --- a/sound/soc/tegra/tegra186_dspk.c +++ b/sound/soc/tegra/tegra186_dspk.c @@ -245,6 +245,7 @@ static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream, cif_conf.audio_bits = TEGRA_ACIF_BITS_16; cif_conf.client_bits = TEGRA_ACIF_BITS_16; break; + case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: cif_conf.audio_bits = TEGRA_ACIF_BITS_32; cif_conf.client_bits = TEGRA_ACIF_BITS_24; @@ -313,6 +314,7 @@ static struct snd_soc_dai_driver tegra186_dspk_dais[] = { .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, }, @@ -324,6 +326,7 @@ static struct snd_soc_dai_driver tegra186_dspk_dais[] = { .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &tegra186_dspk_dai_ops, diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c index 986bab971151..c5a11ff5606f 100644 --- a/sound/soc/tegra/tegra210_admaif.c +++ b/sound/soc/tegra/tegra210_admaif.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. +// All rights reserved. // // tegra210_admaif.c - Tegra ADMAIF driver -// -// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. #include #include @@ -285,6 +285,11 @@ static int tegra_admaif_hw_params(struct snd_pcm_substream *substream, cif_conf.client_bits = TEGRA_ACIF_BITS_16; valid_bit = DATA_16BIT; break; + case SNDRV_PCM_FORMAT_S24_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; + cif_conf.client_bits = TEGRA_ACIF_BITS_24; + valid_bit = DATA_32BIT; + break; case SNDRV_PCM_FORMAT_S32_LE: cif_conf.audio_bits = TEGRA_ACIF_BITS_32; cif_conf.client_bits = TEGRA_ACIF_BITS_32; @@ -561,6 +566,7 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .capture = { \ @@ -570,6 +576,7 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .ops = &tegra_admaif_dai_ops, \ diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c index 357f67353cf3..b080e1303b4a 100644 --- a/sound/soc/tegra/tegra210_adx.c +++ b/sound/soc/tegra/tegra210_adx.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. +// All rights reserved. // // tegra210_adx.c - Tegra210 ADX driver -// -// Copyright (c) 2021-2023 NVIDIA CORPORATION. All rights reserved. #include #include @@ -127,6 +127,7 @@ static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai, case SNDRV_PCM_FORMAT_S16_LE: audio_bits = TEGRA_ACIF_BITS_16; break; + case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: audio_bits = TEGRA_ACIF_BITS_32; break; @@ -237,6 +238,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .capture = { \ @@ -246,6 +248,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .ops = &tegra210_adx_in_dai_ops, \ @@ -260,6 +263,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = { .channels_max = 16, \ .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ @@ -269,6 +273,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = { .channels_max = 16, \ .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c index eeead670484b..8c79f206c8e9 100644 --- a/sound/soc/tegra/tegra210_amx.c +++ b/sound/soc/tegra/tegra210_amx.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. +// All rights reserved. // // tegra210_amx.c - Tegra210 AMX driver -// -// Copyright (c) 2021-2023 NVIDIA CORPORATION. All rights reserved. #include #include @@ -144,6 +144,7 @@ static int tegra210_amx_set_audio_cif(struct snd_soc_dai *dai, case SNDRV_PCM_FORMAT_S16_LE: audio_bits = TEGRA_ACIF_BITS_16; break; + case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: audio_bits = TEGRA_ACIF_BITS_32; break; @@ -266,6 +267,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .capture = { \ @@ -275,6 +277,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .ops = &tegra210_amx_in_dai_ops, \ @@ -290,6 +293,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .capture = { \ @@ -299,6 +303,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .ops = &tegra210_amx_out_dai_ops, \ diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c index be0c5ccf961b..6877dbe9becc 100644 --- a/sound/soc/tegra/tegra210_dmic.c +++ b/sound/soc/tegra/tegra210_dmic.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. +// All rights reserved. // // tegra210_dmic.c - Tegra210 DMIC driver -// -// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. #include #include @@ -139,6 +139,7 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream, case SNDRV_PCM_FORMAT_S16_LE: cif_conf.audio_bits = TEGRA_ACIF_BITS_16; break; + case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: cif_conf.audio_bits = TEGRA_ACIF_BITS_32; break; @@ -325,6 +326,7 @@ static struct snd_soc_dai_driver tegra210_dmic_dais[] = { .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, }, @@ -336,6 +338,7 @@ static struct snd_soc_dai_driver tegra210_dmic_dais[] = { .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &tegra210_dmic_dai_ops, diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c index e5efd6a49ae4..500c9299b9ed 100644 --- a/sound/soc/tegra/tegra210_i2s.c +++ b/sound/soc/tegra/tegra210_i2s.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. +// All rights reserved. // // tegra210_i2s.c - Tegra210 I2S driver -// -// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. #include #include @@ -629,6 +629,7 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream, case SNDRV_PCM_FORMAT_S16_LE: cif_conf.audio_bits = TEGRA_ACIF_BITS_16; break; + case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: cif_conf.audio_bits = TEGRA_ACIF_BITS_32; break; @@ -656,6 +657,11 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream, sample_size = 16; cif_conf.client_bits = TEGRA_ACIF_BITS_16; break; + case SNDRV_PCM_FORMAT_S24_LE: + val = I2S_BITS_24; + sample_size = 32; + cif_conf.client_bits = TEGRA_ACIF_BITS_24; + break; case SNDRV_PCM_FORMAT_S32_LE: val = I2S_BITS_32; sample_size = 32; @@ -720,6 +726,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .capture = { @@ -729,6 +736,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, }, @@ -741,6 +749,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .capture = { @@ -750,6 +759,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &tegra210_i2s_dai_ops, diff --git a/sound/soc/tegra/tegra210_i2s.h b/sound/soc/tegra/tegra210_i2s.h index fe478f3d8435..543332de7405 100644 --- a/sound/soc/tegra/tegra210_i2s.h +++ b/sound/soc/tegra/tegra210_i2s.h @@ -1,8 +1,8 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * tegra210_i2s.h - Definitions for Tegra210 I2S driver +/* SPDX-License-Identifier: GPL-2.0-only + * SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. * - * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * tegra210_i2s.h - Definitions for Tegra210 I2S driver * */ @@ -87,6 +87,7 @@ #define I2S_BITS_8 1 #define I2S_BITS_16 3 +#define I2S_BITS_24 5 #define I2S_BITS_32 7 #define I2S_CTRL_BIT_SIZE_MASK 0x7 diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c index 48889ad14527..e81231b9a8f2 100644 --- a/sound/soc/tegra/tegra210_mixer.c +++ b/sound/soc/tegra/tegra210_mixer.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. +// All rights reserved. // // tegra210_mixer.c - Tegra210 MIXER driver -// -// Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. #include #include @@ -248,6 +248,7 @@ static int tegra210_mixer_set_audio_cif(struct tegra210_mixer *mixer, case SNDRV_PCM_FORMAT_S16_LE: audio_bits = TEGRA_ACIF_BITS_16; break; + case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: audio_bits = TEGRA_ACIF_BITS_32; break; @@ -312,6 +313,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .capture = { \ @@ -321,6 +323,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .ops = &tegra210_mixer_in_dai_ops, \ @@ -336,6 +339,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .capture = { \ @@ -345,6 +349,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .ops = &tegra210_mixer_out_dai_ops, \ diff --git a/sound/soc/tegra/tegra210_mvc.c b/sound/soc/tegra/tegra210_mvc.c index e116e4f0b758..ef8ea05bf7a0 100644 --- a/sound/soc/tegra/tegra210_mvc.c +++ b/sound/soc/tegra/tegra210_mvc.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. +// All rights reserved. // // tegra210_mvc.c - Tegra210 MVC driver -// -// Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. #include #include @@ -441,6 +441,7 @@ static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc, case SNDRV_PCM_FORMAT_S16_LE: audio_bits = TEGRA_ACIF_BITS_16; break; + case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: audio_bits = TEGRA_ACIF_BITS_32; break; @@ -569,6 +570,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .capture = { @@ -578,6 +580,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, }, @@ -592,6 +595,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .capture = { @@ -601,6 +605,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &tegra210_mvc_dai_ops, diff --git a/sound/soc/tegra/tegra210_ope.c b/sound/soc/tegra/tegra210_ope.c index 5d0860722c51..bb59cd6c9d34 100644 --- a/sound/soc/tegra/tegra210_ope.c +++ b/sound/soc/tegra/tegra210_ope.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. +// All rights reserved. // // tegra210_ope.c - Tegra210 OPE driver -// -// Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. #include #include @@ -47,6 +47,7 @@ static int tegra210_ope_set_audio_cif(struct tegra210_ope *ope, case SNDRV_PCM_FORMAT_S16_LE: audio_bits = TEGRA_ACIF_BITS_16; break; + case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: audio_bits = TEGRA_ACIF_BITS_32; break; @@ -129,6 +130,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .capture = { @@ -138,6 +140,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, }, @@ -150,6 +153,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .capture = { @@ -159,6 +163,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &tegra210_ope_dai_ops, diff --git a/sound/soc/tegra/tegra210_sfc.c b/sound/soc/tegra/tegra210_sfc.c index 68f08f4a3576..5d8e454e390b 100644 --- a/sound/soc/tegra/tegra210_sfc.c +++ b/sound/soc/tegra/tegra210_sfc.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. +// All rights reserved. // // tegra210_sfc.c - Tegra210 SFC driver -// -// Copyright (c) 2021-2023 NVIDIA CORPORATION. All rights reserved. #include #include @@ -3133,6 +3133,7 @@ static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc, case SNDRV_PCM_FORMAT_S16_LE: audio_bits = TEGRA_ACIF_BITS_16; break; + case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: audio_bits = TEGRA_ACIF_BITS_32; break; @@ -3395,6 +3396,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .capture = { @@ -3404,6 +3406,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &tegra210_sfc_in_dai_ops, @@ -3417,6 +3420,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .capture = { @@ -3426,6 +3430,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &tegra210_sfc_out_dai_ops, From bf0463db822a9ce92f68cf2f0ee7797a830c9818 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:04 +0100 Subject: [PATCH 115/256] ASoC: fsl_xcvr: enable interrupt of cmdc status update JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 06461e288abcd6d67d0a870cd25731c79ebe66ab Author: Shengjiu Wang Date: Tue Oct 8 14:27:52 2024 +0800 ASoC: fsl_xcvr: enable interrupt of cmdc status update This enables the interrupt to be asserted when there is a change in Capabilities data structure / Latency request of the CMDC Status register. Signed-off-by: Shengjiu Wang Link: https://patch.msgid.link/1728368873-31379-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/fsl/fsl_xcvr.c | 4 ++++ sound/soc/fsl/fsl_xcvr.h | 1 + 2 files changed, 5 insertions(+) diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 4a5fe5fa37ed..5e0fdcffbcce 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -1265,6 +1265,10 @@ static irqreturn_t irq0_isr(int irq, void *devid) dev_dbg(dev, "DMA write request\n"); isr_clr |= FSL_XCVR_IRQ_DMA_WR_REQ; } + if (isr & FSL_XCVR_IRQ_CMDC_STATUS_UPD) { + dev_dbg(dev, "CMDC status update\n"); + isr_clr |= FSL_XCVR_IRQ_CMDC_STATUS_UPD; + } if (isr_clr) { regmap_write(regmap, FSL_XCVR_EXT_ISR_CLR, isr_clr); diff --git a/sound/soc/fsl/fsl_xcvr.h b/sound/soc/fsl/fsl_xcvr.h index 882428592e1a..ce27b13698e7 100644 --- a/sound/soc/fsl/fsl_xcvr.h +++ b/sound/soc/fsl/fsl_xcvr.h @@ -165,6 +165,7 @@ FSL_XCVR_IRQ_MUTE | \ FSL_XCVR_IRQ_FIFO_UOFL_ERR | \ FSL_XCVR_IRQ_HOST_WAKEUP | \ + FSL_XCVR_IRQ_CMDC_STATUS_UPD |\ FSL_XCVR_IRQ_ARC_MODE) #define FSL_XCVR_ISR_CMDC_TX_EN BIT(3) From aa3e604fdcf3ebe63976629b521c19fa7f29e6f2 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:04 +0100 Subject: [PATCH 116/256] ASoC: fsl_xcvr: reset RX dpath after wrong preamble JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1e5d0f106164d2089826c16bb521891d1d06d3ad Author: Shengjiu Wang Date: Tue Oct 8 14:27:53 2024 +0800 ASoC: fsl_xcvr: reset RX dpath after wrong preamble Below preamble error means wrong preamble of IEC958 received, the channel order may be wrong at the moment. FSL_XCVR_IRQ_PREAMBLE_MISMATCH FSL_XCVR_IRQ_UNEXP_PRE_REC FSL_XCVR_IRQ_M_W_PRE_MISMATCH FSL_XCVR_IRQ_B_PRE_MISMATCH All above errors may cause channel swap, to avoid such issues, need to reset the DMAC path. Signed-off-by: Shengjiu Wang Link: https://patch.msgid.link/1728368873-31379-3-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/fsl/fsl_xcvr.c | 90 ++++++++++++++++++++++++++++++++++------ sound/soc/fsl/fsl_xcvr.h | 4 ++ 2 files changed, 81 insertions(+), 13 deletions(-) diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 5e0fdcffbcce..8e0eab51ee4e 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -53,6 +53,8 @@ struct fsl_xcvr { struct snd_aes_iec958 rx_iec958; struct snd_aes_iec958 tx_iec958; u8 cap_ds[FSL_XCVR_CAPDS_SIZE]; + struct work_struct work_rst; + spinlock_t lock; /* Protect hw_reset and trigger */ }; static const struct fsl_xcvr_pll_conf { @@ -663,7 +665,10 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd, { struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - int ret; + unsigned long lock_flags; + int ret = 0; + + spin_lock_irqsave(&xcvr->lock, lock_flags); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -675,7 +680,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd, FSL_XCVR_EXT_CTRL_DPTH_RESET(tx)); if (ret < 0) { dev_err(dai->dev, "Failed to set DPATH RESET: %d\n", ret); - return ret; + goto release_lock; } if (tx) { @@ -687,7 +692,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd, FSL_XCVR_ISR_CMDC_TX_EN); if (ret < 0) { dev_err(dai->dev, "err updating isr %d\n", ret); - return ret; + goto release_lock; } fallthrough; case FSL_XCVR_MODE_SPDIF: @@ -696,7 +701,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd, FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX); if (ret < 0) { dev_err(dai->dev, "Failed to start DATA_TX: %d\n", ret); - return ret; + goto release_lock; } break; } @@ -707,14 +712,14 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd, FSL_XCVR_EXT_CTRL_DMA_DIS(tx), 0); if (ret < 0) { dev_err(dai->dev, "Failed to enable DMA: %d\n", ret); - return ret; + goto release_lock; } ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0, FSL_XCVR_IRQ_EARC_ALL, FSL_XCVR_IRQ_EARC_ALL); if (ret < 0) { dev_err(dai->dev, "Error while setting IER0: %d\n", ret); - return ret; + goto release_lock; } /* clear DPATH RESET */ @@ -723,7 +728,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd, 0); if (ret < 0) { dev_err(dai->dev, "Failed to clear DPATH RESET: %d\n", ret); - return ret; + goto release_lock; } break; @@ -736,14 +741,14 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd, FSL_XCVR_EXT_CTRL_DMA_DIS(tx)); if (ret < 0) { dev_err(dai->dev, "Failed to disable DMA: %d\n", ret); - return ret; + goto release_lock; } ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0, FSL_XCVR_IRQ_EARC_ALL, 0); if (ret < 0) { dev_err(dai->dev, "Failed to clear IER0: %d\n", ret); - return ret; + goto release_lock; } if (tx) { @@ -754,7 +759,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd, FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX); if (ret < 0) { dev_err(dai->dev, "Failed to stop DATA_TX: %d\n", ret); - return ret; + goto release_lock; } if (xcvr->soc_data->spdif_only) break; @@ -768,17 +773,20 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) { dev_err(dai->dev, "Err updating ISR %d\n", ret); - return ret; + goto release_lock; } break; } } break; default: - return -EINVAL; + ret = -EINVAL; + break; } - return 0; +release_lock: + spin_unlock_irqrestore(&xcvr->lock, lock_flags); + return ret; } static int fsl_xcvr_load_firmware(struct fsl_xcvr *xcvr) @@ -1198,6 +1206,34 @@ static const struct regmap_config fsl_xcvr_regmap_cfg = { .cache_type = REGCACHE_FLAT, }; +static void reset_rx_work(struct work_struct *work) +{ + struct fsl_xcvr *xcvr = container_of(work, struct fsl_xcvr, work_rst); + struct device *dev = &xcvr->pdev->dev; + unsigned long lock_flags; + u32 ext_ctrl; + + dev_dbg(dev, "reset rx path\n"); + spin_lock_irqsave(&xcvr->lock, lock_flags); + regmap_read(xcvr->regmap, FSL_XCVR_EXT_CTRL, &ext_ctrl); + + if (!(ext_ctrl & FSL_XCVR_EXT_CTRL_DMA_RD_DIS)) { + regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, + FSL_XCVR_EXT_CTRL_DMA_RD_DIS, + FSL_XCVR_EXT_CTRL_DMA_RD_DIS); + regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, + FSL_XCVR_EXT_CTRL_RX_DPTH_RESET, + FSL_XCVR_EXT_CTRL_RX_DPTH_RESET); + regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, + FSL_XCVR_EXT_CTRL_DMA_RD_DIS, + 0); + regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, + FSL_XCVR_EXT_CTRL_RX_DPTH_RESET, + 0); + } + spin_unlock_irqrestore(&xcvr->lock, lock_flags); +} + static irqreturn_t irq0_isr(int irq, void *devid) { struct fsl_xcvr *xcvr = (struct fsl_xcvr *)devid; @@ -1269,6 +1305,29 @@ static irqreturn_t irq0_isr(int irq, void *devid) dev_dbg(dev, "CMDC status update\n"); isr_clr |= FSL_XCVR_IRQ_CMDC_STATUS_UPD; } + if (isr & FSL_XCVR_IRQ_PREAMBLE_MISMATCH) { + dev_dbg(dev, "Preamble mismatch\n"); + isr_clr |= FSL_XCVR_IRQ_PREAMBLE_MISMATCH; + } + if (isr & FSL_XCVR_IRQ_UNEXP_PRE_REC) { + dev_dbg(dev, "Unexpected preamble received\n"); + isr_clr |= FSL_XCVR_IRQ_UNEXP_PRE_REC; + } + if (isr & FSL_XCVR_IRQ_M_W_PRE_MISMATCH) { + dev_dbg(dev, "M/W preamble mismatch\n"); + isr_clr |= FSL_XCVR_IRQ_M_W_PRE_MISMATCH; + } + if (isr & FSL_XCVR_IRQ_B_PRE_MISMATCH) { + dev_dbg(dev, "B preamble mismatch\n"); + isr_clr |= FSL_XCVR_IRQ_B_PRE_MISMATCH; + } + + if (isr & (FSL_XCVR_IRQ_PREAMBLE_MISMATCH | + FSL_XCVR_IRQ_UNEXP_PRE_REC | + FSL_XCVR_IRQ_M_W_PRE_MISMATCH | + FSL_XCVR_IRQ_B_PRE_MISMATCH)) { + schedule_work(&xcvr->work_rst); + } if (isr_clr) { regmap_write(regmap, FSL_XCVR_EXT_ISR_CLR, isr_clr); @@ -1415,11 +1474,16 @@ static int fsl_xcvr_probe(struct platform_device *pdev) fsl_xcvr_comp.name); } + INIT_WORK(&xcvr->work_rst, reset_rx_work); + spin_lock_init(&xcvr->lock); return ret; } static int fsl_xcvr_remove(struct platform_device *pdev) { + struct fsl_xcvr *xcvr = dev_get_drvdata(&pdev->dev); + + cancel_work_sync(&xcvr->work_rst); pm_runtime_disable(&pdev->dev); return 0; } diff --git a/sound/soc/fsl/fsl_xcvr.h b/sound/soc/fsl/fsl_xcvr.h index ce27b13698e7..c72cb05184df 100644 --- a/sound/soc/fsl/fsl_xcvr.h +++ b/sound/soc/fsl/fsl_xcvr.h @@ -166,6 +166,10 @@ FSL_XCVR_IRQ_FIFO_UOFL_ERR | \ FSL_XCVR_IRQ_HOST_WAKEUP | \ FSL_XCVR_IRQ_CMDC_STATUS_UPD |\ + FSL_XCVR_IRQ_B_PRE_MISMATCH |\ + FSL_XCVR_IRQ_M_W_PRE_MISMATCH |\ + FSL_XCVR_IRQ_PREAMBLE_MISMATCH |\ + FSL_XCVR_IRQ_UNEXP_PRE_REC |\ FSL_XCVR_IRQ_ARC_MODE) #define FSL_XCVR_ISR_CMDC_TX_EN BIT(3) From 270cd0cd71d1dce958dc51d16a2ad29f37255cac Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:05 +0100 Subject: [PATCH 117/256] ASoC: uniphier: Handle regmap_write errors in aio_iecout_set_enable() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9b0c65115acdcb6fd6bbeb360c1f4f7b14c9a610 Author: Ingyu Jang Date: Tue Oct 8 14:11:11 2024 +0900 ASoC: uniphier: Handle regmap_write errors in aio_iecout_set_enable() The aio_oport_set_stream_type() function did not previously check the return values of regmap_write(). If these functions fail, it could lead to silent failures when configuring the audio playback port, causing improper behavior in audio stream output via S/PDIF without any indication of an error. This patch modifies aio_oport_set_stream_type() to check the return values of regmap_write(). If regmap_write() fails, the error code is propagated back to the caller to ensure proper error handling. Signed-off-by: Ingyu Jang Link: https://patch.msgid.link/SE1P216MB2287962B462AE91B26248D19FD7E2@SE1P216MB2287.KORP216.PROD.OUTLOOK.COM Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/uniphier/aio-core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sound/soc/uniphier/aio-core.c b/sound/soc/uniphier/aio-core.c index a3447d49aca4..5ab09a57e25f 100644 --- a/sound/soc/uniphier/aio-core.c +++ b/sound/soc/uniphier/aio-core.c @@ -837,6 +837,7 @@ int aio_oport_set_stream_type(struct uniphier_aio_sub *sub, { struct regmap *r = sub->aio->chip->regmap; u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN; + int ret; switch (pc) { case IEC61937_PC_AC3: @@ -879,8 +880,13 @@ int aio_oport_set_stream_type(struct uniphier_aio_sub *sub, break; } - regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet); - regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause); + ret = regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet); + if (ret) + return ret; + + ret = regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause); + if (ret) + return ret; return 0; } From 0f84446e1573b3324962b04e18661519e5b50df4 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:33:05 +0100 Subject: [PATCH 118/256] ASoC: SOF: core: Add debug module parameters to set IPC and boot timeout JIRA: https://issues.redhat.com/browse/RHEL-80681 commit de688e50f5ef5b4937a5dbd5bfc7afb38673b936 Author: Peter Ujfalusi Date: Wed Oct 23 14:06:09 2024 +0300 ASoC: SOF: core: Add debug module parameters to set IPC and boot timeout Add two module parameters to override the IPC and boot timeout values if the SOF stack is compiled with debug enabled to allow experimenting with different timeout values without the need to recompile the kernel. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241023110610.6141-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/core.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 83fe0401baf8..79bbbcca9c60 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -24,6 +24,17 @@ static int sof_core_debug = IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE module_param_named(sof_debug, sof_core_debug, int, 0444); MODULE_PARM_DESC(sof_debug, "SOF core debug options (0x0 all off)"); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG) +static unsigned int sof_ipc_timeout_ms; +static unsigned int sof_boot_timeout_ms; +module_param_named(ipc_timeout, sof_ipc_timeout_ms, uint, 0444); +MODULE_PARM_DESC(ipc_timeout, + "Set the IPC timeout value in ms (0 to use the platform default)"); +module_param_named(boot_timeout, sof_boot_timeout_ms, uint, 0444); +MODULE_PARM_DESC(boot_timeout, + "Set the DSP boot timeout value in ms (0 to use the platform default)"); +#endif + /* SOF defaults if not provided by the platform in ms */ #define TIMEOUT_DEFAULT_IPC_MS 500 #define TIMEOUT_DEFAULT_BOOT_MS 2000 @@ -632,6 +643,15 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) else sdev->boot_timeout = plat_data->desc->boot_timeout; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG) + /* Override the timeout values with module parameter, if set */ + if (sof_ipc_timeout_ms) + sdev->ipc_timeout = sof_ipc_timeout_ms; + + if (sof_boot_timeout_ms) + sdev->boot_timeout = sof_boot_timeout_ms; +#endif + sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED); /* From 5ba37a525e604e11df44bb969d98d17ee9fae868 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:36:25 +0100 Subject: [PATCH 119/256] ASoC: SOF: sof-of-dev: add parameter to override tplg/fw_filename JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9cb86a9cf12504c8dd60b40a6a200856852c1813 Author: Anne Onciulescu Date: Thu Oct 17 14:03:13 2024 +0300 ASoC: SOF: sof-of-dev: add parameter to override tplg/fw_filename Add support to override topology and firmware filename, using module parameters. This is helpful for development and also for testing various scenarios. Signed-off-by: Anne Onciulescu Reviewed-by: Bard Liao Reviewed-by: Chao Song Reviewed-by: Peter Ujfalusi Signed-off-by: Daniel Baluta Link: https://patch.msgid.link/20241017110313.1423258-1-daniel.baluta@nxp.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/sof-of-dev.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index b2eb5c94e7cf..c05ed1e298cf 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -18,10 +18,18 @@ static char *fw_path; module_param(fw_path, charp, 0444); MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware."); +static char *fw_filename; +module_param(fw_filename, charp, 0444); +MODULE_PARM_DESC(fw_filename, "alternate filename for SOF firmware."); + static char *tplg_path; module_param(tplg_path, charp, 0444); MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology."); +static char *tplg_filename; +module_param(tplg_filename, charp, 0444); +MODULE_PARM_DESC(tplg_filename, "alternate filename for SOF topology."); + const struct dev_pm_ops sof_of_pm = { .prepare = snd_sof_prepare, .complete = snd_sof_complete, @@ -68,6 +76,8 @@ int sof_of_probe(struct platform_device *pdev) sof_pdata->ipc_file_profile_base.ipc_type = desc->ipc_default; sof_pdata->ipc_file_profile_base.fw_path = fw_path; sof_pdata->ipc_file_profile_base.tplg_path = tplg_path; + sof_pdata->ipc_file_profile_base.fw_name = fw_filename; + sof_pdata->ipc_file_profile_base.tplg_name = tplg_filename; /* set callback to be called on successful device probe to enable runtime_pm */ sof_pdata->sof_probe_complete = sof_of_probe_complete; From 90bfe1df415232f704c7666b27997fc6ffd83795 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:36:32 +0100 Subject: [PATCH 120/256] ASoC: SOF: core: Add fw, tplg and ipc type override parameters JIRA: https://issues.redhat.com/browse/RHEL-80681 commit acb219840fbc57e3135436c03d2c4c2db80e39ee Author: Peter Ujfalusi Date: Wed Oct 23 14:06:10 2024 +0300 ASoC: SOF: core: Add fw, tplg and ipc type override parameters The different bus type helpers define their own override parameters for firmware name/path, topology name/path. sof-pci-dev covers all while others just a subset. There is no technical reason to do that since these are generic platform independent parameters. Add the override module options to core (snd-sof module) and update the description for the device helper modules as deprecated. Signed-off-by: Peter Ujfalusi Reviewed-by: Daniel Baluta Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241023110610.6141-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/core.c | 44 ++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-acpi-dev.c | 4 ++-- sound/soc/sof/sof-of-dev.c | 8 +++---- sound/soc/sof/sof-pci-dev.c | 12 +++++----- 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 79bbbcca9c60..24e779e8d650 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -19,6 +19,31 @@ #define CREATE_TRACE_POINTS #include +/* Module parameters for firmware, topology and IPC type override */ +static char *override_fw_path; +module_param_named(fw_path, override_fw_path, charp, 0444); +MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware."); + +static char *override_fw_filename; +module_param_named(fw_filename, override_fw_filename, charp, 0444); +MODULE_PARM_DESC(fw_filename, "alternate filename for SOF firmware."); + +static char *override_lib_path; +module_param_named(lib_path, override_lib_path, charp, 0444); +MODULE_PARM_DESC(lib_path, "alternate path for SOF firmware libraries."); + +static char *override_tplg_path; +module_param_named(tplg_path, override_tplg_path, charp, 0444); +MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology."); + +static char *override_tplg_filename; +module_param_named(tplg_filename, override_tplg_filename, charp, 0444); +MODULE_PARM_DESC(tplg_filename, "alternate filename for SOF topology."); + +static int override_ipc_type = -1; +module_param_named(ipc_type, override_ipc_type, int, 0444); +MODULE_PARM_DESC(ipc_type, "Force SOF IPC type. 0 - IPC3, 1 - IPC4"); + /* see SOF_DBG_ flags */ static int sof_core_debug = IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE); module_param_named(sof_debug, sof_core_debug, int, 0444); @@ -581,6 +606,23 @@ static void sof_probe_work(struct work_struct *work) } } +static void +sof_apply_profile_override(struct sof_loadable_file_profile *path_override) +{ + if (override_ipc_type >= 0 && override_ipc_type < SOF_IPC_TYPE_COUNT) + path_override->ipc_type = override_ipc_type; + if (override_fw_path) + path_override->fw_path = override_fw_path; + if (override_fw_filename) + path_override->fw_name = override_fw_filename; + if (override_lib_path) + path_override->fw_lib_path = override_lib_path; + if (override_tplg_path) + path_override->tplg_path = override_tplg_path; + if (override_tplg_filename) + path_override->tplg_name = override_tplg_filename; +} + int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) { struct snd_sof_dev *sdev; @@ -612,6 +654,8 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) } } + sof_apply_profile_override(&plat_data->ipc_file_profile_base); + /* Initialize sof_ops based on the initial selected IPC version */ ret = sof_init_sof_ops(sdev); if (ret) diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index f320e7ab80c3..0e8d3ccd4d47 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -24,11 +24,11 @@ static char *fw_path; module_param(fw_path, charp, 0444); -MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware."); +MODULE_PARM_DESC(fw_path, "deprecated - moved to snd-sof module."); static char *tplg_path; module_param(tplg_path, charp, 0444); -MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology."); +MODULE_PARM_DESC(tplg_path, "deprecated - moved to snd-sof module."); static int sof_acpi_debug; module_param_named(sof_acpi_debug, sof_acpi_debug, int, 0444); diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index c05ed1e298cf..3c8d698258ae 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -16,19 +16,19 @@ static char *fw_path; module_param(fw_path, charp, 0444); -MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware."); +MODULE_PARM_DESC(fw_path, "deprecated - moved to snd-sof module."); static char *fw_filename; module_param(fw_filename, charp, 0444); -MODULE_PARM_DESC(fw_filename, "alternate filename for SOF firmware."); +MODULE_PARM_DESC(fw_filename, "deprecated - moved to snd-sof module."); static char *tplg_path; module_param(tplg_path, charp, 0444); -MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology."); +MODULE_PARM_DESC(tplg_path, "deprecated - moved to snd-sof module."); static char *tplg_filename; module_param(tplg_filename, charp, 0444); -MODULE_PARM_DESC(tplg_filename, "alternate filename for SOF topology."); +MODULE_PARM_DESC(tplg_filename, "deprecated - moved to snd-sof module."); const struct dev_pm_ops sof_of_pm = { .prepare = snd_sof_prepare, diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 38f2187da5de..fe5650616573 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -22,23 +22,23 @@ static char *fw_path; module_param(fw_path, charp, 0444); -MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware."); +MODULE_PARM_DESC(fw_path, "deprecated - moved to snd-sof module."); static char *fw_filename; module_param(fw_filename, charp, 0444); -MODULE_PARM_DESC(fw_filename, "alternate filename for SOF firmware."); +MODULE_PARM_DESC(fw_filename, "deprecated - moved to snd-sof module."); static char *lib_path; module_param(lib_path, charp, 0444); -MODULE_PARM_DESC(lib_path, "alternate path for SOF firmware libraries."); +MODULE_PARM_DESC(lib_path, "deprecated - moved to snd-sof module."); static char *tplg_path; module_param(tplg_path, charp, 0444); -MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology."); +MODULE_PARM_DESC(tplg_path, "deprecated - moved to snd-sof module."); static char *tplg_filename; module_param(tplg_filename, charp, 0444); -MODULE_PARM_DESC(tplg_filename, "alternate filename for SOF topology."); +MODULE_PARM_DESC(tplg_filename, "deprecated - moved to snd-sof module."); static int sof_pci_debug; module_param_named(sof_pci_debug, sof_pci_debug, int, 0444); @@ -46,7 +46,7 @@ MODULE_PARM_DESC(sof_pci_debug, "SOF PCI debug options (0x0 all off)"); static int sof_pci_ipc_type = -1; module_param_named(ipc_type, sof_pci_ipc_type, int, 0444); -MODULE_PARM_DESC(ipc_type, "Force SOF IPC type. 0 - IPC3, 1 - IPC4"); +MODULE_PARM_DESC(ipc_type, "deprecated - moved to snd-sof module."); static const char *sof_dmi_override_tplg_name; static bool sof_dmi_use_community_key; From 26693066501c0eee2bb4ab545c95d52a8023b63b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:36:43 +0100 Subject: [PATCH 121/256] ASoC: amd: remove dpcm_xxx flags JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 12c61265e5b687b155d08e052c2b6d78eaee4849 Author: Kuninori Morimoto Date: Sun Oct 20 23:58:38 2024 +0000 ASoC: amd: remove dpcm_xxx flags dpcm_xxx flags are no longer needed. It converts dpcm_xxx flag to xxx_only if needed. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87jze29vip.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp-da7219-max98357a.c | 20 ++++++++++---------- sound/soc/amd/acp-es8336.c | 2 -- sound/soc/amd/acp/acp-mach-common.c | 24 +++++++----------------- sound/soc/amd/acp3x-rt5682-max9836.c | 6 ++---- sound/soc/amd/vangogh/acp5x-mach.c | 6 ------ 5 files changed, 19 insertions(+), 39 deletions(-) diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index 77cf72082e73..02b04f355ca6 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -542,7 +542,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .init = cz_da7219_init, - .dpcm_playback = 1, + .playback_only = 1, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_da7219_play_ops, SND_SOC_DAILINK_REG(designware1, dlgs, platform), @@ -552,7 +552,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .stream_name = "Capture", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, - .dpcm_capture = 1, + .capture_only = 1, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_da7219_cap_ops, SND_SOC_DAILINK_REG(designware2, dlgs, platform), @@ -562,7 +562,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .stream_name = "HiFi Playback", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, - .dpcm_playback = 1, + .playback_only = 1, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_max_play_ops, SND_SOC_DAILINK_REG(designware3, mx, platform), @@ -573,7 +573,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .stream_name = "DMIC0 Capture", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, - .dpcm_capture = 1, + .capture_only = 1, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_dmic0_cap_ops, SND_SOC_DAILINK_REG(designware3, adau, platform), @@ -584,7 +584,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .stream_name = "DMIC1 Capture", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, - .dpcm_capture = 1, + .capture_only = 1, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_dmic1_cap_ops, SND_SOC_DAILINK_REG(designware2, adau, platform), @@ -598,7 +598,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .init = cz_rt5682_init, - .dpcm_playback = 1, + .playback_only = 1, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_rt5682_play_ops, SND_SOC_DAILINK_REG(designware1, rt5682, platform), @@ -608,7 +608,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { .stream_name = "Capture", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, - .dpcm_capture = 1, + .capture_only = 1, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_rt5682_cap_ops, SND_SOC_DAILINK_REG(designware2, rt5682, platform), @@ -618,7 +618,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { .stream_name = "HiFi Playback", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, - .dpcm_playback = 1, + .playback_only = 1, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_rt5682_max_play_ops, SND_SOC_DAILINK_REG(designware3, mx, platform), @@ -629,7 +629,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { .stream_name = "DMIC0 Capture", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, - .dpcm_capture = 1, + .capture_only = 1, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_rt5682_dmic0_cap_ops, SND_SOC_DAILINK_REG(designware3, adau, platform), @@ -640,7 +640,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { .stream_name = "DMIC1 Capture", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, - .dpcm_capture = 1, + .capture_only = 1, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, .ops = &cz_rt5682_dmic1_cap_ops, SND_SOC_DAILINK_REG(designware2, adau, platform), diff --git a/sound/soc/amd/acp-es8336.c b/sound/soc/amd/acp-es8336.c index 3756b8bef17b..0193b3eae7a6 100644 --- a/sound/soc/amd/acp-es8336.c +++ b/sound/soc/amd/acp-es8336.c @@ -150,8 +150,6 @@ static struct snd_soc_dai_link st_dai_es8336[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .trigger_stop = SND_SOC_TRIGGER_ORDER_LDC, - .dpcm_capture = 1, - .dpcm_playback = 1, .init = st_es8336_init, .ops = &st_es8336_ops, SND_SOC_DAILINK_REG(designware1, codec, platform), diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index e38b478e15f3..67aa0ad83486 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -1407,8 +1407,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) links[i].num_cpus = ARRAY_SIZE(sof_sp); links[i].platforms = sof_component; links[i].num_platforms = ARRAY_SIZE(sof_component); - links[i].dpcm_playback = 1; - links[i].dpcm_capture = 1; links[i].nonatomic = true; links[i].no_pcm = 1; if (!drv_data->hs_codec_id) { @@ -1444,8 +1442,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) links[i].num_cpus = ARRAY_SIZE(sof_hs); links[i].platforms = sof_component; links[i].num_platforms = ARRAY_SIZE(sof_component); - links[i].dpcm_playback = 1; - links[i].dpcm_capture = 1; links[i].nonatomic = true; links[i].no_pcm = 1; if (!drv_data->hs_codec_id) { @@ -1480,7 +1476,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) } links[i].platforms = sof_component; links[i].num_platforms = ARRAY_SIZE(sof_component); - links[i].dpcm_playback = 1; + links[i].playback_only = 1; links[i].nonatomic = true; links[i].no_pcm = 1; if (!drv_data->amp_codec_id) { @@ -1512,7 +1508,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) links[i].num_cpus = ARRAY_SIZE(sof_hs_virtual); links[i].platforms = sof_component; links[i].num_platforms = ARRAY_SIZE(sof_component); - links[i].dpcm_playback = 1; + links[i].playback_only = 1; links[i].nonatomic = true; links[i].no_pcm = 1; if (!drv_data->amp_codec_id) { @@ -1527,7 +1523,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) links[i].init = acp_card_maxim_init; } if (drv_data->amp_codec_id == MAX98388) { - links[i].dpcm_capture = 1; + links[i].playback_only = 0; links[i].codecs = max98388; links[i].num_codecs = ARRAY_SIZE(max98388); links[i].ops = &acp_max98388_ops; @@ -1553,8 +1549,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) links[i].num_cpus = ARRAY_SIZE(sof_bt); links[i].platforms = sof_component; links[i].num_platforms = ARRAY_SIZE(sof_component); - links[i].dpcm_playback = 1; - links[i].dpcm_capture = 1; links[i].nonatomic = true; links[i].no_pcm = 1; if (!drv_data->bt_codec_id) { @@ -1575,7 +1569,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) links[i].num_cpus = ARRAY_SIZE(sof_dmic); links[i].platforms = sof_component; links[i].num_platforms = ARRAY_SIZE(sof_component); - links[i].dpcm_capture = 1; + links[i].capture_only = 1; links[i].nonatomic = true; links[i].no_pcm = 1; } @@ -1614,8 +1608,6 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) links[i].num_cpus = ARRAY_SIZE(i2s_sp); links[i].platforms = platform_component; links[i].num_platforms = ARRAY_SIZE(platform_component); - links[i].dpcm_playback = 1; - links[i].dpcm_capture = 1; if (!drv_data->hs_codec_id) { /* Use dummy codec if codec id not specified */ links[i].codecs = &snd_soc_dummy_dlc; @@ -1663,8 +1655,6 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) break; } - links[i].dpcm_playback = 1; - links[i].dpcm_capture = 1; if (!drv_data->hs_codec_id) { /* Use dummy codec if codec id not specified */ links[i].codecs = &snd_soc_dummy_dlc; @@ -1692,7 +1682,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) links[i].num_cpus = ARRAY_SIZE(i2s_sp); links[i].platforms = platform_component; links[i].num_platforms = ARRAY_SIZE(platform_component); - links[i].dpcm_playback = 1; + links[i].playback_only = 1; if (!drv_data->amp_codec_id) { /* Use dummy codec if codec id not specified */ links[i].codecs = &snd_soc_dummy_dlc; @@ -1735,7 +1725,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) break; } - links[i].dpcm_playback = 1; + links[i].playback_only = 1; if (!drv_data->amp_codec_id) { /* Use dummy codec if codec id not specified */ links[i].codecs = &snd_soc_dummy_dlc; @@ -1792,7 +1782,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) break; } links[i].ops = &acp_card_dmic_ops; - links[i].dpcm_capture = 1; + links[i].capture_only = 1; } card->dai_link = links; diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index 357dfd016baf..4ca1978020a9 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -317,8 +317,6 @@ static struct snd_soc_dai_link acp3x_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, .init = acp3x_5682_init, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &acp3x_5682_ops, SND_SOC_DAILINK_REG(acp3x_i2s, rt5682, platform), }, @@ -327,7 +325,7 @@ static struct snd_soc_dai_link acp3x_dai[] = { .stream_name = "HiFi Playback", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, - .dpcm_playback = 1, + .playback_only = 1, .ops = &acp3x_max_play_ops, .cpus = acp3x_bt, .num_cpus = ARRAY_SIZE(acp3x_bt), @@ -339,7 +337,7 @@ static struct snd_soc_dai_link acp3x_dai[] = { .stream_name = "Capture DMIC0", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, - .dpcm_capture = 1, + .capture_only = 1, .ops = &acp3x_ec_cap0_ops, SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), }, diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index 7878e061ecb9..2ca904db82ab 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -276,8 +276,6 @@ static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &acp5x_8821_ops, .init = acp5x_8821_init, SND_SOC_DAILINK_REG(acp5x_i2s, nau8821, platform), @@ -288,7 +286,6 @@ static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, - .dpcm_playback = 1, .playback_only = 1, .ops = &acp5x_cs35l41_play_ops, SND_SOC_DAILINK_REG(acp5x_bt, cs35l41, platform), @@ -375,8 +372,6 @@ static struct snd_soc_dai_link acp5x_8821_98388_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &acp5x_8821_ops, .init = acp5x_8821_init, SND_SOC_DAILINK_REG(acp5x_i2s, nau8821, platform), @@ -387,7 +382,6 @@ static struct snd_soc_dai_link acp5x_8821_98388_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, - .dpcm_playback = 1, .playback_only = 1, .ops = &acp5x_max98388_play_ops, SND_SOC_DAILINK_REG(acp5x_bt, max98388, platform), From 814e3c5b1fe7507792ab31080220d4fc559c93ff Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:36:56 +0100 Subject: [PATCH 122/256] ASoC: sof: remove dpcm_xxx flags JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 90bbbf612f9e5e4548b27b213b1866b4feb670bd Author: Kuninori Morimoto Date: Sun Oct 20 23:58:49 2024 +0000 ASoC: sof: remove dpcm_xxx flags dpcm_xxx flags are no longer needed. It converts dpcm_xxx flag to xxx_only if needed. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87h6969vie.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/nocodec.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index b12b3d865ae3..c0c906a78eba 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -55,10 +55,9 @@ static int sof_nocodec_bes_setup(struct device *dev, links[i].no_pcm = 1; links[i].cpus->dai_name = drv[i].name; links[i].platforms->name = dev_name(dev->parent); - if (drv[i].playback.channels_min) - links[i].dpcm_playback = 1; - if (drv[i].capture.channels_min) - links[i].dpcm_capture = 1; + + links[i].playback_only = drv[i].playback.channels_min && !drv[i].capture.channels_min; + links[i].capture_only = !drv[i].playback.channels_min && drv[i].capture.channels_min; links[i].be_hw_params_fixup = sof_pcm_dai_link_fixup; } From daef52683dfc730a222cae12338df5ec383849a7 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:36:56 +0100 Subject: [PATCH 123/256] ASoC: intel: remove dpcm_xxx flags JIRA: https://issues.redhat.com/browse/RHEL-80681 commit d26aed5eba16bf5a4aa86bc717edf0b5ed192b93 Author: Kuninori Morimoto Date: Sun Oct 20 23:58:55 2024 +0000 ASoC: intel: remove dpcm_xxx flags dpcm_xxx flags are no longer needed. It converts dpcm_xxx flag to xxx_only if needed. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87froq9vi9.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/intel/avs/boards/da7219.c | 2 -- sound/soc/intel/avs/boards/dmic.c | 4 ++-- sound/soc/intel/avs/boards/es8336.c | 2 -- sound/soc/intel/avs/boards/hdaudio.c | 4 ---- sound/soc/intel/avs/boards/i2s_test.c | 2 -- sound/soc/intel/avs/boards/max98357a.c | 2 +- sound/soc/intel/avs/boards/max98373.c | 2 -- sound/soc/intel/avs/boards/max98927.c | 2 -- sound/soc/intel/avs/boards/nau8825.c | 2 -- sound/soc/intel/avs/boards/rt274.c | 2 -- sound/soc/intel/avs/boards/rt286.c | 2 -- sound/soc/intel/avs/boards/rt298.c | 2 -- sound/soc/intel/avs/boards/rt5514.c | 2 +- sound/soc/intel/avs/boards/rt5663.c | 2 -- sound/soc/intel/avs/boards/rt5682.c | 2 -- sound/soc/intel/avs/boards/ssm4567.c | 2 -- 16 files changed, 4 insertions(+), 32 deletions(-) diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c index 80c0a1a95654..93eba4fd2771 100644 --- a/sound/soc/intel/avs/boards/da7219.c +++ b/sound/soc/intel/avs/boards/da7219.c @@ -203,8 +203,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->exit = avs_da7219_codec_exit; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/dmic.c b/sound/soc/intel/avs/boards/dmic.c index a31aa471a1c2..4dd9591ee98b 100644 --- a/sound/soc/intel/avs/boards/dmic.c +++ b/sound/soc/intel/avs/boards/dmic.c @@ -22,7 +22,7 @@ static struct snd_soc_dai_link card_dai_links[] = { { .name = "DMIC", .id = 0, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), @@ -30,7 +30,7 @@ static struct snd_soc_dai_link card_dai_links[] = { { .name = "DMIC WoV", .id = 1, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .no_pcm = 1, .ignore_suspend = 1, diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c index c8522e2430f8..426ce37105ae 100644 --- a/sound/soc/intel/avs/boards/es8336.c +++ b/sound/soc/intel/avs/boards/es8336.c @@ -233,8 +233,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->ops = &avs_es8336_ops; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c index 430c070a1a0e..cb6d54db7189 100644 --- a/sound/soc/intel/avs/boards/hdaudio.c +++ b/sound/soc/intel/avs/boards/hdaudio.c @@ -39,8 +39,6 @@ static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int dl[i].id = i; dl[i].nonatomic = 1; dl[i].no_pcm = 1; - dl[i].dpcm_playback = 1; - dl[i].dpcm_capture = 1; dl[i].platforms = platform; dl[i].num_platforms = 1; dl[i].ignore_pmdown_time = 1; @@ -160,8 +158,6 @@ static const struct snd_soc_dai_link probing_link = { .id = -1, .nonatomic = 1, .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .cpus = &snd_soc_dummy_dlc, .num_cpus = 1, .init = avs_probing_link_init, diff --git a/sound/soc/intel/avs/boards/i2s_test.c b/sound/soc/intel/avs/boards/i2s_test.c index 7e6c8d9c900b..4556f105c793 100644 --- a/sound/soc/intel/avs/boards/i2s_test.c +++ b/sound/soc/intel/avs/boards/i2s_test.c @@ -46,8 +46,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->id = 0; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c index 8d550e82b46a..6570209c1a63 100644 --- a/sound/soc/intel/avs/boards/max98357a.c +++ b/sound/soc/intel/avs/boards/max98357a.c @@ -82,7 +82,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->be_hw_params_fixup = avs_max98357a_be_fixup; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_playback = 1; + dl->playback_only = 1; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/max98373.c b/sound/soc/intel/avs/boards/max98373.c index fdef5a008daf..6f25e66344b7 100644 --- a/sound/soc/intel/avs/boards/max98373.c +++ b/sound/soc/intel/avs/boards/max98373.c @@ -134,8 +134,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->be_hw_params_fixup = avs_max98373_be_fixup; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; dl->ignore_pmdown_time = 1; dl->ops = &avs_max98373_ops; diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c index 082f311d8b84..ad18c4e9a670 100644 --- a/sound/soc/intel/avs/boards/max98927.c +++ b/sound/soc/intel/avs/boards/max98927.c @@ -131,8 +131,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->be_hw_params_fixup = avs_max98927_be_fixup; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; dl->ignore_pmdown_time = 1; dl->ops = &avs_max98927_ops; diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c index 6ea9058fdb2a..bf902540744c 100644 --- a/sound/soc/intel/avs/boards/nau8825.c +++ b/sound/soc/intel/avs/boards/nau8825.c @@ -210,8 +210,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->ops = &avs_nau8825_ops; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c index 9fcce86c6eb4..4b6c02a40204 100644 --- a/sound/soc/intel/avs/boards/rt274.c +++ b/sound/soc/intel/avs/boards/rt274.c @@ -184,8 +184,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->be_hw_params_fixup = avs_rt274_be_fixup; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c index f157f2d19efb..e40563ca99fd 100644 --- a/sound/soc/intel/avs/boards/rt286.c +++ b/sound/soc/intel/avs/boards/rt286.c @@ -153,8 +153,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->ops = &avs_rt286_ops; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c index 1e85242c8dd2..94fce07c83f9 100644 --- a/sound/soc/intel/avs/boards/rt298.c +++ b/sound/soc/intel/avs/boards/rt298.c @@ -173,8 +173,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->ops = &avs_rt298_ops; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/rt5514.c b/sound/soc/intel/avs/boards/rt5514.c index cfa146b6cf08..30588d9e9ba3 100644 --- a/sound/soc/intel/avs/boards/rt5514.c +++ b/sound/soc/intel/avs/boards/rt5514.c @@ -121,7 +121,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->be_hw_params_fixup = avs_rt5514_be_fixup; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; + dl->capture_only = 1; dl->ops = &avs_rt5514_ops; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/rt5663.c b/sound/soc/intel/avs/boards/rt5663.c index 44f857e90969..b456b9d14665 100644 --- a/sound/soc/intel/avs/boards/rt5663.c +++ b/sound/soc/intel/avs/boards/rt5663.c @@ -171,8 +171,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->be_hw_params_fixup = avs_rt5663_be_fixup; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; dl->ops = &avs_rt5663_ops; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c index 0dcc6392a0cc..335960cfd7ba 100644 --- a/sound/soc/intel/avs/boards/rt5682.c +++ b/sound/soc/intel/avs/boards/rt5682.c @@ -242,8 +242,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->ops = &avs_rt5682_ops; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; *dai_link = dl; diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c index 63bbfc30f35e..cfef00462f66 100644 --- a/sound/soc/intel/avs/boards/ssm4567.c +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -121,8 +121,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->be_hw_params_fixup = avs_ssm4567_be_fixup; dl->nonatomic = 1; dl->no_pcm = 1; - dl->dpcm_capture = 1; - dl->dpcm_playback = 1; dl->ignore_pmdown_time = 1; *dai_link = dl; From a420cf6d83b97cad396ae072ccace18e9bc8f57b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:36:56 +0100 Subject: [PATCH 124/256] ASoC: samsung: remove dpcm_xxx flags JIRA: https://issues.redhat.com/browse/RHEL-80681 commit fa9c4b46fb76e2cb36bd8f94a096e61ebdb8b7f9 Author: Kuninori Morimoto Date: Sun Oct 20 23:59:03 2024 +0000 ASoC: samsung: remove dpcm_xxx flags dpcm_xxx flags are no longer needed. It converts dpcm_xxx flag to xxx_only if needed. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ed4a9vi0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/samsung/odroid.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 173b2ffb3f11..4ac34f0daed1 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -172,25 +172,24 @@ static struct snd_soc_dai_link odroid_card_dais[] = { .name = "Primary", .stream_name = "Primary", .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(primary), }, { /* BE <-> CODECs link */ .name = "I2S Mixer", .ops = &odroid_card_be_ops, .no_pcm = 1, - .dpcm_playback = 1, + .playback_only = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAILINK_REG(mixer), }, { /* Secondary FE <-> BE link */ - .playback_only = 1, .ops = &odroid_card_fe_ops, .name = "Secondary", .stream_name = "Secondary", .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(secondary), } }; @@ -278,8 +277,8 @@ static int odroid_audio_probe(struct platform_device *pdev) /* Set capture capability only for boards with the MAX98090 CODEC */ if (codec_link->num_codecs > 1) { - card->dai_link[0].dpcm_capture = 1; - card->dai_link[1].dpcm_capture = 1; + card->dai_link[0].playback_only = 0; + card->dai_link[1].playback_only = 0; } priv->sclk_i2s = of_clk_get_by_name(cpu_dai, "i2s_opclk1"); From a6282c89f831aa57b4bdb1b541acc22e760ddc42 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:04 +0100 Subject: [PATCH 125/256] ASoC: soc-core: remove dpcm_xxx flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit b6b8caf6470b9793ae4b66a95c742a1c97ece748 Author: Kuninori Morimoto Date: Sun Oct 20 23:59:14 2024 +0000 ASoC: soc-core: remove dpcm_xxx flags dpcm_xxx flags are no longer needed. It converts dpcm_xxx flag to xxx_only if needed. Signed-off-by: Kuninori Morimoto Reviewed-by: Amadeusz SÅ‚awiÅ„ski Signed-off-by: Amadeusz SÅ‚awiÅ„ski Link: https://patch.msgid.link/87bjze9vhp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/soc-core.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 20248a29d167..f04b671ce33e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1999,25 +1999,7 @@ match: dai_link->platforms->name = component->name; /* convert non BE into BE */ - if (!dai_link->no_pcm) { - dai_link->no_pcm = 1; - - if (dai_link->dpcm_playback) - dev_warn(card->dev, - "invalid configuration, dailink %s has flags no_pcm=0 and dpcm_playback=1\n", - dai_link->name); - if (dai_link->dpcm_capture) - dev_warn(card->dev, - "invalid configuration, dailink %s has flags no_pcm=0 and dpcm_capture=1\n", - dai_link->name); - - /* convert normal link into DPCM one */ - if (!(dai_link->dpcm_playback || - dai_link->dpcm_capture)) { - dai_link->dpcm_playback = !dai_link->capture_only; - dai_link->dpcm_capture = !dai_link->playback_only; - } - } + dai_link->no_pcm = 1; /* * override any BE fixups From b9ee1abc4e3c340bde4796022c1c42aa7d7f0842 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:04 +0100 Subject: [PATCH 126/256] ASoC: soc-compress: remove dpcm_xxx flags JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0f77c88f0e3a3945c328bbb9a9e3c4b5826e8fe0 Author: Kuninori Morimoto Date: Sun Oct 20 23:59:20 2024 +0000 ASoC: soc-compress: remove dpcm_xxx flags dpcm_xxx flags are no longer needed. It converts dpcm_xxx flag to xxx_only if needed. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a5ey9vhj.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/soc-compress.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index e692aa3b8b22..a0c55246f424 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -606,12 +606,19 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) return -ENOMEM; if (rtd->dai_link->dynamic) { + int playback = 1; + int capture = 1; + + if (rtd->dai_link->capture_only) + playback = 0; + if (rtd->dai_link->playback_only) + capture = 0; + snprintf(new_name, sizeof(new_name), "(%s)", rtd->dai_link->stream_name); ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, - rtd->dai_link->dpcm_playback, - rtd->dai_link->dpcm_capture, &be_pcm); + playback, capture, &be_pcm); if (ret < 0) { dev_err(rtd->card->dev, "Compress ASoC: can't create compressed for %s: %d\n", @@ -624,9 +631,9 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) rtd->pcm = be_pcm; rtd->fe_compr = 1; - if (rtd->dai_link->dpcm_playback) + if (playback) be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; - if (rtd->dai_link->dpcm_capture) + if (capture) be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); } else { From 7e23f6bdfeb6f42ee003cecd9d0393ad3dbbd42c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:04 +0100 Subject: [PATCH 127/256] ASoC: intel: boards: remove dpcm_xxx flags JIRA: https://issues.redhat.com/browse/RHEL-80681 commit ae0967da4bbfadc7156ba1deeb16fb31495ea359 Author: Kuninori Morimoto Date: Sun Oct 20 23:59:31 2024 +0000 ASoC: intel: boards: remove dpcm_xxx flags dpcm_xxx flags are no longer needed. It converts dpcm_xxx flag to xxx_only if needed. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877ca29vh9.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/intel/boards/bdw-rt5650.c | 4 ---- sound/soc/intel/boards/bdw-rt5677.c | 4 ---- sound/soc/intel/boards/bdw_rt286.c | 10 +++------- sound/soc/intel/boards/bytcht_cx2072x.c | 6 +----- sound/soc/intel/boards/bytcht_da7213.c | 6 +----- sound/soc/intel/boards/bytcht_es8316.c | 6 +----- sound/soc/intel/boards/bytcht_nocodec.c | 6 +----- sound/soc/intel/boards/bytcr_rt5640.c | 6 +----- sound/soc/intel/boards/bytcr_rt5651.c | 6 +----- sound/soc/intel/boards/bytcr_wm5102.c | 6 +----- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 6 +----- sound/soc/intel/boards/cht_bsw_nau8824.c | 6 +----- sound/soc/intel/boards/cht_bsw_rt5645.c | 6 +----- sound/soc/intel/boards/cht_bsw_rt5672.c | 6 +----- sound/soc/intel/boards/ehl_rt5660.c | 14 ++++++-------- sound/soc/intel/boards/hsw_rt5640.c | 10 +++------- sound/soc/intel/boards/sof_board_helpers.c | 15 ++++----------- sound/soc/intel/boards/sof_es8336.c | 8 +++----- sound/soc/intel/boards/sof_pcm512x.c | 9 ++++----- sound/soc/intel/boards/sof_wm8804.c | 2 -- 20 files changed, 34 insertions(+), 108 deletions(-) diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c index 3c7cee03a02e..d25a7188f603 100644 --- a/sound/soc/intel/boards/bdw-rt5650.c +++ b/sound/soc/intel/boards/bdw-rt5650.c @@ -239,8 +239,6 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST }, - .dpcm_playback = 1, - .dpcm_capture = 1, SND_SOC_DAILINK_REG(fe, dummy, platform), }, @@ -256,8 +254,6 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = broadwell_ssp0_fixup, .ops = &bdw_rt5650_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, .init = bdw_rt5650_init, SND_SOC_DAILINK_REG(ssp0_port, be, platform), }, diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index 304af3d06d01..9484f3410787 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -329,8 +329,6 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST }, - .dpcm_capture = 1, - .dpcm_playback = 1, .ops = &bdw_rt5677_fe_ops, SND_SOC_DAILINK_REG(fe, dummy, platform), }, @@ -356,8 +354,6 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = broadwell_ssp0_fixup, .ops = &bdw_rt5677_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, .init = bdw_rt5677_init, .exit = bdw_rt5677_exit, SND_SOC_DAILINK_REG(ssp0_port, be, platform), diff --git a/sound/soc/intel/boards/bdw_rt286.c b/sound/soc/intel/boards/bdw_rt286.c index 58db09d9b6e1..523ade9f31ab 100644 --- a/sound/soc/intel/boards/bdw_rt286.c +++ b/sound/soc/intel/boards/bdw_rt286.c @@ -133,8 +133,6 @@ static struct snd_soc_dai_link card_dai_links[] = { .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .dpcm_capture = 1, SND_SOC_DAILINK_REG(system, dummy, platform), }, { @@ -143,7 +141,7 @@ static struct snd_soc_dai_link card_dai_links[] = { .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(offload0, dummy, platform), }, { @@ -152,7 +150,7 @@ static struct snd_soc_dai_link card_dai_links[] = { .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(offload1, dummy, platform), }, { @@ -161,7 +159,7 @@ static struct snd_soc_dai_link card_dai_links[] = { .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(loopback, dummy, platform), }, /* Back End DAI links */ @@ -177,8 +175,6 @@ static struct snd_soc_dai_link card_dai_links[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = codec_link_hw_params_fixup, .ops = &codec_link_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, SND_SOC_DAILINK_REG(ssp0_port, codec, platform), }, }; diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 8c2b4ab764bb..68a3d345dc25 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -175,8 +175,6 @@ static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = { .stream_name = "Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &byt_cht_cx2072x_aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -185,7 +183,7 @@ static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &byt_cht_cx2072x_aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -198,8 +196,6 @@ static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = { | SND_SOC_DAIFMT_CBC_CFC, .init = byt_cht_cx2072x_init, .be_hw_params_fixup = byt_cht_cx2072x_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, SND_SOC_DAILINK_REG(ssp2, cx2072x, platform), }, }; diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c index 9178bbe8d995..31141d4b6b25 100644 --- a/sound/soc/intel/boards/bytcht_da7213.c +++ b/sound/soc/intel/boards/bytcht_da7213.c @@ -174,8 +174,6 @@ static struct snd_soc_dai_link dailink[] = { .stream_name = "Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -184,7 +182,7 @@ static struct snd_soc_dai_link dailink[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -197,8 +195,6 @@ static struct snd_soc_dai_link dailink[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, .be_hw_params_fixup = codec_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &ssp2_ops, SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 6447010fd4bd..1fd8b0a0728f 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -315,8 +315,6 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { .stream_name = "Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &byt_cht_es8316_aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -326,7 +324,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &byt_cht_es8316_aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -339,8 +337,6 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, .be_hw_params_fixup = byt_cht_es8316_codec_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, .init = byt_cht_es8316_init, SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, diff --git a/sound/soc/intel/boards/bytcht_nocodec.c b/sound/soc/intel/boards/bytcht_nocodec.c index 4a957d1cece3..fec23bda9e64 100644 --- a/sound/soc/intel/boards/bytcht_nocodec.c +++ b/sound/soc/intel/boards/bytcht_nocodec.c @@ -119,8 +119,6 @@ static struct snd_soc_dai_link dais[] = { .ignore_suspend = 1, .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -130,7 +128,7 @@ static struct snd_soc_dai_link dais[] = { .ignore_suspend = 1, .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -144,8 +142,6 @@ static struct snd_soc_dai_link dais[] = { | SND_SOC_DAIFMT_CBC_CFC, .be_hw_params_fixup = codec_fixup, .ignore_suspend = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, SND_SOC_DAILINK_REG(ssp2_port, dummy, platform), }, }; diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index f805a9adfd65..89e23d9349d3 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -1564,8 +1564,6 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .stream_name = "Baytrail Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &byt_rt5640_aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -1574,7 +1572,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &byt_rt5640_aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -1586,8 +1584,6 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, .be_hw_params_fixup = byt_rt5640_codec_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, .init = byt_rt5640_init, .exit = byt_rt5640_exit, .ops = &byt_rt5640_be_ssp2_ops, diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 11b0c1d22691..3400f6371922 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -770,8 +770,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = { .stream_name = "Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &byt_rt5651_aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -780,7 +778,7 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &byt_rt5651_aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -793,8 +791,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, .be_hw_params_fixup = byt_rt5651_codec_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, .init = byt_rt5651_init, .ops = &byt_rt5651_be_ssp2_ops, SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index 03864b07997f..e7618570db6f 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -462,8 +462,6 @@ static struct snd_soc_dai_link byt_wm5102_dais[] = { .stream_name = "Baytrail Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &byt_wm5102_aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), @@ -473,7 +471,7 @@ static struct snd_soc_dai_link byt_wm5102_dais[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &byt_wm5102_aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -490,8 +488,6 @@ static struct snd_soc_dai_link byt_wm5102_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, .be_hw_params_fixup = byt_wm5102_codec_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, .init = byt_wm5102_init, SND_SOC_DAILINK_REG(ssp0_port, ssp0_codec, platform), }, diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 6c166e2e30af..b000b6a19fd7 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -351,8 +351,6 @@ static struct snd_soc_dai_link cht_dailink[] = { .stream_name = "Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &cht_aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -361,7 +359,7 @@ static struct snd_soc_dai_link cht_dailink[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &cht_aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -374,8 +372,6 @@ static struct snd_soc_dai_link cht_dailink[] = { | SND_SOC_DAIFMT_CBC_CFC, .init = cht_codec_init, .be_hw_params_fixup = cht_codec_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &cht_be_ssp2_ops, SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index 7651b83632fa..4afb292d4f13 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -193,8 +193,6 @@ static struct snd_soc_dai_link cht_dailink[] = { .stream_name = "Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &cht_aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -203,7 +201,7 @@ static struct snd_soc_dai_link cht_dailink[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &cht_aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -217,8 +215,6 @@ static struct snd_soc_dai_link cht_dailink[] = { | SND_SOC_DAIFMT_CBC_CFC, .init = cht_codec_init, .be_hw_params_fixup = cht_codec_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &cht_be_ssp2_ops, SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index ac23a8b7cafc..b977a2db73a3 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -448,8 +448,6 @@ static struct snd_soc_dai_link cht_dailink[] = { .stream_name = "Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &cht_aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -458,7 +456,7 @@ static struct snd_soc_dai_link cht_dailink[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &cht_aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -470,8 +468,6 @@ static struct snd_soc_dai_link cht_dailink[] = { .no_pcm = 1, .init = cht_codec_init, .be_hw_params_fixup = cht_codec_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &cht_be_ssp2_ops, SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index c6c469d51243..aaef212cf44e 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -358,8 +358,6 @@ static struct snd_soc_dai_link cht_dailink[] = { .stream_name = "Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &cht_aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -368,7 +366,7 @@ static struct snd_soc_dai_link cht_dailink[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &cht_aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -381,8 +379,6 @@ static struct snd_soc_dai_link cht_dailink[] = { .no_pcm = 1, .init = cht_codec_init, .be_hw_params_fixup = cht_codec_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &cht_be_ssp2_ops, SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, diff --git a/sound/soc/intel/boards/ehl_rt5660.c b/sound/soc/intel/boards/ehl_rt5660.c index 90d93e667bd9..ebc417c04a50 100644 --- a/sound/soc/intel/boards/ehl_rt5660.c +++ b/sound/soc/intel/boards/ehl_rt5660.c @@ -178,8 +178,6 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = { .name = "SSP0-Codec", .id = 0, .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &rt5660_ops, SND_SOC_DAILINK_REG(ssp0_pin, rt5660_codec, platform), }, @@ -187,7 +185,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = { .name = "dmic48k", .id = 1, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, @@ -195,7 +193,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = { .name = "dmic16k", .id = 2, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform), }, @@ -203,7 +201,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = { .name = "iDisp1", .id = 5, .init = hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, @@ -211,7 +209,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = { .name = "iDisp2", .id = 6, .init = hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -219,7 +217,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = { .name = "iDisp3", .id = 7, .init = hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, @@ -227,7 +225,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = { .name = "iDisp4", .id = 8, .init = hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp4_pin, idisp4_codec, platform), }, diff --git a/sound/soc/intel/boards/hsw_rt5640.c b/sound/soc/intel/boards/hsw_rt5640.c index 1826a4dfd0f3..9bb2822ba63e 100644 --- a/sound/soc/intel/boards/hsw_rt5640.c +++ b/sound/soc/intel/boards/hsw_rt5640.c @@ -85,8 +85,6 @@ static struct snd_soc_dai_link card_dai_links[] = { .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .dpcm_capture = 1, SND_SOC_DAILINK_REG(system, dummy, platform), }, { @@ -95,7 +93,7 @@ static struct snd_soc_dai_link card_dai_links[] = { .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(offload0, dummy, platform), }, { @@ -104,7 +102,7 @@ static struct snd_soc_dai_link card_dai_links[] = { .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(offload1, dummy, platform), }, { @@ -113,7 +111,7 @@ static struct snd_soc_dai_link card_dai_links[] = { .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(loopback, dummy, platform), }, /* Back End DAI links */ @@ -127,8 +125,6 @@ static struct snd_soc_dai_link card_dai_links[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = codec_link_hw_params_fixup, .ops = &codec_link_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, SND_SOC_DAILINK_REG(ssp0_port, codec, platform), }, }; diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c index 24f716e42d6a..50e846d67c19 100644 --- a/sound/soc/intel/boards/sof_board_helpers.c +++ b/sound/soc/intel/boards/sof_board_helpers.c @@ -217,8 +217,6 @@ static int set_ssp_codec_link(struct device *dev, struct snd_soc_dai_link *link, link->id = be_id; link->no_pcm = 1; - link->dpcm_capture = 1; - link->dpcm_playback = 1; return 0; } @@ -268,7 +266,7 @@ static int set_dmic_link(struct device *dev, struct snd_soc_dai_link *link, link->init = dmic_init; link->ignore_suspend = 1; link->no_pcm = 1; - link->dpcm_capture = 1; + link->capture_only = 1; return 0; } @@ -326,7 +324,7 @@ static int set_idisp_hdmi_link(struct device *dev, struct snd_soc_dai_link *link link->id = be_id; link->init = (hdmi_id == 1) ? hdmi_init : NULL; link->no_pcm = 1; - link->dpcm_playback = 1; + link->playback_only = 1; return 0; } @@ -361,13 +359,12 @@ static int set_ssp_amp_link(struct device *dev, struct snd_soc_dai_link *link, /* codecs - caller to handle */ /* platforms */ + /* feedback stream or firmware-generated echo reference */ link->platforms = platform_component; link->num_platforms = ARRAY_SIZE(platform_component); link->id = be_id; link->no_pcm = 1; - link->dpcm_capture = 1; /* feedback stream or firmware-generated echo reference */ - link->dpcm_playback = 1; return 0; } @@ -407,8 +404,6 @@ static int set_bt_offload_link(struct device *dev, struct snd_soc_dai_link *link link->id = be_id; link->no_pcm = 1; - link->dpcm_capture = 1; - link->dpcm_playback = 1; return 0; } @@ -448,7 +443,7 @@ static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link, link->id = be_id; link->no_pcm = 1; - link->dpcm_capture = 1; + link->capture_only = 1; return 0; } @@ -496,8 +491,6 @@ static int set_hda_codec_link(struct device *dev, struct snd_soc_dai_link *link, if (be_type == SOF_HDA_ANALOG) link->init = hda_init; link->no_pcm = 1; - link->dpcm_capture = 1; - link->dpcm_playback = 1; return 0; } diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index 65e2e75ceca7..c3dc01a1451c 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -455,8 +455,6 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].exit = sof_es8316_exit; links[id].ops = &sof_es8336_ops; links[id].nonatomic = true; - links[id].dpcm_playback = 1; - links[id].dpcm_capture = 1; links[id].no_pcm = 1; links[id].cpus = &cpus[id]; links[id].num_cpus = 1; @@ -496,7 +494,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].platforms = platform_component; links[id].num_platforms = ARRAY_SIZE(platform_component); links[id].ignore_suspend = 1; - links[id].dpcm_capture = 1; + links[id].capture_only = 1; links[id].no_pcm = 1; id++; @@ -539,7 +537,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].platforms = platform_component; links[id].num_platforms = ARRAY_SIZE(platform_component); links[id].init = sof_hdmi_init; - links[id].dpcm_playback = 1; + links[id].playback_only = 1; links[id].no_pcm = 1; id++; @@ -569,7 +567,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].num_codecs = 1; links[id].platforms = platform_component; links[id].num_platforms = ARRAY_SIZE(platform_component); - links[id].dpcm_capture = 1; + links[id].capture_only = 1; links[id].no_pcm = 1; links[id].num_cpus = 1; id++; diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c index 0ebf3d546b72..f75a6c1796c7 100644 --- a/sound/soc/intel/boards/sof_pcm512x.c +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -246,12 +246,11 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].num_platforms = ARRAY_SIZE(platform_component); links[id].init = sof_pcm512x_codec_init; links[id].ops = &sof_pcm512x_ops; - links[id].dpcm_playback = 1; /* * capture only supported with specific versions of the Hifiberry DAC+ */ - if (sof_pcm512x_quirk & SOF_PCM512X_ENABLE_SSP_CAPTURE) - links[id].dpcm_capture = 1; + if (!(sof_pcm512x_quirk & SOF_PCM512X_ENABLE_SSP_CAPTURE)) + links[id].playback_only = 1; links[id].no_pcm = 1; links[id].cpus = &cpus[id]; links[id].num_cpus = 1; @@ -294,7 +293,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].platforms = platform_component; links[id].num_platforms = ARRAY_SIZE(platform_component); links[id].ignore_suspend = 1; - links[id].dpcm_capture = 1; + links[id].capture_only = 1; links[id].no_pcm = 1; id++; } @@ -341,7 +340,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].platforms = platform_component; links[id].num_platforms = ARRAY_SIZE(platform_component); links[id].init = sof_hdmi_init; - links[id].dpcm_playback = 1; + links[id].playback_only = 1; links[id].no_pcm = 1; id++; } diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c index abf70c98f057..c48637490812 100644 --- a/sound/soc/intel/boards/sof_wm8804.c +++ b/sound/soc/intel/boards/sof_wm8804.c @@ -167,8 +167,6 @@ static struct snd_soc_dai_link dailink[] = { .name = "SSP5-Codec", .id = 0, .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &sof_wm8804_ops, SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform), }, From 4e25a8291f999618be6f1e7872a2536ebb385614 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:05 +0100 Subject: [PATCH 128/256] ASoC: soc-topology: remove dpcm_xxx flags JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 44b6f24018317f6096007d9d397e6f3dfb0131ae Author: Kuninori Morimoto Date: Sun Oct 20 23:59:25 2024 +0000 ASoC: soc-topology: remove dpcm_xxx flags dpcm_xxx flags are no longer needed. It converts dpcm_xxx flag to xxx_only if needed. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qui9vhe.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/soc-topology-test.c | 2 -- sound/soc/soc-topology.c | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-topology-test.c b/sound/soc/soc-topology-test.c index a2b08568f4e8..c8f2ec29e970 100644 --- a/sound/soc/soc-topology-test.c +++ b/sound/soc/soc-topology-test.c @@ -88,8 +88,6 @@ static struct snd_soc_dai_link kunit_dai_links[] = { .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .dpcm_capture = 1, SND_SOC_DAILINK_REG(dummy, dummy, platform), }, }; diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 97517423d1f0..43003d2d3666 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1544,8 +1544,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, /* enable DPCM */ link->dynamic = 1; link->ignore_pmdown_time = 1; - link->dpcm_playback = le32_to_cpu(pcm->playback); - link->dpcm_capture = le32_to_cpu(pcm->capture); + link->playback_only = le32_to_cpu(pcm->playback) && !le32_to_cpu(pcm->capture); + link->capture_only = !le32_to_cpu(pcm->playback) && le32_to_cpu(pcm->capture); if (pcm->flag_mask) set_link_flags(link, le32_to_cpu(pcm->flag_mask), From 37ca20eb2464fd581c7dd1a4c9f242799a78e9f2 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:05 +0100 Subject: [PATCH 129/256] ASoC: soc-pcm: remove dpcm_xxx flags JIRA: https://issues.redhat.com/browse/RHEL-80681 commit c7ae6551533e7c7bf903a2d259044778f4b103ce Author: Kuninori Morimoto Date: Sun Oct 20 23:59:36 2024 +0000 ASoC: soc-pcm: remove dpcm_xxx flags dpcm_xxx flags are no longer needed. Let's remove it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/875xpm9vh3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/soc.h | 5 ----- sound/soc/soc-pcm.c | 33 --------------------------------- 2 files changed, 38 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 1d015a47c4ce..41cb9f0fcef3 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -810,11 +810,6 @@ struct snd_soc_dai_link { /* This DAI link can route to other DAI links at runtime (Frontend)*/ unsigned int dynamic:1; - /* REMOVE ME */ - /* DPCM capture and Playback support */ - unsigned int dpcm_capture:1; - unsigned int dpcm_playback:1; - /* DPCM used FE & BE merged format */ unsigned int dpcm_merged_format:1; /* DPCM used FE & BE merged channel */ diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e2c5300df0f2..5142d1abbc7b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2844,39 +2844,6 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, has_capture = 1; } - /* - * REMOVE ME - * - * dpcm_xxx flag will be removed soon, Indicates warning if dpcm_xxx flag was used - * as availability limitation - */ - if (has_playback && has_capture) { - if ( dai_link->dpcm_playback && - !dai_link->dpcm_capture && - !dai_link->playback_only) { - dev_warn(rtd->card->dev, - "both playback/capture are available," - " but not using playback_only flag (%s)\n", - dai_link->stream_name); - dev_warn(rtd->card->dev, - "dpcm_playback/capture are no longer needed," - " please use playback/capture_only instead\n"); - has_capture = 0; - } - - if (!dai_link->dpcm_playback && - dai_link->dpcm_capture && - !dai_link->capture_only) { - dev_warn(rtd->card->dev, - "both playback/capture are available," - " but not using capture_only flag (%s)\n", - dai_link->stream_name); - dev_warn(rtd->card->dev, - "dpcm_playback/capture are no longer needed," - " please use playback/capture_only instead\n"); - has_playback = 0; - } - } } else { struct snd_soc_dai *codec_dai; From 2f41ade20887933365e611e342a3b97998dd1aef Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:05 +0100 Subject: [PATCH 130/256] ASoC: doc: remove dpcm_xxx flags JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0e3dc8e4bd4a739401ada1541452fe1499254680 Author: Kuninori Morimoto Date: Sun Oct 20 23:59:43 2024 +0000 ASoC: doc: remove dpcm_xxx flags dpcm_xxx flags are no longer needed. Let's remove it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874j569vgw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- Documentation/sound/soc/dpcm.rst | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Documentation/sound/soc/dpcm.rst b/Documentation/sound/soc/dpcm.rst index 2d7ad1d91504..02419a6f8213 100644 --- a/Documentation/sound/soc/dpcm.rst +++ b/Documentation/sound/soc/dpcm.rst @@ -157,15 +157,13 @@ FE DAI links are defined as follows :- .codec_dai_name = "snd-soc-dummy-dai", .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, }, .....< other FE and BE DAI links here > }; This FE DAI link is pretty similar to a regular DAI link except that we also -set the DAI link to a DPCM FE with the ``dynamic = 1``. The supported FE stream -directions should also be set with the ``dpcm_playback`` and ``dpcm_capture`` -flags. There is also an option to specify the ordering of the trigger call for +set the DAI link to a DPCM FE with the ``dynamic = 1``. +There is also an option to specify the ordering of the trigger call for each FE. This allows the ASoC core to trigger the DSP before or after the other components (as some DSPs have strong requirements for the ordering DAI/DSP start and stop sequences). @@ -189,15 +187,12 @@ The BE DAIs are configured as follows :- .ignore_pmdown_time = 1, .be_hw_params_fixup = hswult_ssp0_fixup, .ops = &haswell_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, }, .....< other BE DAI links here > }; This BE DAI link connects DAI0 to the codec (in this case RT5460 AIF1). It sets -the ``no_pcm`` flag to mark it has a BE and sets flags for supported stream -directions using ``dpcm_playback`` and ``dpcm_capture`` above. +the ``no_pcm`` flag to mark it has a BE. The BE has also flags set for ignoring suspend and PM down time. This allows the BE to work in a hostless mode where the host CPU is not transferring data From da049c777bcee2d04ffbf64d9e1b62001bd2e8b5 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:05 +0100 Subject: [PATCH 131/256] ASoC: soc-pcm: merge DPCM and non-DPCM validation check JIRA: https://issues.redhat.com/browse/RHEL-80681 commit a6ff8572fd3fafe3f0f39e94ad8d4b6c88de7e03 Author: Kuninori Morimoto Date: Sun Oct 20 23:59:49 2024 +0000 ASoC: soc-pcm: merge DPCM and non-DPCM validation check DPCM and non-DPCM validation check are very similar. The big difference is that DPCM doesn't check Codec validation. This is historical reason. It should be checked, but it breaks existing driver/behavior. Anyway, if we uses dummy DAI as Codec when DPCM case, there is no difference between DPCM and non-DPCM. Let's merge these. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/8734kq9vgq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/soc-pcm.c | 60 +++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 5142d1abbc7b..678400e76e53 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2822,7 +2822,11 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, { struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_dai *cpu_dai; + struct snd_soc_dai *codec_dai; struct snd_soc_dai_link_ch_map *ch_maps; + struct snd_soc_dai *dummy_dai = snd_soc_find_dai(&snd_soc_dummy_dlc); + int cpu_capture; + int cpu_playback; int has_playback = 0; int has_capture = 0; int i; @@ -2832,40 +2836,38 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, return -EINVAL; } - if (dai_link->dynamic || dai_link->no_pcm) { + /* Adapt stream for codec2codec links */ + cpu_capture = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_CAPTURE); + cpu_playback = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_PLAYBACK); - for_each_rtd_ch_maps(rtd, i, ch_maps) { - cpu_dai = snd_soc_rtd_to_cpu(rtd, ch_maps->cpu); - - if (snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) - has_playback = 1; - - if (snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) - has_capture = 1; - } - - } else { - struct snd_soc_dai *codec_dai; - - /* Adapt stream for codec2codec links */ - int cpu_capture = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_CAPTURE); - int cpu_playback = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_PLAYBACK); + /* + * see + * soc.h :: [dai_link->ch_maps Image sample] + */ + for_each_rtd_ch_maps(rtd, i, ch_maps) { + cpu_dai = snd_soc_rtd_to_cpu(rtd, ch_maps->cpu); + codec_dai = snd_soc_rtd_to_codec(rtd, ch_maps->codec); /* - * see - * soc.h :: [dai_link->ch_maps Image sample] + * FIXME + * + * DPCM Codec has been no checked before. + * It should be checked, but it breaks compatibility. + * + * For example there is a case that CPU have loopback capabilities which is used + * for tests on boards where the Codec has no capture capabilities. In this case, + * Codec capture validation check will be fail, but system should allow capture + * capabilities. We have no solution for it today. */ - for_each_rtd_ch_maps(rtd, i, ch_maps) { - cpu_dai = snd_soc_rtd_to_cpu(rtd, ch_maps->cpu); - codec_dai = snd_soc_rtd_to_codec(rtd, ch_maps->codec); + if (dai_link->dynamic || dai_link->no_pcm) + codec_dai = dummy_dai; - if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && - snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) - has_playback = 1; - if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && - snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) - has_capture = 1; - } + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && + snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) + has_playback = 1; + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && + snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) + has_capture = 1; } if (dai_link->playback_only) From 4446a94f03bbbeff7a47f0b23f11ac5190ddbe46 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:05 +0100 Subject: [PATCH 132/256] ASoC: codecs: fix error code in ntp8835_i2c_probe() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9c2e48ee9aa64f609709eeb120cf728d66d4a145 Author: Harshit Mogalapalli Date: Wed Oct 23 07:44:11 2024 -0700 ASoC: codecs: fix error code in ntp8835_i2c_probe() When reset_control_deassert() fails it returns valid error codes stored in return, pass that to dev_err_probe() instead of PTR_ERR(ntp8835->reset). Fixes: dc9004ea273a ("ASoC: codecs: Add NeoFidelity NTP8835 codec") Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202409281054.DUTb5KxU-lkp@intel.com/ Signed-off-by: Harshit Mogalapalli Link: https://patch.msgid.link/20241023144421.1720234-1-harshit.m.mogalapalli@oracle.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/ntp8835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/ntp8835.c b/sound/soc/codecs/ntp8835.c index 800bda6b49dd..796e1410496f 100644 --- a/sound/soc/codecs/ntp8835.c +++ b/sound/soc/codecs/ntp8835.c @@ -428,7 +428,7 @@ static int ntp8835_i2c_probe(struct i2c_client *i2c) ret = reset_control_deassert(ntp8835->reset); if (ret) - return dev_err_probe(&i2c->dev, PTR_ERR(ntp8835->reset), + return dev_err_probe(&i2c->dev, ret, "Failed to deassert reset\n"); dev_set_drvdata(&i2c->dev, ntp8835); From 720258be5d885254893ba781b656040854ced279 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:06 +0100 Subject: [PATCH 133/256] ASoC: sun4i-codec: Add support for different DAC FIFOC addresses to quirks JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 5836a9d2ca48bb7473bb10d061c03525d8f4f163 Author: Marcus Cooper Date: Wed Oct 23 20:56:59 2024 +1300 ASoC: sun4i-codec: Add support for different DAC FIFOC addresses to quirks The Allwinner H616 SoC uses a different register address to control the output FIFO. Allow this to be specified separately from the ADC FIFO control register. Signed-off-by: Marcus Cooper Signed-off-by: Ryan Walklin Reviewed-by: Andre Przywara Tested-by: Philippe Simons Link: https://patch.msgid.link/20241023075917.186835-4-ryan@testtoast.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sunxi/sun4i-codec.c | 83 +++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index d5fd588b306d..3ad2718f8f9b 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -238,6 +238,8 @@ struct sun4i_codec { /* ADC_FIFOC register is at different offset on different SoCs */ struct regmap_field *reg_adc_fifoc; + /* DAC_FIFOC register is at different offset on different SoCs */ + struct regmap_field *reg_dac_fifoc; struct snd_dmaengine_dai_dma_data capture_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data; @@ -246,19 +248,19 @@ struct sun4i_codec { static void sun4i_codec_start_playback(struct sun4i_codec *scodec) { /* Flush TX FIFO */ - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH)); + regmap_field_set_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH)); /* Enable DAC DRQ */ - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN)); + regmap_field_set_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN)); } static void sun4i_codec_stop_playback(struct sun4i_codec *scodec) { /* Disable DAC DRQ */ - regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN)); + regmap_field_clear_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN)); } static void sun4i_codec_start_capture(struct sun4i_codec *scodec) @@ -356,13 +358,13 @@ static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream, u32 val; /* Flush the TX FIFO */ - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH)); + regmap_field_set_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH)); /* Set TX FIFO Empty Trigger Level */ - regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - 0x3f << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL, - 0xf << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL); + regmap_field_update_bits(scodec->reg_dac_fifoc, + 0x3f << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL, + 0xf << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL); if (substream->runtime->rate > 32000) /* Use 64 bits FIR filter */ @@ -371,13 +373,13 @@ static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream, /* Use 32 bits FIR filter */ val = BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION); - regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION), - val); + regmap_field_update_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION), + val); /* Send zeros when we have an underrun */ - regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_SEND_LASAT)); + regmap_field_clear_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_SEND_LASAT)); return 0; }; @@ -510,9 +512,9 @@ static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec, u32 val; /* Set DAC sample rate */ - regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - 7 << SUN4I_CODEC_DAC_FIFOC_DAC_FS, - hwrate << SUN4I_CODEC_DAC_FIFOC_DAC_FS); + regmap_field_update_bits(scodec->reg_dac_fifoc, + 7 << SUN4I_CODEC_DAC_FIFOC_DAC_FS, + hwrate << SUN4I_CODEC_DAC_FIFOC_DAC_FS); /* Set the number of channels we want to use */ if (params_channels(params) == 1) @@ -520,27 +522,27 @@ static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec, else val = 0; - regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN), - val); + regmap_field_update_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN), + val); /* Set the number of sample bits to either 16 or 24 bits */ if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) { - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS)); + regmap_field_set_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS)); /* Set TX FIFO mode to padding the LSBs with 0 */ - regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE)); + regmap_field_clear_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE)); scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; } else { - regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS)); + regmap_field_clear_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS)); /* Set TX FIFO mode to repeat the MSB */ - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE)); + regmap_field_set_bits(scodec->reg_dac_fifoc, + BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE)); scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; } @@ -587,8 +589,8 @@ static int sun4i_codec_startup(struct snd_pcm_substream *substream, * Stop issuing DRQ when we have room for less than 16 samples * in our TX FIFO */ - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, - 3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT); + regmap_field_set_bits(scodec->reg_dac_fifoc, + 3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT); return clk_prepare_enable(scodec->clk_module); } @@ -1561,6 +1563,7 @@ struct sun4i_codec_quirks { const struct snd_soc_component_driver *codec; struct snd_soc_card * (*create_card)(struct device *dev); struct reg_field reg_adc_fifoc; /* used for regmap_field */ + struct reg_field reg_dac_fifoc; /* used for regmap_field */ unsigned int reg_dac_txdata; /* TX FIFO offset for DMA config */ unsigned int reg_adc_rxdata; /* RX FIFO offset for DMA config */ bool has_reset; @@ -1571,6 +1574,7 @@ static const struct sun4i_codec_quirks sun4i_codec_quirks = { .codec = &sun4i_codec_codec, .create_card = sun4i_codec_create_card, .reg_adc_fifoc = REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31), + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31), .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA, }; @@ -1580,6 +1584,7 @@ static const struct sun4i_codec_quirks sun6i_a31_codec_quirks = { .codec = &sun6i_codec_codec, .create_card = sun6i_codec_create_card, .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31), + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31), .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA, .has_reset = true, @@ -1590,6 +1595,7 @@ static const struct sun4i_codec_quirks sun7i_codec_quirks = { .codec = &sun7i_codec_codec, .create_card = sun4i_codec_create_card, .reg_adc_fifoc = REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31), + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31), .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA, }; @@ -1599,6 +1605,7 @@ static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = { .codec = &sun8i_a23_codec_codec, .create_card = sun8i_a23_codec_create_card, .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31), + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31), .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA, .has_reset = true, @@ -1614,6 +1621,7 @@ static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = { .codec = &sun8i_a23_codec_codec, .create_card = sun8i_h3_codec_create_card, .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31), + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31), .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA, .has_reset = true, @@ -1628,6 +1636,7 @@ static const struct sun4i_codec_quirks sun8i_v3s_codec_quirks = { .codec = &sun8i_a23_codec_codec, .create_card = sun8i_v3s_codec_create_card, .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31), + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31), .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA, .has_reset = true, @@ -1735,6 +1744,16 @@ static int sun4i_codec_probe(struct platform_device *pdev) return ret; } + scodec->reg_dac_fifoc = devm_regmap_field_alloc(&pdev->dev, + scodec->regmap, + quirks->reg_dac_fifoc); + if (IS_ERR(scodec->reg_dac_fifoc)) { + ret = PTR_ERR(scodec->reg_dac_fifoc); + dev_err(&pdev->dev, "Failed to create regmap fields: %d\n", + ret); + return ret; + } + /* Enable the bus clock */ if (clk_prepare_enable(scodec->clk_apb)) { dev_err(&pdev->dev, "Failed to enable the APB clock\n"); From ae381c9fd95c32b76bbd61e9c6888a9eb4ec62a4 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:06 +0100 Subject: [PATCH 134/256] ASoC: sun4i-codec: Add playback only flag to quirks JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9fde21d6c5d1f75c2651442e5aae463545136aad Author: Marcus Cooper Date: Wed Oct 23 20:57:00 2024 +1300 ASoC: sun4i-codec: Add playback only flag to quirks Some devices only have the playback side of the codec implemented so add a quirk to check for this. This flag is only required internally within the codec driver, as the DAI is configured for playback only (capture disabled) separately in the create_card() function for these devices. Signed-off-by: Marcus Cooper Signed-off-by: Ryan Walklin Reviewed-by: Andre Przywara Tested-by: Philippe Simons Link: https://patch.msgid.link/20241023075917.186835-5-ryan@testtoast.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sunxi/sun4i-codec.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 3ad2718f8f9b..c78b8de061eb 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1567,6 +1567,7 @@ struct sun4i_codec_quirks { unsigned int reg_dac_txdata; /* TX FIFO offset for DMA config */ unsigned int reg_adc_rxdata; /* RX FIFO offset for DMA config */ bool has_reset; + bool playback_only; }; static const struct sun4i_codec_quirks sun4i_codec_quirks = { @@ -1775,10 +1776,13 @@ static int sun4i_codec_probe(struct platform_device *pdev) scodec->playback_dma_data.maxburst = 8; scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - /* DMA configuration for RX FIFO */ - scodec->capture_dma_data.addr = res->start + quirks->reg_adc_rxdata; - scodec->capture_dma_data.maxburst = 8; - scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + if (!quirks->playback_only) { + /* DMA configuration for RX FIFO */ + scodec->capture_dma_data.addr = res->start + + quirks->reg_adc_rxdata; + scodec->capture_dma_data.maxburst = 8; + scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + } ret = devm_snd_soc_register_component(&pdev->dev, quirks->codec, &sun4i_codec_dai, 1); From 450df3b9094d5a03def4a29b58dbb53d802a4fc6 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:06 +0100 Subject: [PATCH 135/256] ASoC: sun4i-codec: support allwinner H616 codec JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9155c321a1d0220a60878f2c99bc79b5a7e34d95 Author: Ryan Walklin Date: Wed Oct 23 20:57:01 2024 +1300 ASoC: sun4i-codec: support allwinner H616 codec The H616 SoC codec is playback-only with a single line-out route, and has some register differences from prior codecs. Add the required compatible string, registers, quirks, DAPM widgets, codec controls and routes, based on existing devices and the H616 datasheet. Signed-off-by: Ryan Walklin Link: https://patch.msgid.link/20241023075917.186835-6-ryan@testtoast.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sunxi/sun4i-codec.c | 203 ++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index c78b8de061eb..b053c574d7de 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -226,6 +226,43 @@ #define SUN8I_H3_CODEC_DAC_DBG (0x48) #define SUN8I_H3_CODEC_ADC_DBG (0x4c) +/* H616 specific registers */ +#define SUN50I_H616_CODEC_DAC_FIFOC (0x10) + +#define SUN50I_DAC_FIFO_STA (0x14) +#define SUN50I_DAC_TXE_INT (3) +#define SUN50I_DAC_TXU_INT (2) +#define SUN50I_DAC_TXO_INT (1) + +#define SUN50I_DAC_CNT (0x24) +#define SUN50I_DAC_DG_REG (0x28) +#define SUN50I_DAC_DAP_CTL (0xf0) + +#define SUN50I_H616_DAC_AC_DAC_REG (0x310) +#define SUN50I_H616_DAC_LEN (15) +#define SUN50I_H616_DAC_REN (14) +#define SUN50I_H616_LINEOUTL_EN (13) +#define SUN50I_H616_LMUTE (12) +#define SUN50I_H616_LINEOUTR_EN (11) +#define SUN50I_H616_RMUTE (10) +#define SUN50I_H616_RSWITCH (9) +#define SUN50I_H616_RAMPEN (8) +#define SUN50I_H616_LINEOUTL_SEL (6) +#define SUN50I_H616_LINEOUTR_SEL (5) +#define SUN50I_H616_LINEOUT_VOL (0) + +#define SUN50I_H616_DAC_AC_MIXER_REG (0x314) +#define SUN50I_H616_LMIX_LDAC (21) +#define SUN50I_H616_LMIX_RDAC (20) +#define SUN50I_H616_RMIX_RDAC (17) +#define SUN50I_H616_RMIX_LDAC (16) +#define SUN50I_H616_LMIXEN (11) +#define SUN50I_H616_RMIXEN (10) + +#define SUN50I_H616_DAC_AC_RAMP_REG (0x31c) +#define SUN50I_H616_RAMP_STEP (4) +#define SUN50I_H616_RDEN (0) + /* TODO H3 DAP (Digital Audio Processing) bits */ struct sun4i_codec { @@ -1516,6 +1553,150 @@ static struct snd_soc_card *sun8i_v3s_codec_create_card(struct device *dev) return card; }; +static const struct snd_kcontrol_new sun50i_h616_codec_codec_controls[] = { + SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC, + SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1, + sun6i_codec_dvol_scale), + SOC_SINGLE_TLV("Line Out Playback Volume", + SUN50I_H616_DAC_AC_DAC_REG, + SUN50I_H616_LINEOUT_VOL, 0x1f, 0, + sun6i_codec_lineout_vol_scale), + SOC_DOUBLE("Line Out Playback Switch", + SUN50I_H616_DAC_AC_DAC_REG, + SUN50I_H616_LINEOUTL_EN, + SUN50I_H616_LINEOUTR_EN, 1, 0), +}; + +static const struct snd_kcontrol_new sun50i_h616_codec_mixer_controls[] = { + SOC_DAPM_DOUBLE("DAC Playback Switch", + SUN50I_H616_DAC_AC_MIXER_REG, + SUN50I_H616_LMIX_LDAC, + SUN50I_H616_RMIX_RDAC, 1, 0), + SOC_DAPM_DOUBLE("DAC Reversed Playback Switch", + SUN50I_H616_DAC_AC_MIXER_REG, + SUN50I_H616_LMIX_RDAC, + SUN50I_H616_RMIX_LDAC, 1, 0), +}; + +static SOC_ENUM_DOUBLE_DECL(sun50i_h616_codec_lineout_src_enum, + SUN50I_H616_DAC_AC_DAC_REG, + SUN50I_H616_LINEOUTL_SEL, + SUN50I_H616_LINEOUTR_SEL, + sun6i_codec_lineout_src_enum_text); + +static const struct snd_kcontrol_new sun50i_h616_codec_lineout_src[] = { + SOC_DAPM_ENUM("Line Out Source Playback Route", + sun50i_h616_codec_lineout_src_enum), +}; + +static const struct snd_soc_dapm_widget sun50i_h616_codec_codec_widgets[] = { + /* Digital parts of the DACs */ + SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC, + SUN4I_CODEC_DAC_DPC_EN_DA, 0, + NULL, 0), + + /* Analog parts of the DACs */ + SND_SOC_DAPM_DAC("Left DAC", "Codec Playback", + SUN50I_H616_DAC_AC_DAC_REG, + SUN50I_H616_DAC_LEN, 0), + SND_SOC_DAPM_DAC("Right DAC", "Codec Playback", + SUN50I_H616_DAC_AC_DAC_REG, + SUN50I_H616_DAC_REN, 0), + + /* Mixers */ + SOC_MIXER_ARRAY("Left Mixer", SUN50I_H616_DAC_AC_MIXER_REG, + SUN50I_H616_LMIXEN, 0, + sun50i_h616_codec_mixer_controls), + SOC_MIXER_ARRAY("Right Mixer", SUN50I_H616_DAC_AC_MIXER_REG, + SUN50I_H616_RMIXEN, 0, + sun50i_h616_codec_mixer_controls), + + /* Line Out path */ + SND_SOC_DAPM_MUX("Line Out Source Playback Route", + SND_SOC_NOPM, 0, 0, sun50i_h616_codec_lineout_src), + SND_SOC_DAPM_OUT_DRV("Line Out Ramp Controller", + SUN50I_H616_DAC_AC_RAMP_REG, + SUN50I_H616_RDEN, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("LINEOUT"), +}; + +static const struct snd_soc_component_driver sun50i_h616_codec_codec = { + .controls = sun50i_h616_codec_codec_controls, + .num_controls = ARRAY_SIZE(sun50i_h616_codec_codec_controls), + .dapm_widgets = sun50i_h616_codec_codec_widgets, + .num_dapm_widgets = ARRAY_SIZE(sun50i_h616_codec_codec_widgets), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, +}; + +static const struct snd_kcontrol_new sun50i_h616_card_controls[] = { + SOC_DAPM_PIN_SWITCH("LINEOUT"), +}; + +static const struct snd_soc_dapm_widget sun50i_h616_codec_card_dapm_widgets[] = { + SND_SOC_DAPM_LINE("Line Out", NULL), + SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event), +}; + +/* Connect digital side enables to analog side widgets */ +static const struct snd_soc_dapm_route sun50i_h616_codec_card_routes[] = { + /* DAC Routes */ + { "Left DAC", NULL, "DAC Enable" }, + { "Right DAC", NULL, "DAC Enable" }, + + /* Left Mixer Routes */ + { "Left Mixer", "DAC Playback Switch", "Left DAC" }, + { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" }, + + /* Right Mixer Routes */ + { "Right Mixer", "DAC Playback Switch", "Right DAC" }, + { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" }, + + /* Line Out Routes */ + { "Line Out Source Playback Route", "Stereo", "Left Mixer" }, + { "Line Out Source Playback Route", "Stereo", "Right Mixer" }, + { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" }, + { "Line Out Source Playback Route", "Mono Differential", "Right Mixer" }, + { "Line Out Ramp Controller", NULL, "Line Out Source Playback Route" }, + { "LINEOUT", NULL, "Line Out Ramp Controller" }, +}; + +static struct snd_soc_card *sun50i_h616_codec_create_card(struct device *dev) +{ + struct snd_soc_card *card; + int ret; + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return ERR_PTR(-ENOMEM); + + card->dai_link = sun4i_codec_create_link(dev, &card->num_links); + if (!card->dai_link) + return ERR_PTR(-ENOMEM); + + card->dai_link->playback_only = true; + card->dai_link->capture_only = false; + + card->dev = dev; + card->owner = THIS_MODULE; + card->name = "H616 Audio Codec"; + card->driver_name = "sun4i-codec"; + card->controls = sun50i_h616_card_controls; + card->num_controls = ARRAY_SIZE(sun50i_h616_card_controls); + card->dapm_widgets = sun50i_h616_codec_card_dapm_widgets; + card->num_dapm_widgets = ARRAY_SIZE(sun50i_h616_codec_card_dapm_widgets); + card->dapm_routes = sun50i_h616_codec_card_routes; + card->num_dapm_routes = ARRAY_SIZE(sun50i_h616_codec_card_routes); + card->fully_routed = true; + + ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing"); + if (ret) + dev_warn(dev, "failed to parse audio-routing: %d\n", ret); + + return card; +}; + static const struct regmap_config sun4i_codec_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -1558,6 +1739,14 @@ static const struct regmap_config sun8i_v3s_codec_regmap_config = { .max_register = SUN8I_H3_CODEC_ADC_DBG, }; +static const struct regmap_config sun50i_h616_codec_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = SUN50I_H616_DAC_AC_RAMP_REG, + .cache_type = REGCACHE_NONE, +}; + struct sun4i_codec_quirks { const struct regmap_config *regmap_config; const struct snd_soc_component_driver *codec; @@ -1643,6 +1832,15 @@ static const struct sun4i_codec_quirks sun8i_v3s_codec_quirks = { .has_reset = true, }; +static const struct sun4i_codec_quirks sun50i_h616_codec_quirks = { + .regmap_config = &sun50i_h616_codec_regmap_config, + .codec = &sun50i_h616_codec_codec, + .create_card = sun50i_h616_codec_create_card, + .reg_dac_fifoc = REG_FIELD(SUN50I_H616_CODEC_DAC_FIFOC, 0, 31), + .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA, + .has_reset = true, +}; + static const struct of_device_id sun4i_codec_of_match[] = { { .compatible = "allwinner,sun4i-a10-codec", @@ -1668,6 +1866,10 @@ static const struct of_device_id sun4i_codec_of_match[] = { .compatible = "allwinner,sun8i-v3s-codec", .data = &sun8i_v3s_codec_quirks, }, + { + .compatible = "allwinner,sun50i-h616-codec", + .data = &sun50i_h616_codec_quirks, + }, {} }; MODULE_DEVICE_TABLE(of, sun4i_codec_of_match); @@ -1858,4 +2060,5 @@ MODULE_AUTHOR("Emilio López "); MODULE_AUTHOR("Jon Smirl "); MODULE_AUTHOR("Maxime Ripard "); MODULE_AUTHOR("Chen-Yu Tsai "); +MODULE_AUTHOR("Ryan Walklin Date: Mon, 17 Mar 2025 13:37:06 +0100 Subject: [PATCH 136/256] ASoC: rt-sdw-common: fix rt_sdca_index_update_bits function parameter description JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 4d9661e28be13f90db43b889fd15f4aad53de7d1 Author: Bard Liao Date: Thu Oct 24 14:02:05 2024 +0800 ASoC: rt-sdw-common: fix rt_sdca_index_update_bits function parameter description Fix the mismatch between function parameter and description. Below warning are reported with W=1. warning: Function parameter or struct member 'val' not described in 'rt_sdca_index_update_bits' warning: Excess function parameter 'value' description in 'rt_sdca_index_update_bits' Signed-off-by: Bard Liao Reviewed-by: Shuming Fan Link: https://patch.msgid.link/20241024060205.20201-1-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/rt-sdw-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt-sdw-common.c b/sound/soc/codecs/rt-sdw-common.c index 9f51fec383f9..ad61943ce75f 100644 --- a/sound/soc/codecs/rt-sdw-common.c +++ b/sound/soc/codecs/rt-sdw-common.c @@ -76,7 +76,7 @@ EXPORT_SYMBOL_GPL(rt_sdca_index_read); * @nid: Realtek-defined ID. * @reg: register. * @mask: Bitmask to change - * @value: New value for bitmask + * @val: New value for bitmask * * A value of zero will be returned on success, a negative errno will * be returned in error cases. From 93f74decf98eb8b06fa38cdf54989c8dd61b8622 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:06 +0100 Subject: [PATCH 137/256] ASoC: cs42l84: Add new codec driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 250304a0fb34bb74f4726645ae24dc31d7582a22 Author: Martin PoviÅ¡er Date: Sun Oct 20 00:47:32 2024 +1000 ASoC: cs42l84: Add new codec driver The CS42L84 is a codec from Cirrus Logic found in Apple Silicon Macs. The chip continues Apple's long tradition of compelling vendors to spin out bespoke SKUs that are based on existing IP but made subtly incompatible with the publicly available part. CS42L84 is very similar to CS42L42, but has a different regmap. Signed-off-by: Martin PoviÅ¡er Signed-off-by: Hector Martin Signed-off-by: James Calligeros Reviewed-by: Neal Gompa Link: https://patch.msgid.link/20241020-cs42l84-v2-2-37ba2b6721d9@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- MAINTAINERS | 1 + sound/soc/codecs/Kconfig | 7 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/cs42l84.c | 1082 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/cs42l84.h | 210 +++++++ 5 files changed, 1302 insertions(+) create mode 100644 sound/soc/codecs/cs42l84.c create mode 100644 sound/soc/codecs/cs42l84.h diff --git a/MAINTAINERS b/MAINTAINERS index 87278aecf6e9..eed52bedf6d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1789,6 +1789,7 @@ F: Documentation/devicetree/bindings/sound/adi,ssm3515.yaml F: Documentation/devicetree/bindings/sound/apple,* F: sound/soc/apple/* F: sound/soc/codecs/cs42l83-i2c.c +F: sound/soc/codecs/cs42l84.* F: sound/soc/codecs/ssm3515.c ARM/ARTPEC MACHINE SUPPORT diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6fc6bfe5be8b..deab09965010 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -84,6 +84,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_CS42L52 imply SND_SOC_CS42L56 imply SND_SOC_CS42L73 + imply SND_SOC_CS42L84 imply SND_SOC_CS4234 imply SND_SOC_CS4265 imply SND_SOC_CS4270 @@ -911,6 +912,12 @@ config SND_SOC_CS42L83 select REGMAP_I2C select SND_SOC_CS42L42_CORE +config SND_SOC_CS42L84 + tristate "Cirrus Logic CS42L84 CODEC" + depends on I2C + select REGMAP + select REGMAP_I2C + config SND_SOC_CS4234 tristate "Cirrus Logic CS4234 CODEC" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index c2eb999a1d92..e7912ed26673 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -90,6 +90,7 @@ snd-soc-cs42l52-y := cs42l52.o snd-soc-cs42l56-y := cs42l56.o snd-soc-cs42l73-y := cs42l73.o snd-soc-cs42l83-i2c-y := cs42l83-i2c.o +snd-soc-cs42l84-objs := cs42l84.o snd-soc-cs4234-y := cs4234.o snd-soc-cs4265-y := cs4265.o snd-soc-cs4270-y := cs4270.o @@ -494,6 +495,7 @@ obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o obj-$(CONFIG_SND_SOC_CS42L83) += snd-soc-cs42l83-i2c.o +obj-$(CONFIG_SND_SOC_CS42L84) += snd-soc-cs42l84.o obj-$(CONFIG_SND_SOC_CS4234) += snd-soc-cs4234.o obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o diff --git a/sound/soc/codecs/cs42l84.c b/sound/soc/codecs/cs42l84.c new file mode 100644 index 000000000000..84a1e8ac818c --- /dev/null +++ b/sound/soc/codecs/cs42l84.c @@ -0,0 +1,1082 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * cs42l84.c -- CS42L84 ALSA SoC audio driver + * + * Copyright (C) The Asahi Linux Contributors + * + * Based on sound/soc/codecs/cs42l42{.c,.h} + * Copyright 2016 Cirrus Logic, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cs42l84.h" +#include "cirrus_legacy.h" + +struct cs42l84_private { + struct regmap *regmap; + struct device *dev; + struct gpio_desc *reset_gpio; + struct snd_soc_jack *jack; + struct mutex irq_lock; + u8 plug_state; + int pll_config; + int bclk; + u8 pll_mclk_f; + u32 srate; + u8 stream_use; + int hs_type; +}; + +static bool cs42l84_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS42L84_DEVID ... CS42L84_DEVID+5: + case CS42L84_TSRS_PLUG_INT_STATUS: + case CS42L84_PLL_LOCK_STATUS: + case CS42L84_TSRS_PLUG_STATUS: + case CS42L84_HS_DET_STATUS2: + return true; + default: + return false; + } +} + +static const struct regmap_config cs42l84_regmap = { + .reg_bits = 16, + .val_bits = 8, + + .volatile_reg = cs42l84_volatile_register, + + .max_register = 0x73fe, + + .cache_type = REGCACHE_MAPLE, + + .use_single_read = true, + .use_single_write = true, +}; + +static int cs42l84_put_dac_vol(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *val) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kctl); + struct soc_mixer_control *mc = (struct soc_mixer_control *) kctl->private_value; + int vola, volb; + int ret, ret2, updated = 0; + + vola = val->value.integer.value[0] + mc->min; + volb = val->value.integer.value[1] + mc->min; + + if (vola < mc->min || vola > mc->max || volb < mc->min || volb > mc->max) + return -EINVAL; + + ret = snd_soc_component_update_bits(component, CS42L84_FRZ_CTL, + CS42L84_FRZ_CTL_ENGAGE, + CS42L84_FRZ_CTL_ENGAGE); + if (ret < 0) + goto bail; + updated |= ret; + + ret = snd_soc_component_update_bits(component, CS42L84_DAC_CHA_VOL_LSB, + 0xff, vola & 0xff); + if (ret < 0) + goto bail; + updated |= ret; + + ret = snd_soc_component_update_bits(component, CS42L84_DAC_CHA_VOL_MSB, + 0xff, (vola >> 8) & 0x01); + if (ret < 0) + goto bail; + updated |= ret; + + ret = snd_soc_component_update_bits(component, CS42L84_DAC_CHB_VOL_LSB, + 0xff, volb & 0xff); + if (ret < 0) + goto bail; + updated |= ret; + + ret = snd_soc_component_update_bits(component, CS42L84_DAC_CHB_VOL_MSB, + 0xff, (volb >> 8) & 0x01); + if (ret < 0) + goto bail; + ret |= updated; + +bail: + ret2 = snd_soc_component_update_bits(component, CS42L84_FRZ_CTL, + CS42L84_FRZ_CTL_ENGAGE, 0); + if (ret2 < 0 && ret >= 0) + ret = ret2; + + return ret; +} + +static int cs42l84_get_dac_vol(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *val) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kctl); + struct soc_mixer_control *mc = (struct soc_mixer_control *) kctl->private_value; + int vola, volb; + int ret; + + ret = snd_soc_component_read(component, CS42L84_DAC_CHA_VOL_LSB); + if (ret < 0) + return ret; + vola = ret; + + ret = snd_soc_component_read(component, CS42L84_DAC_CHA_VOL_MSB); + if (ret < 0) + return ret; + vola |= (ret & 1) << 8; + + ret = snd_soc_component_read(component, CS42L84_DAC_CHB_VOL_LSB); + if (ret < 0) + return ret; + volb = ret; + + ret = snd_soc_component_read(component, CS42L84_DAC_CHB_VOL_MSB); + if (ret < 0) + return ret; + volb |= (ret & 1) << 8; + + if (vola & BIT(8)) + vola |= ~((int)(BIT(8) - 1)); + if (volb & BIT(8)) + volb |= ~((int)(BIT(8) - 1)); + + val->value.integer.value[0] = vola - mc->min; + val->value.integer.value[1] = volb - mc->min; + + return 0; +} + +static const DECLARE_TLV_DB_SCALE(cs42l84_dac_tlv, -12800, 50, true); +static const DECLARE_TLV_DB_SCALE(cs42l84_adc_tlv, -1200, 50, false); +static const DECLARE_TLV_DB_SCALE(cs42l84_pre_tlv, 0, 1000, false); + +static const struct snd_kcontrol_new cs42l84_snd_controls[] = { + SOC_DOUBLE_R_S_EXT_TLV("DAC Playback Volume", CS42L84_DAC_CHA_VOL_LSB, + CS42L84_DAC_CHB_VOL_LSB, 0, -256, 24, 8, 0, + cs42l84_get_dac_vol, cs42l84_put_dac_vol, cs42l84_dac_tlv), + SOC_SINGLE_TLV("ADC Preamp Capture Volume", CS42L84_ADC_CTL1, + CS42L84_ADC_CTL1_PREAMP_GAIN_SHIFT, 2, 0, cs42l84_pre_tlv), + SOC_SINGLE_TLV("ADC PGA Capture Volume", CS42L84_ADC_CTL1, + CS42L84_ADC_CTL1_PGA_GAIN_SHIFT, 24, 0, cs42l84_adc_tlv), + SOC_SINGLE("ADC WNF Switch", CS42L84_ADC_CTL4, + CS42L84_ADC_CTL4_WNF_EN_SHIFT, 1, 0), + SOC_SINGLE("WNF Corner Frequency", CS42L84_ADC_CTL4, + CS42L84_ADC_CTL4_WNF_CF_SHIFT, 3, 0), + SOC_SINGLE("ADC HPF Switch", CS42L84_ADC_CTL4, + CS42L84_ADC_CTL4_HPF_EN_SHIFT, 1, 0), + SOC_SINGLE("HPF Corner Frequency", CS42L84_ADC_CTL4, + CS42L84_ADC_CTL4_HPF_CF_SHIFT, 3, 0), +}; + +static const char * const cs42l84_mux_text[] = { + "Blank", "ADC", "ASP RX CH1", "ASP RX CH2", +}; + +static const unsigned int cs42l84_mux_values[] = { + 0b0000, 0b0111, 0b1101, 0b1110, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(cs42l84_daca_mux_enum, + CS42L84_BUS_DAC_SRC, CS42L84_BUS_DAC_SRC_DACA_SHIFT, + 0b1111, cs42l84_mux_text, cs42l84_mux_values); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs42l84_dacb_mux_enum, + CS42L84_BUS_DAC_SRC, CS42L84_BUS_DAC_SRC_DACB_SHIFT, + 0b1111, cs42l84_mux_text, cs42l84_mux_values); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs42l84_sdout1_mux_enum, + CS42L84_BUS_ASP_TX_SRC, CS42L84_BUS_ASP_TX_SRC_CH1_SHIFT, + 0b1111, cs42l84_mux_text, cs42l84_mux_values); + +static const struct snd_kcontrol_new cs42l84_daca_mux_ctrl = + SOC_DAPM_ENUM("DACA Select", cs42l84_daca_mux_enum); + +static const struct snd_kcontrol_new cs42l84_dacb_mux_ctrl = + SOC_DAPM_ENUM("DACB Select", cs42l84_dacb_mux_enum); + +static const struct snd_kcontrol_new cs42l84_sdout1_mux_ctrl = + SOC_DAPM_ENUM("SDOUT1 Select", cs42l84_sdout1_mux_enum); + +static const struct snd_soc_dapm_widget cs42l84_dapm_widgets[] = { + /* Playback Path */ + SND_SOC_DAPM_OUTPUT("HP"), + SND_SOC_DAPM_DAC("DAC", NULL, CS42L84_MSM_BLOCK_EN2, CS42L84_MSM_BLOCK_EN2_DAC_SHIFT, 0), + SND_SOC_DAPM_MUX("DACA Select", SND_SOC_NOPM, 0, 0, &cs42l84_daca_mux_ctrl), + SND_SOC_DAPM_MUX("DACB Select", SND_SOC_NOPM, 0, 0, &cs42l84_dacb_mux_ctrl), + SND_SOC_DAPM_AIF_IN("SDIN1", NULL, 0, CS42L84_ASP_RX_EN, CS42L84_ASP_RX_EN_CH1_SHIFT, 0), + SND_SOC_DAPM_AIF_IN("SDIN2", NULL, 1, CS42L84_ASP_RX_EN, CS42L84_ASP_RX_EN_CH2_SHIFT, 0), + + /* Capture Path */ + SND_SOC_DAPM_INPUT("HS"), + SND_SOC_DAPM_ADC("ADC", NULL, CS42L84_MSM_BLOCK_EN2, CS42L84_MSM_BLOCK_EN2_ADC_SHIFT, 0), + SND_SOC_DAPM_MUX("SDOUT1 Select", SND_SOC_NOPM, 0, 0, &cs42l84_sdout1_mux_ctrl), + SND_SOC_DAPM_AIF_OUT("SDOUT1", NULL, 0, CS42L84_ASP_TX_EN, CS42L84_ASP_TX_EN_CH1_SHIFT, 0), + + /* Playback/Capture Requirements */ + SND_SOC_DAPM_SUPPLY("BUS", CS42L84_MSM_BLOCK_EN2, CS42L84_MSM_BLOCK_EN2_BUS_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ASP", CS42L84_MSM_BLOCK_EN2, CS42L84_MSM_BLOCK_EN2_ASP_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("BCLK", CS42L84_ASP_CTL, CS42L84_ASP_CTL_BCLK_EN_SHIFT, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route cs42l84_audio_map[] = { + /* Playback Path */ + {"HP", NULL, "DAC"}, + {"DAC", NULL, "DACA Select"}, + {"DAC", NULL, "DACB Select"}, + {"DACA Select", "ASP RX CH1", "SDIN1"}, + {"DACA Select", "ASP RX CH2", "SDIN2"}, + {"DACB Select", "ASP RX CH1", "SDIN1"}, + {"DACB Select", "ASP RX CH2", "SDIN2"}, + {"SDIN1", NULL, "Playback"}, + {"SDIN2", NULL, "Playback"}, + + {"ADC", NULL, "HS"}, + {"SDOUT1 Select", "ADC", "ADC"}, + {"SDOUT1", NULL, "SDOUT1 Select"}, + {"Capture", NULL, "SDOUT1"}, + + /* Playback Requirements */ + {"DAC", NULL, "BUS"}, + {"SDIN1", NULL, "ASP"}, + {"SDIN2", NULL, "ASP"}, + {"SDIN1", NULL, "BCLK"}, + {"SDIN2", NULL, "BCLK"}, + + /* Capture Requirements */ + {"SDOUT1", NULL, "BUS"}, + {"SDOUT1", NULL, "ASP"}, + {"SDOUT1", NULL, "BCLK"}, +}; + +static int cs42l84_set_jack(struct snd_soc_component *component, struct snd_soc_jack *jk, void *d) +{ + struct cs42l84_private *cs42l84 = snd_soc_component_get_drvdata(component); + + /* Prevent race with interrupt handler */ + mutex_lock(&cs42l84->irq_lock); + cs42l84->jack = jk; + snd_soc_jack_report(jk, cs42l84->hs_type, SND_JACK_HEADSET); + mutex_unlock(&cs42l84->irq_lock); + + return 0; +} + +static int cs42l84_component_probe(struct snd_soc_component *component) +{ + snd_soc_component_update_bits(component, CS42L84_ASP_CTL, + CS42L84_ASP_CTL_TDM_MODE, 0); + snd_soc_component_update_bits(component, CS42L84_HP_VOL_CTL, + CS42L84_HP_VOL_CTL_SOFT | CS42L84_HP_VOL_CTL_ZERO_CROSS, + CS42L84_HP_VOL_CTL_ZERO_CROSS); + + /* TDM settings */ + snd_soc_component_update_bits(component, CS42L84_ASP_RX_CH1_CTL1, + CS42L84_ASP_RX_CHx_CTL1_EDGE | + CS42L84_ASP_RX_CHx_CTL1_SLOT_START_LSB, 0); + snd_soc_component_update_bits(component, CS42L84_ASP_RX_CH1_CTL2, + CS42L84_ASP_RX_CHx_CTL2_SLOT_START_MSB, 0); + snd_soc_component_update_bits(component, CS42L84_ASP_RX_CH2_CTL1, + CS42L84_ASP_RX_CHx_CTL1_EDGE | + CS42L84_ASP_RX_CHx_CTL1_SLOT_START_LSB, + CS42L84_ASP_RX_CHx_CTL1_EDGE); + snd_soc_component_update_bits(component, CS42L84_ASP_RX_CH2_CTL2, + CS42L84_ASP_RX_CHx_CTL2_SLOT_START_MSB, 0); + snd_soc_component_update_bits(component, CS42L84_ASP_TX_CH1_CTL1, + CS42L84_ASP_RX_CHx_CTL1_EDGE | \ + CS42L84_ASP_RX_CHx_CTL1_SLOT_START_LSB, 0); + snd_soc_component_update_bits(component, CS42L84_ASP_TX_CH1_CTL2, + CS42L84_ASP_RX_CHx_CTL2_SLOT_START_MSB, 0); + snd_soc_component_update_bits(component, CS42L84_ASP_TX_CH2_CTL1, + CS42L84_ASP_RX_CHx_CTL1_EDGE | \ + CS42L84_ASP_RX_CHx_CTL1_SLOT_START_LSB, + CS42L84_ASP_RX_CHx_CTL1_EDGE); + snd_soc_component_update_bits(component, CS42L84_ASP_TX_CH2_CTL2, + CS42L84_ASP_RX_CHx_CTL2_SLOT_START_MSB, 0); + /* Routing defaults */ + snd_soc_component_write(component, CS42L84_BUS_DAC_SRC, + 0b1101 << CS42L84_BUS_DAC_SRC_DACA_SHIFT | + 0b1110 << CS42L84_BUS_DAC_SRC_DACB_SHIFT); + snd_soc_component_write(component, CS42L84_BUS_ASP_TX_SRC, + 0b0111 << CS42L84_BUS_ASP_TX_SRC_CH1_SHIFT); + + return 0; +} + +static const struct snd_soc_component_driver soc_component_dev_cs42l84 = { + .set_jack = cs42l84_set_jack, + .probe = cs42l84_component_probe, + .controls = cs42l84_snd_controls, + .num_controls = ARRAY_SIZE(cs42l84_snd_controls), + .dapm_widgets = cs42l84_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42l84_dapm_widgets), + .dapm_routes = cs42l84_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs42l84_audio_map), + .endianness = 1, +}; + +struct cs42l84_pll_params { + u32 bclk; + u8 mclk_src_sel; + u8 bclk_prediv; + u8 pll_div_int; + u32 pll_div_frac; + u8 pll_mode; + u8 pll_divout; + u32 mclk_int; +}; + +/* + * Common PLL Settings for given BCLK + */ +static const struct cs42l84_pll_params pll_ratio_table[] = { + { 3072000, 1, 0, 0x40, 0x000000, 0x03, 0x10, 12288000}, + { 6144000, 1, 1, 0x40, 0x000000, 0x03, 0x10, 12288000}, + { 12288000, 0, 0, 0, 0, 0, 0, 12288000}, + { 24576000, 1, 3, 0x40, 0x000000, 0x03, 0x10, 12288000}, +}; + +static int cs42l84_pll_config(struct snd_soc_component *component) +{ + struct cs42l84_private *cs42l84 = snd_soc_component_get_drvdata(component); + int i; + u32 clk; + u32 fsync; + + clk = cs42l84->bclk; + + /* Don't reconfigure if there is an audio stream running */ + if (cs42l84->stream_use) { + if (pll_ratio_table[cs42l84->pll_config].bclk == clk) + return 0; + else + return -EBUSY; + } + + for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) { + if (pll_ratio_table[i].bclk == clk) { + cs42l84->pll_config = i; + break; + } + } + + if (i == ARRAY_SIZE(pll_ratio_table)) + return -EINVAL; + + /* Set up the LRCLK */ + fsync = clk / cs42l84->srate; + if (((fsync * cs42l84->srate) != clk) + || ((fsync % 2) != 0)) { + dev_err(component->dev, + "Unsupported bclk %d/sample rate %d\n", + clk, cs42l84->srate); + return -EINVAL; + } + + /* Set the LRCLK period */ + snd_soc_component_update_bits(component, CS42L84_ASP_FSYNC_CTL2, + CS42L84_ASP_FSYNC_CTL2_BCLK_PERIOD_LO, + FIELD_PREP(CS42L84_ASP_FSYNC_CTL2_BCLK_PERIOD_LO, fsync & 0x7f)); + snd_soc_component_update_bits(component, CS42L84_ASP_FSYNC_CTL3, + CS42L84_ASP_FSYNC_CTL3_BCLK_PERIOD_HI, + FIELD_PREP(CS42L84_ASP_FSYNC_CTL3_BCLK_PERIOD_HI, fsync >> 7)); + + /* Save what the MCLK will be */ + switch (pll_ratio_table[i].mclk_int) { + case 12000000: + cs42l84->pll_mclk_f = CS42L84_CCM_CTL1_MCLK_F_12MHZ; + break; + case 12288000: + cs42l84->pll_mclk_f = CS42L84_CCM_CTL1_MCLK_F_12_288KHZ; + break; + case 24000000: + cs42l84->pll_mclk_f = CS42L84_CCM_CTL1_MCLK_F_24MHZ; + break; + case 24576000: + cs42l84->pll_mclk_f = CS42L84_CCM_CTL1_MCLK_F_24_576KHZ; + break; + } + + snd_soc_component_update_bits(component, CS42L84_PLL_CTL1, CS42L84_PLL_CTL1_EN, 0); + + if (pll_ratio_table[i].mclk_src_sel) { + /* Configure PLL */ + snd_soc_component_update_bits(component, + CS42L84_CCM_CTL3, CS42L84_CCM_CTL3_REFCLK_DIV, + FIELD_PREP(CS42L84_CCM_CTL3_REFCLK_DIV, pll_ratio_table[i].bclk_prediv)); + snd_soc_component_write(component, + CS42L84_PLL_DIV_INT, + pll_ratio_table[i].pll_div_int); + snd_soc_component_write(component, + CS42L84_PLL_DIV_FRAC0, + pll_ratio_table[i].pll_div_frac); + snd_soc_component_write(component, + CS42L84_PLL_DIV_FRAC1, + pll_ratio_table[i].pll_div_frac >> 8); + snd_soc_component_write(component, + CS42L84_PLL_DIV_FRAC2, + pll_ratio_table[i].pll_div_frac >> 16); + snd_soc_component_update_bits(component, + CS42L84_PLL_CTL1, CS42L84_PLL_CTL1_MODE, + FIELD_PREP(CS42L84_PLL_CTL1_MODE, pll_ratio_table[i].pll_mode)); + snd_soc_component_write(component, + CS42L84_PLL_DIVOUT, + pll_ratio_table[i].pll_divout); + } + + return 0; +} + +static int cs42l84_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + default: + return -EINVAL; + } + + /* Bitclock/frame inversion */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_IB_IF: + break; + default: + return -EINVAL; + } + + return 0; +} + +static int cs42l84_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct cs42l84_private *cs42l84 = snd_soc_component_get_drvdata(component); + int ret; + u32 ccm_samp_rate; + + cs42l84->srate = params_rate(params); + + ret = cs42l84_pll_config(component); + if (ret) + return ret; + + switch (params_rate(params)) { + case 44100: + ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_44K1HZ; + break; + case 48000: + ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_48KHZ; + break; + case 88200: + ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_88K2HZ; + break; + case 96000: + ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_96KHZ; + break; + case 176400: + ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_176K4HZ; + break; + case 192000: + ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_192KHZ; + break; + default: + return -EINVAL; + } + + snd_soc_component_write(component, CS42L84_CCM_SAMP_RATE, ccm_samp_rate); + + switch (substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + snd_soc_component_write(component, CS42L84_ASP_RX_CH1_WIDTH, + params_width(params) - 1); + snd_soc_component_write(component, CS42L84_ASP_RX_CH2_WIDTH, + params_width(params) - 1); + break; + + case SNDRV_PCM_STREAM_CAPTURE: + snd_soc_component_write(component, CS42L84_ASP_TX_CH1_WIDTH, + params_width(params) - 1); + snd_soc_component_write(component, CS42L84_ASP_TX_CH2_WIDTH, + params_width(params) - 1); + break; + } + + return 0; +} + +static int cs42l84_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_component *component = dai->component; + struct cs42l84_private *cs42l84 = snd_soc_component_get_drvdata(component); + int i; + + if (freq == 0) { + cs42l84->bclk = 0; + return 0; + } + + for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) { + if (pll_ratio_table[i].bclk == freq) { + cs42l84->bclk = freq; + return 0; + } + } + + dev_err(component->dev, "BCLK %u not supported\n", freq); + + return -EINVAL; +} + +static int cs42l84_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ + struct snd_soc_component *component = dai->component; + struct cs42l84_private *cs42l84 = snd_soc_component_get_drvdata(component); + unsigned int regval; + int ret; + + if (mute) { + /* Mute the headphone */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_component_update_bits(component, CS42L84_DAC_CTL1, + CS42L84_DAC_CTL1_UNMUTE, 0); + cs42l84->stream_use &= ~(1 << stream); + if (!cs42l84->stream_use) { + /* Must disconnect PLL before stopping it */ + snd_soc_component_write(component, CS42L84_CCM_CTL1, + CS42L84_CCM_CTL1_RCO); + + usleep_range(150, 300); + + snd_soc_component_update_bits(component, CS42L84_PLL_CTL1, + CS42L84_PLL_CTL1_EN, 0); + + snd_soc_component_update_bits(component, CS42L84_CCM_CTL4, + CS42L84_CCM_CTL4_REFCLK_EN, 0); + } + } else { + if (!cs42l84->stream_use) { + /* SCLK must be running before codec unmute. + * + * Note carried over from CS42L42: + * + * PLL must not be started with ADC and HP both off + * otherwise the FILT+ supply will not charge properly. + * DAPM widgets power-up before stream unmute so at least + * one of the "DAC" or "ADC" widgets will already have + * powered-up. + */ + + snd_soc_component_update_bits(component, CS42L84_CCM_CTL4, + CS42L84_CCM_CTL4_REFCLK_EN, + CS42L84_CCM_CTL4_REFCLK_EN); + + if (pll_ratio_table[cs42l84->pll_config].mclk_src_sel) { + snd_soc_component_update_bits(component, CS42L84_PLL_CTL1, + CS42L84_PLL_CTL1_EN, + CS42L84_PLL_CTL1_EN); + /* TODO: should we be doing something with divout here? */ + + ret = regmap_read_poll_timeout(cs42l84->regmap, + CS42L84_PLL_LOCK_STATUS, + regval, + (regval & CS42L84_PLL_LOCK_STATUS_LOCKED), + CS42L84_PLL_LOCK_POLL_US, + CS42L84_PLL_LOCK_TIMEOUT_US); + if (ret < 0) + dev_warn(component->dev, "PLL failed to lock: %d\n", ret); + + if (regval & CS42L84_PLL_LOCK_STATUS_ERROR) + dev_warn(component->dev, "PLL lock error\n"); + + /* PLL must be running to drive glitchless switch logic */ + snd_soc_component_update_bits(component, + CS42L84_CCM_CTL1, + CS42L84_CCM_CTL1_MCLK_SRC | CS42L84_CCM_CTL1_MCLK_FREQ, + FIELD_PREP(CS42L84_CCM_CTL1_MCLK_SRC, CS42L84_CCM_CTL1_MCLK_SRC_PLL) + | FIELD_PREP(CS42L84_CCM_CTL1_MCLK_FREQ, cs42l84->pll_mclk_f)); + usleep_range(CS42L84_CLOCK_SWITCH_DELAY_US, CS42L84_CLOCK_SWITCH_DELAY_US*2); + } else { + snd_soc_component_update_bits(component, + CS42L84_CCM_CTL1, + CS42L84_CCM_CTL1_MCLK_SRC | CS42L84_CCM_CTL1_MCLK_FREQ, + FIELD_PREP(CS42L84_CCM_CTL1_MCLK_SRC, CS42L84_CCM_CTL1_MCLK_SRC_BCLK) + | FIELD_PREP(CS42L84_CCM_CTL1_MCLK_FREQ, cs42l84->pll_mclk_f)); + usleep_range(CS42L84_CLOCK_SWITCH_DELAY_US, CS42L84_CLOCK_SWITCH_DELAY_US*2); + } + } + cs42l84->stream_use |= 1 << stream; + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + /* Un-mute the headphone */ + snd_soc_component_update_bits(component, CS42L84_DAC_CTL1, + CS42L84_DAC_CTL1_UNMUTE, + CS42L84_DAC_CTL1_UNMUTE); + } + + return 0; +} + +static const struct snd_soc_dai_ops cs42l84_ops = { + .hw_params = cs42l84_pcm_hw_params, + .set_fmt = cs42l84_set_dai_fmt, + .set_sysclk = cs42l84_set_sysclk, + .mute_stream = cs42l84_mute_stream, +}; + +#define CS42L84_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver cs42l84_dai = { + .name = "cs42l84", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000, + .formats = CS42L84_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000, + .formats = CS42L84_FORMATS, + }, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, + .ops = &cs42l84_ops, +}; + +struct cs42l84_irq_params { + u16 status_addr; + u16 mask_addr; + u8 mask; +}; + +static const struct cs42l84_irq_params irq_params_table[] = { + {CS42L84_TSRS_PLUG_INT_STATUS, CS42L84_TSRS_PLUG_INT_MASK, + CS42L84_TSRS_PLUG_VAL_MASK} +}; + +static void cs42l84_detect_hs(struct cs42l84_private *cs42l84) +{ + unsigned int reg; + + /* Power up HSBIAS */ + regmap_update_bits(cs42l84->regmap, + CS42L84_MISC_DET_CTL, + CS42L84_MISC_DET_CTL_HSBIAS_CTL | CS42L84_MISC_DET_CTL_DETECT_MODE, + FIELD_PREP(CS42L84_MISC_DET_CTL_HSBIAS_CTL, 3) | /* 2.7 V */ + FIELD_PREP(CS42L84_MISC_DET_CTL_DETECT_MODE, 0)); + + /* Power up level detection circuitry */ + regmap_update_bits(cs42l84->regmap, + CS42L84_MISC_DET_CTL, + CS42L84_MISC_DET_CTL_PDN_MIC_LVL_DET, 0); + + /* TODO: Optimize */ + msleep(50); + + /* Connect HSBIAS in CTIA wiring */ + /* TODO: Should likely be subject of detection */ + regmap_write(cs42l84->regmap, + CS42L84_HS_SWITCH_CTL, + CS42L84_HS_SWITCH_CTL_REF_HS3 | \ + CS42L84_HS_SWITCH_CTL_HSB_FILT_HS3 | \ + CS42L84_HS_SWITCH_CTL_GNDHS_HS3 | \ + CS42L84_HS_SWITCH_CTL_HSB_HS4); + regmap_update_bits(cs42l84->regmap, + CS42L84_HS_DET_CTL2, + CS42L84_HS_DET_CTL2_SET, + FIELD_PREP(CS42L84_HS_DET_CTL2_SET, 0)); + + regmap_update_bits(cs42l84->regmap, + CS42L84_MISC_DET_CTL, + CS42L84_MISC_DET_CTL_DETECT_MODE, + FIELD_PREP(CS42L84_MISC_DET_CTL_DETECT_MODE, 3)); + + /* TODO: Optimize */ + msleep(50); + + regmap_read(cs42l84->regmap, CS42L84_HS_DET_STATUS2, ®); + regmap_update_bits(cs42l84->regmap, + CS42L84_MISC_DET_CTL, + CS42L84_MISC_DET_CTL_PDN_MIC_LVL_DET, + CS42L84_MISC_DET_CTL_PDN_MIC_LVL_DET); + + switch (reg & 0b11) { + case 0b11: /* shorted */ + case 0b00: /* open */ + /* Power down HSBIAS */ + regmap_update_bits(cs42l84->regmap, + CS42L84_MISC_DET_CTL, + CS42L84_MISC_DET_CTL_HSBIAS_CTL, + FIELD_PREP(CS42L84_MISC_DET_CTL_HSBIAS_CTL, 1)); /* 0.0 V */ + break; + } + + switch (reg & 0b11) { + case 0b10: /* load */ + dev_dbg(cs42l84->dev, "Detected mic\n"); + cs42l84->hs_type = SND_JACK_HEADSET; + snd_soc_jack_report(cs42l84->jack, SND_JACK_HEADSET, + SND_JACK_HEADSET); + break; + + case 0b00: /* open */ + dev_dbg(cs42l84->dev, "Detected open circuit on HS4\n"); + fallthrough; + case 0b11: /* shorted */ + default: + snd_soc_jack_report(cs42l84->jack, SND_JACK_HEADPHONE, + SND_JACK_HEADSET); + cs42l84->hs_type = SND_JACK_HEADPHONE; + dev_dbg(cs42l84->dev, "Detected bare headphone (no mic)\n"); + break; + } +} + +static void cs42l84_revert_hs(struct cs42l84_private *cs42l84) +{ + /* Power down HSBIAS */ + regmap_update_bits(cs42l84->regmap, + CS42L84_MISC_DET_CTL, + CS42L84_MISC_DET_CTL_HSBIAS_CTL | CS42L84_MISC_DET_CTL_DETECT_MODE, + FIELD_PREP(CS42L84_MISC_DET_CTL_HSBIAS_CTL, 1) | /* 0.0 V */ + FIELD_PREP(CS42L84_MISC_DET_CTL_DETECT_MODE, 0)); + + /* Disconnect HSBIAS */ + regmap_write(cs42l84->regmap, + CS42L84_HS_SWITCH_CTL, + CS42L84_HS_SWITCH_CTL_REF_HS3 | \ + CS42L84_HS_SWITCH_CTL_REF_HS4 | \ + CS42L84_HS_SWITCH_CTL_HSB_FILT_HS3 | \ + CS42L84_HS_SWITCH_CTL_HSB_FILT_HS4 | \ + CS42L84_HS_SWITCH_CTL_GNDHS_HS3 | \ + CS42L84_HS_SWITCH_CTL_GNDHS_HS4); + regmap_update_bits(cs42l84->regmap, + CS42L84_HS_DET_CTL2, + CS42L84_HS_DET_CTL2_SET, + FIELD_PREP(CS42L84_HS_DET_CTL2_SET, 2)); +} + +static irqreturn_t cs42l84_irq_thread(int irq, void *data) +{ + struct cs42l84_private *cs42l84 = (struct cs42l84_private *)data; + unsigned int stickies[1]; + unsigned int masks[1]; + unsigned int reg; + u8 current_plug_status; + int i; + + mutex_lock(&cs42l84->irq_lock); + /* Read sticky registers to clear interrupt */ + for (i = 0; i < ARRAY_SIZE(stickies); i++) { + regmap_read(cs42l84->regmap, irq_params_table[i].status_addr, + &(stickies[i])); + regmap_read(cs42l84->regmap, irq_params_table[i].mask_addr, + &(masks[i])); + stickies[i] = stickies[i] & (~masks[i]) & + irq_params_table[i].mask; + } + + if ((~masks[0]) & irq_params_table[0].mask) { + regmap_read(cs42l84->regmap, CS42L84_TSRS_PLUG_STATUS, ®); + current_plug_status = (((char) reg) & + (CS42L84_TS_PLUG | CS42L84_TS_UNPLUG)) >> + CS42L84_TS_PLUG_SHIFT; + + switch (current_plug_status) { + case CS42L84_PLUG: + if (cs42l84->plug_state != CS42L84_PLUG) { + cs42l84->plug_state = CS42L84_PLUG; + dev_dbg(cs42l84->dev, "Plug event\n"); + + cs42l84_detect_hs(cs42l84); + + /* + * Check the tip sense status again, and possibly invalidate + * the detection result + * + * Thanks to debounce, this should reliably indicate if the tip + * was disconnected at any point during the detection procedure. + */ + regmap_read(cs42l84->regmap, CS42L84_TSRS_PLUG_STATUS, ®); + current_plug_status = (((char) reg) & + (CS42L84_TS_PLUG | CS42L84_TS_UNPLUG)) >> + CS42L84_TS_PLUG_SHIFT; + if (current_plug_status != CS42L84_PLUG) { + dev_dbg(cs42l84->dev, "Wobbly connection, detection invalidated\n"); + cs42l84->plug_state = CS42L84_UNPLUG; + cs42l84_revert_hs(cs42l84); + } + } + break; + + case CS42L84_UNPLUG: + if (cs42l84->plug_state != CS42L84_UNPLUG) { + cs42l84->plug_state = CS42L84_UNPLUG; + dev_dbg(cs42l84->dev, "Unplug event\n"); + + cs42l84_revert_hs(cs42l84); + cs42l84->hs_type = 0; + snd_soc_jack_report(cs42l84->jack, 0, + SND_JACK_HEADSET); + } + break; + + default: + if (cs42l84->plug_state != CS42L84_TRANS) + cs42l84->plug_state = CS42L84_TRANS; + } + } + mutex_unlock(&cs42l84->irq_lock); + + return IRQ_HANDLED; +} + +static void cs42l84_set_interrupt_masks(struct cs42l84_private *cs42l84) +{ + regmap_update_bits(cs42l84->regmap, CS42L84_TSRS_PLUG_INT_MASK, + CS42L84_RS_PLUG | CS42L84_RS_UNPLUG | + CS42L84_TS_PLUG | CS42L84_TS_UNPLUG, + CS42L84_RS_PLUG | CS42L84_RS_UNPLUG); +} + +static void cs42l84_setup_plug_detect(struct cs42l84_private *cs42l84) +{ + unsigned int reg; + + /* Set up plug detection */ + regmap_update_bits(cs42l84->regmap, CS42L84_MIC_DET_CTL4, + CS42L84_MIC_DET_CTL4_LATCH_TO_VP, + CS42L84_MIC_DET_CTL4_LATCH_TO_VP); + regmap_update_bits(cs42l84->regmap, CS42L84_TIP_SENSE_CTL2, + CS42L84_TIP_SENSE_CTL2_MODE, + FIELD_PREP(CS42L84_TIP_SENSE_CTL2_MODE, CS42L84_TIP_SENSE_CTL2_MODE_SHORT_DET)); + regmap_update_bits(cs42l84->regmap, CS42L84_RING_SENSE_CTL, + CS42L84_RING_SENSE_CTL_INV | CS42L84_RING_SENSE_CTL_UNK1 | + CS42L84_RING_SENSE_CTL_RISETIME | CS42L84_RING_SENSE_CTL_FALLTIME, + CS42L84_RING_SENSE_CTL_INV | CS42L84_RING_SENSE_CTL_UNK1 | + FIELD_PREP(CS42L84_RING_SENSE_CTL_RISETIME, CS42L84_DEBOUNCE_TIME_125MS) | + FIELD_PREP(CS42L84_RING_SENSE_CTL_FALLTIME, CS42L84_DEBOUNCE_TIME_125MS)); + regmap_update_bits(cs42l84->regmap, CS42L84_TIP_SENSE_CTL, + CS42L84_TIP_SENSE_CTL_INV | + CS42L84_TIP_SENSE_CTL_RISETIME | CS42L84_TIP_SENSE_CTL_FALLTIME, + CS42L84_TIP_SENSE_CTL_INV | + FIELD_PREP(CS42L84_TIP_SENSE_CTL_RISETIME, CS42L84_DEBOUNCE_TIME_500MS) | + FIELD_PREP(CS42L84_TIP_SENSE_CTL_FALLTIME, CS42L84_DEBOUNCE_TIME_125MS)); + regmap_update_bits(cs42l84->regmap, CS42L84_MSM_BLOCK_EN3, + CS42L84_MSM_BLOCK_EN3_TR_SENSE, + CS42L84_MSM_BLOCK_EN3_TR_SENSE); + + /* Save the initial status of the tip sense */ + regmap_read(cs42l84->regmap, CS42L84_TSRS_PLUG_STATUS, ®); + cs42l84->plug_state = (((char) reg) & + (CS42L84_TS_PLUG | CS42L84_TS_UNPLUG)) >> + CS42L84_TS_PLUG_SHIFT; + + /* Set mic-detection threshold */ + regmap_update_bits(cs42l84->regmap, + CS42L84_MIC_DET_CTL1, CS42L84_MIC_DET_CTL1_HS_DET_LEVEL, + FIELD_PREP(CS42L84_MIC_DET_CTL1_HS_DET_LEVEL, 0x2c)); /* ~1.9 V */ + + /* Disconnect HSBIAS (initially) */ + regmap_write(cs42l84->regmap, + CS42L84_HS_SWITCH_CTL, + CS42L84_HS_SWITCH_CTL_REF_HS3 | \ + CS42L84_HS_SWITCH_CTL_REF_HS4 | \ + CS42L84_HS_SWITCH_CTL_HSB_FILT_HS3 | \ + CS42L84_HS_SWITCH_CTL_HSB_FILT_HS4 | \ + CS42L84_HS_SWITCH_CTL_GNDHS_HS3 | \ + CS42L84_HS_SWITCH_CTL_GNDHS_HS4); + regmap_update_bits(cs42l84->regmap, + CS42L84_HS_DET_CTL2, + CS42L84_HS_DET_CTL2_SET | CS42L84_HS_DET_CTL2_CTL, + FIELD_PREP(CS42L84_HS_DET_CTL2_SET, 2) | + FIELD_PREP(CS42L84_HS_DET_CTL2_CTL, 0)); + regmap_update_bits(cs42l84->regmap, + CS42L84_HS_CLAMP_DISABLE, 1, 1); + +} + +static int cs42l84_i2c_probe(struct i2c_client *i2c_client) +{ + struct cs42l84_private *cs42l84; + int ret, devid; + unsigned int reg; + + cs42l84 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l84_private), + GFP_KERNEL); + if (!cs42l84) + return -ENOMEM; + + cs42l84->dev = &i2c_client->dev; + i2c_set_clientdata(i2c_client, cs42l84); + mutex_init(&cs42l84->irq_lock); + + cs42l84->regmap = devm_regmap_init_i2c(i2c_client, &cs42l84_regmap); + if (IS_ERR(cs42l84->regmap)) { + ret = PTR_ERR(cs42l84->regmap); + dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); + return ret; + } + + /* Reset the Device */ + cs42l84->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, + "reset", GPIOD_OUT_LOW); + if (IS_ERR(cs42l84->reset_gpio)) { + ret = PTR_ERR(cs42l84->reset_gpio); + goto err_disable_noreset; + } + + if (cs42l84->reset_gpio) { + dev_dbg(&i2c_client->dev, "Found reset GPIO\n"); + gpiod_set_value_cansleep(cs42l84->reset_gpio, 1); + } + usleep_range(CS42L84_BOOT_TIME_US, CS42L84_BOOT_TIME_US * 2); + + /* Request IRQ if one was specified */ + if (i2c_client->irq) { + ret = request_threaded_irq(i2c_client->irq, + NULL, cs42l84_irq_thread, + IRQF_ONESHOT, + "cs42l84", cs42l84); + if (ret == -EPROBE_DEFER) { + goto err_disable_noirq; + } else if (ret != 0) { + dev_err(&i2c_client->dev, + "Failed to request IRQ: %d\n", ret); + goto err_disable_noirq; + } + } + + /* initialize codec */ + devid = cirrus_read_device_id(cs42l84->regmap, CS42L84_DEVID); + if (devid < 0) { + ret = devid; + dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret); + goto err_disable; + } + + if (devid != CS42L84_CHIP_ID) { + dev_err(&i2c_client->dev, + "CS42L84 Device ID (%X). Expected %X\n", + devid, CS42L84_CHIP_ID); + ret = -EINVAL; + goto err_disable; + } + + ret = regmap_read(cs42l84->regmap, CS42L84_REVID, ®); + if (ret < 0) { + dev_err(&i2c_client->dev, "Get Revision ID failed\n"); + goto err_shutdown; + } + + dev_info(&i2c_client->dev, + "Cirrus Logic CS42L84, Revision: %02X\n", reg & 0xFF); + + /* Setup plug detection */ + cs42l84_setup_plug_detect(cs42l84); + + /* Mask/Unmask Interrupts */ + cs42l84_set_interrupt_masks(cs42l84); + + /* Register codec for machine driver */ + ret = devm_snd_soc_register_component(&i2c_client->dev, + &soc_component_dev_cs42l84, &cs42l84_dai, 1); + if (ret < 0) + goto err_shutdown; + + return 0; + +err_shutdown: + /* Nothing to do */ + +err_disable: + if (i2c_client->irq) + free_irq(i2c_client->irq, cs42l84); + +err_disable_noirq: + gpiod_set_value_cansleep(cs42l84->reset_gpio, 0); +err_disable_noreset: + return ret; +} + +static void cs42l84_i2c_remove(struct i2c_client *i2c_client) +{ + struct cs42l84_private *cs42l84 = i2c_get_clientdata(i2c_client); + + if (i2c_client->irq) + free_irq(i2c_client->irq, cs42l84); + + gpiod_set_value_cansleep(cs42l84->reset_gpio, 0); +} + +static const struct of_device_id cs42l84_of_match[] = { + { .compatible = "cirrus,cs42l84", }, + {} +}; +MODULE_DEVICE_TABLE(of, cs42l84_of_match); + +static const struct i2c_device_id cs42l84_id[] = { + {"cs42l84", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs42l84_id); + +static struct i2c_driver cs42l84_i2c_driver = { + .driver = { + .name = "cs42l84", + .of_match_table = of_match_ptr(cs42l84_of_match), + }, + .id_table = cs42l84_id, + .probe = cs42l84_i2c_probe, + .remove = cs42l84_i2c_remove, +}; + +module_i2c_driver(cs42l84_i2c_driver); + +MODULE_DESCRIPTION("ASoC CS42L84 driver"); +MODULE_AUTHOR("Martin PoviÅ¡er "); +MODULE_AUTHOR("Hector Martin "); +MODULE_AUTHOR("James Calligeros "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42l84.h b/sound/soc/codecs/cs42l84.h new file mode 100644 index 000000000000..dbf778a902b9 --- /dev/null +++ b/sound/soc/codecs/cs42l84.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) The Asahi Linux Contributors + * + * Based on sound/soc/codecs/cs42l42.h + * + * Copyright 2016 Cirrus Logic, Inc. + */ + + +#ifndef __CS42L84_H__ +#define __CS42L84_H__ + +#include + +#define CS42L84_CHIP_ID 0x42a84 + +#define CS42L84_DEVID 0x0000 +#define CS42L84_REVID 0x73fe +#define CS42L84_FRZ_CTL 0x0006 +#define CS42L84_FRZ_CTL_ENGAGE BIT(0) + +#define CS42L84_TSRS_PLUG_INT_STATUS 0x0400 +#define CS42L84_TSRS_PLUG_INT_MASK 0x0418 +#define CS42L84_RS_PLUG_SHIFT 0 +#define CS42L84_RS_PLUG BIT(0) +#define CS42L84_RS_UNPLUG BIT(1) +#define CS42L84_TS_PLUG_SHIFT 2 +#define CS42L84_TS_PLUG BIT(2) +#define CS42L84_TS_UNPLUG BIT(3) +#define CS42L84_TSRS_PLUG_VAL_MASK GENMASK(3, 0) +#define CS42L84_PLL_LOCK_STATUS 0x040e // probably bit 0x10 +#define CS42L84_PLL_LOCK_STATUS_LOCKED BIT(4) +#define CS42L84_PLL_LOCK_STATUS_ERROR BIT(5) + +#define CS42L84_PLUG 3 +#define CS42L84_UNPLUG 0 +#define CS42L84_TRANS 1 + +#define CS42L84_CCM_CTL1 0x0600 +#define CS42L84_CCM_CTL1_MCLK_SRC GENMASK(1, 0) +#define CS42L84_CCM_CTL1_MCLK_SRC_RCO 0 +#define CS42L84_CCM_CTL1_MCLK_SRC_MCLK 1 +#define CS42L84_CCM_CTL1_MCLK_SRC_BCLK 2 +#define CS42L84_CCM_CTL1_MCLK_SRC_PLL 3 +#define CS42L84_CCM_CTL1_MCLK_FREQ GENMASK(3, 2) +#define CS42L84_CCM_CTL1_MCLK_F_12MHZ 0b00 +#define CS42L84_CCM_CTL1_MCLK_F_24MHZ 0b01 +#define CS42L84_CCM_CTL1_MCLK_F_12_288KHZ 0b10 +#define CS42L84_CCM_CTL1_MCLK_F_24_576KHZ 0b11 +#define CS42L84_CCM_CTL1_RCO \ + (FIELD_PREP(CS42L84_CCM_CTL1_MCLK_SRC, CS42L84_CCM_CTL1_MCLK_SRC_RCO) \ + | FIELD_PREP(CS42L84_CCM_CTL1_MCLK_FREQ, CS42L84_CCM_CTL1_MCLK_F_12MHZ)) + +#define CS42L84_CCM_SAMP_RATE 0x0601 +#define CS42L84_CCM_SAMP_RATE_RATE_48KHZ 4 +#define CS42L84_CCM_SAMP_RATE_RATE_96KHZ 5 +#define CS42L84_CCM_SAMP_RATE_RATE_192KHZ 6 +#define CS42L84_CCM_SAMP_RATE_RATE_44K1HZ 12 +#define CS42L84_CCM_SAMP_RATE_RATE_88K2HZ 13 +#define CS42L84_CCM_SAMP_RATE_RATE_176K4HZ 14 +#define CS42L84_CCM_CTL3 0x0602 +#define CS42L84_CCM_CTL3_REFCLK_DIV GENMASK(2, 1) +#define CS42L84_CCM_CTL4 0x0603 +#define CS42L84_CCM_CTL4_REFCLK_EN BIT(0) + +#define CS42L84_CCM_ASP_CLK_CTRL 0x0608 + +#define CS42L84_PLL_CTL1 0x0800 +#define CS42L84_PLL_CTL1_EN BIT(0) +#define CS42L84_PLL_CTL1_MODE GENMASK(2, 1) +#define CS42L84_PLL_DIV_FRAC0 0x0804 +#define CS42L84_PLL_DIV_FRAC1 0x0805 +#define CS42L84_PLL_DIV_FRAC2 0x0806 +#define CS42L84_PLL_DIV_INT 0x0807 +#define CS42L84_PLL_DIVOUT 0x0808 + +#define CS42L84_RING_SENSE_CTL 0x1282 +#define CS42L84_RING_SENSE_CTL_INV BIT(7) +#define CS42L84_RING_SENSE_CTL_UNK1 BIT(6) +#define CS42L84_RING_SENSE_CTL_FALLTIME GENMASK(5, 3) +#define CS42L84_RING_SENSE_CTL_RISETIME GENMASK(2, 0) +#define CS42L84_TIP_SENSE_CTL 0x1283 +#define CS42L84_TIP_SENSE_CTL_INV BIT(7) +#define CS42L84_TIP_SENSE_CTL_FALLTIME GENMASK(5, 3) +#define CS42L84_TIP_SENSE_CTL_RISETIME GENMASK(2, 0) + +#define CS42L84_TSRS_PLUG_STATUS 0x1288 + +#define CS42L84_TIP_SENSE_CTL2 0x1473 +#define CS42L84_TIP_SENSE_CTL2_MODE GENMASK(7, 6) +#define CS42L84_TIP_SENSE_CTL2_MODE_DISABLED 0b00 +#define CS42L84_TIP_SENSE_CTL2_MODE_DIG_INPUT 0b01 +#define CS42L84_TIP_SENSE_CTL2_MODE_SHORT_DET 0b11 +#define CS42L84_TIP_SENSE_CTL2_INV BIT(5) + +#define CS42L84_MISC_DET_CTL 0x1474 +#define CS42L84_MISC_DET_CTL_DETECT_MODE GENMASK(4, 3) +#define CS42L84_MISC_DET_CTL_HSBIAS_CTL GENMASK(2, 1) +#define CS42L84_MISC_DET_CTL_PDN_MIC_LVL_DET BIT(0) + +#define CS42L84_MIC_DET_CTL1 0x1475 +#define CS42L84_MIC_DET_CTL1_HS_DET_LEVEL GENMASK(5, 0) + +#define CS42L84_MIC_DET_CTL4 0x1477 +#define CS42L84_MIC_DET_CTL4_LATCH_TO_VP BIT(1) + +#define CS42L84_HS_DET_STATUS2 0x147d + +#define CS42L84_MSM_BLOCK_EN1 0x1800 +#define CS42L84_MSM_BLOCK_EN2 0x1801 +#define CS42L84_MSM_BLOCK_EN2_ASP_SHIFT 6 +#define CS42L84_MSM_BLOCK_EN2_BUS_SHIFT 5 +#define CS42L84_MSM_BLOCK_EN2_DAC_SHIFT 4 +#define CS42L84_MSM_BLOCK_EN2_ADC_SHIFT 3 +#define CS42L84_MSM_BLOCK_EN3 0x1802 +#define CS42L84_MSM_BLOCK_EN3_TR_SENSE BIT(3) + +#define CS42L84_HS_DET_CTL2 0x1811 +#define CS42L84_HS_DET_CTL2_CTL GENMASK(7, 6) +#define CS42L84_HS_DET_CTL2_SET GENMASK(5, 4) +#define CS42L84_HS_DET_CTL2_REF BIT(3) +#define CS42L84_HS_DET_CTL2_AUTO_TIME GENMASK(1, 0) + +#define CS42L84_HS_SWITCH_CTL 0x1812 +#define CS42L84_HS_SWITCH_CTL_REF_HS3 BIT(7) +#define CS42L84_HS_SWITCH_CTL_REF_HS4 BIT(6) +#define CS42L84_HS_SWITCH_CTL_HSB_FILT_HS3 BIT(5) +#define CS42L84_HS_SWITCH_CTL_HSB_FILT_HS4 BIT(4) +#define CS42L84_HS_SWITCH_CTL_HSB_HS3 BIT(3) +#define CS42L84_HS_SWITCH_CTL_HSB_HS4 BIT(2) +#define CS42L84_HS_SWITCH_CTL_GNDHS_HS3 BIT(1) +#define CS42L84_HS_SWITCH_CTL_GNDHS_HS4 BIT(0) + +#define CS42L84_HS_CLAMP_DISABLE 0x1813 + +#define CS42L84_ADC_CTL1 0x2000 +#define CS42L84_ADC_CTL1_PREAMP_GAIN_SHIFT 6 +#define CS42L84_ADC_CTL1_PGA_GAIN_SHIFT 0 +#define CS42L84_ADC_CTL4 0x2003 +#define CS42L84_ADC_CTL4_WNF_CF_SHIFT 4 +#define CS42L84_ADC_CTL4_WNF_EN_SHIFT 3 +#define CS42L84_ADC_CTL4_HPF_CF_SHIFT 1 +#define CS42L84_ADC_CTL4_HPF_EN_SHIFT 0 + +#define CS42L84_DAC_CTL1 0x3000 +#define CS42L84_DAC_CTL1_UNMUTE BIT(0) +//#define CS42L84_DAC_CTL1_DACB_INV_SHIFT 1 +//#define CS42L84_DAC_CTL1_DACA_INV_SHIFT 0 +#define CS42L84_DAC_CTL2 0x3001 + +#define CS42L84_DAC_CHA_VOL_LSB 0x3004 +#define CS42L84_DAC_CHA_VOL_MSB 0x3005 +#define CS42L84_DAC_CHB_VOL_LSB 0x3006 +#define CS42L84_DAC_CHB_VOL_MSB 0x3007 +#define CS42L84_HP_VOL_CTL 0x3020 +#define CS42L84_HP_VOL_CTL_ZERO_CROSS BIT(1) +#define CS42L84_HP_VOL_CTL_SOFT BIT(0) + +#define CS42L84_SRC_ASP_RX_CH1 0b1101 +#define CS42L84_SRC_ASP_RX_CH2 0b1110 + +#define CS42L84_BUS_ASP_TX_SRC 0x4000 +#define CS42L84_BUS_ASP_TX_SRC_CH1_SHIFT 0 +#define CS42L84_BUS_DAC_SRC 0x4001 +#define CS42L84_BUS_DAC_SRC_DACA_SHIFT 0 +#define CS42L84_BUS_DAC_SRC_DACB_SHIFT 4 + +#define CS42L84_ASP_CTL 0x5000 +#define CS42L84_ASP_CTL_BCLK_EN_SHIFT 1 +#define CS42L84_ASP_CTL_TDM_MODE BIT(2) +#define CS42L84_ASP_FSYNC_CTL2 0x5010 +#define CS42L84_ASP_FSYNC_CTL2_BCLK_PERIOD_LO GENMASK(7, 1) +#define CS42L84_ASP_FSYNC_CTL3 0x5011 +#define CS42L84_ASP_FSYNC_CTL3_BCLK_PERIOD_HI GENMASK(4, 0) +#define CS42L84_ASP_DATA_CTL 0x5018 + +#define CS42L84_ASP_RX_EN 0x5020 +#define CS42L84_ASP_RX_EN_CH1_SHIFT 0 +#define CS42L84_ASP_RX_EN_CH2_SHIFT 1 +#define CS42L84_ASP_TX_EN 0x5024 +#define CS42L84_ASP_TX_EN_CH1_SHIFT 0 + +#define CS42L84_ASP_RX_CH1_CTL1 0x5028 +#define CS42L84_ASP_RX_CH1_CTL2 0x5029 +#define CS42L84_ASP_RX_CH1_WIDTH 0x502a +#define CS42L84_ASP_RX_CH2_CTL1 0x502c +#define CS42L84_ASP_RX_CH2_CTL2 0x502d +#define CS42L84_ASP_RX_CH2_WIDTH 0x502e + +#define CS42L84_ASP_RX_CHx_CTL1_EDGE BIT(0) +#define CS42L84_ASP_RX_CHx_CTL1_SLOT_START_LSB GENMASK(7, 1) +#define CS42L84_ASP_RX_CHx_CTL2_SLOT_START_MSB GENMASK(2, 0) + +#define CS42L84_ASP_TX_CH1_CTL1 0x5068 +#define CS42L84_ASP_TX_CH1_CTL2 0x5069 +#define CS42L84_ASP_TX_CH1_WIDTH 0x506a +#define CS42L84_ASP_TX_CH2_CTL1 0x506c +#define CS42L84_ASP_TX_CH2_CTL2 0x506d +#define CS42L84_ASP_TX_CH2_WIDTH 0x506e + +#define CS42L84_DEBOUNCE_TIME_125MS 0b001 +#define CS42L84_DEBOUNCE_TIME_500MS 0b011 + +#define CS42L84_BOOT_TIME_US 3000 +#define CS42L84_CLOCK_SWITCH_DELAY_US 150 +#define CS42L84_PLL_LOCK_POLL_US 250 +#define CS42L84_PLL_LOCK_TIMEOUT_US 1250 + +#endif /* __CS42L84_H__ */ From 640741ee3f2fb9a781f07f5640d458698ed5c1c0 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:37:06 +0100 Subject: [PATCH 138/256] ASoC: cs42l84: leverage ring sense IRQs to correctly detect headsets JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 2391b8719d686b1947b5f81250281fa112da91dc Author: James Calligeros Date: Sun Oct 20 00:47:33 2024 +1000 ASoC: cs42l84: leverage ring sense IRQs to correctly detect headsets Some jacks integrated on devices with this codec, such as certain Apple Silicon Macs, have quite trigger-happy tip sense switches that cause a tip sense IRQ before the plug is fully seated. If users are unfortunate with their timing, this can lead to headsets being detected as mic-less headphones among other issues with the codec's device detection routines. Introduce some rudimentary ring sense interrupt handling so that we can re-trigger the codec's detection routines when we are certain that the plug is fully seated. This seems to differ from what other Cirrus drivers do, but is necessary for devices to be reliably detected properly here. Signed-off-by: James Calligeros Reviewed-by: Neal Gompa Link: https://patch.msgid.link/20241020-cs42l84-v2-3-37ba2b6721d9@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/cs42l84.c | 92 +++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 31 deletions(-) diff --git a/sound/soc/codecs/cs42l84.c b/sound/soc/codecs/cs42l84.c index 84a1e8ac818c..47731cdc0e67 100644 --- a/sound/soc/codecs/cs42l84.c +++ b/sound/soc/codecs/cs42l84.c @@ -44,7 +44,8 @@ struct cs42l84_private { struct gpio_desc *reset_gpio; struct snd_soc_jack *jack; struct mutex irq_lock; - u8 plug_state; + u8 tip_state; + u8 ring_state; int pll_config; int bclk; u8 pll_mclk_f; @@ -798,13 +799,23 @@ static void cs42l84_revert_hs(struct cs42l84_private *cs42l84) FIELD_PREP(CS42L84_HS_DET_CTL2_SET, 2)); } +static void cs42l84_set_interrupt_masks(struct cs42l84_private *cs42l84, + unsigned int val) +{ + regmap_update_bits(cs42l84->regmap, CS42L84_TSRS_PLUG_INT_MASK, + CS42L84_RS_PLUG | CS42L84_RS_UNPLUG | + CS42L84_TS_PLUG | CS42L84_TS_UNPLUG, + val); +} + static irqreturn_t cs42l84_irq_thread(int irq, void *data) { struct cs42l84_private *cs42l84 = (struct cs42l84_private *)data; unsigned int stickies[1]; unsigned int masks[1]; unsigned int reg; - u8 current_plug_status; + u8 current_tip_state; + u8 current_ring_state; int i; mutex_lock(&cs42l84->irq_lock); @@ -818,16 +829,24 @@ static irqreturn_t cs42l84_irq_thread(int irq, void *data) irq_params_table[i].mask; } + /* When handling plug sene IRQs, we only care about EITHER tip OR ring. + * Ring is useless on remove, and is only useful on insert for + * detecting if the plug state has changed AFTER we have handled the + * tip sense IRQ, e.g. if the plug was not fully seated within the tip + * sense debounce time. + */ + if ((~masks[0]) & irq_params_table[0].mask) { regmap_read(cs42l84->regmap, CS42L84_TSRS_PLUG_STATUS, ®); - current_plug_status = (((char) reg) & + + current_tip_state = (((char) reg) & (CS42L84_TS_PLUG | CS42L84_TS_UNPLUG)) >> CS42L84_TS_PLUG_SHIFT; - switch (current_plug_status) { - case CS42L84_PLUG: - if (cs42l84->plug_state != CS42L84_PLUG) { - cs42l84->plug_state = CS42L84_PLUG; + if (current_tip_state != cs42l84->tip_state) { + cs42l84->tip_state = current_tip_state; + switch (current_tip_state) { + case CS42L84_PLUG: dev_dbg(cs42l84->dev, "Plug event\n"); cs42l84_detect_hs(cs42l84); @@ -840,47 +859,58 @@ static irqreturn_t cs42l84_irq_thread(int irq, void *data) * was disconnected at any point during the detection procedure. */ regmap_read(cs42l84->regmap, CS42L84_TSRS_PLUG_STATUS, ®); - current_plug_status = (((char) reg) & + current_tip_state = (((char) reg) & (CS42L84_TS_PLUG | CS42L84_TS_UNPLUG)) >> CS42L84_TS_PLUG_SHIFT; - if (current_plug_status != CS42L84_PLUG) { + if (current_tip_state != CS42L84_PLUG) { dev_dbg(cs42l84->dev, "Wobbly connection, detection invalidated\n"); - cs42l84->plug_state = CS42L84_UNPLUG; + cs42l84->tip_state = CS42L84_UNPLUG; cs42l84_revert_hs(cs42l84); } - } - break; - case CS42L84_UNPLUG: - if (cs42l84->plug_state != CS42L84_UNPLUG) { - cs42l84->plug_state = CS42L84_UNPLUG; + /* Unmask ring sense interrupts */ + cs42l84_set_interrupt_masks(cs42l84, 0); + break; + case CS42L84_UNPLUG: + cs42l84->ring_state = CS42L84_UNPLUG; dev_dbg(cs42l84->dev, "Unplug event\n"); cs42l84_revert_hs(cs42l84); cs42l84->hs_type = 0; snd_soc_jack_report(cs42l84->jack, 0, SND_JACK_HEADSET); - } - break; - default: - if (cs42l84->plug_state != CS42L84_TRANS) - cs42l84->plug_state = CS42L84_TRANS; + /* Mask ring sense interrupts */ + cs42l84_set_interrupt_masks(cs42l84, + CS42L84_RS_PLUG | CS42L84_RS_UNPLUG); + break; + default: + cs42l84->ring_state = CS42L84_TRANS; + break; + } + + mutex_unlock(&cs42l84->irq_lock); + + return IRQ_HANDLED; + } + + /* Tip state didn't change, we must've got a ring sense IRQ */ + current_ring_state = (((char) reg) & + (CS42L84_RS_PLUG | CS42L84_RS_UNPLUG)) >> + CS42L84_RS_PLUG_SHIFT; + + if (current_ring_state != cs42l84->ring_state) { + cs42l84->ring_state = current_ring_state; + if (current_ring_state == CS42L84_PLUG) + cs42l84_detect_hs(cs42l84); } } + mutex_unlock(&cs42l84->irq_lock); return IRQ_HANDLED; } -static void cs42l84_set_interrupt_masks(struct cs42l84_private *cs42l84) -{ - regmap_update_bits(cs42l84->regmap, CS42L84_TSRS_PLUG_INT_MASK, - CS42L84_RS_PLUG | CS42L84_RS_UNPLUG | - CS42L84_TS_PLUG | CS42L84_TS_UNPLUG, - CS42L84_RS_PLUG | CS42L84_RS_UNPLUG); -} - static void cs42l84_setup_plug_detect(struct cs42l84_private *cs42l84) { unsigned int reg; @@ -910,7 +940,7 @@ static void cs42l84_setup_plug_detect(struct cs42l84_private *cs42l84) /* Save the initial status of the tip sense */ regmap_read(cs42l84->regmap, CS42L84_TSRS_PLUG_STATUS, ®); - cs42l84->plug_state = (((char) reg) & + cs42l84->tip_state = (((char) reg) & (CS42L84_TS_PLUG | CS42L84_TS_UNPLUG)) >> CS42L84_TS_PLUG_SHIFT; @@ -1017,8 +1047,8 @@ static int cs42l84_i2c_probe(struct i2c_client *i2c_client) /* Setup plug detection */ cs42l84_setup_plug_detect(cs42l84); - /* Mask/Unmask Interrupts */ - cs42l84_set_interrupt_masks(cs42l84); + /* Mask ring sense interrupts */ + cs42l84_set_interrupt_masks(cs42l84, CS42L84_RS_PLUG | CS42L84_RS_UNPLUG); /* Register codec for machine driver */ ret = devm_snd_soc_register_component(&i2c_client->dev, From 4f8739ec1d2486b2e084f7b6196dde2b92b378b4 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:39:00 +0100 Subject: [PATCH 139/256] ALSA: compress_offload: introduce accel operation mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 04177158cf98a79744937893b100020d77e6f9ac Author: Jaroslav Kysela Date: Wed Oct 2 11:39:04 2024 +0200 ALSA: compress_offload: introduce accel operation mode There is a requirement to expose the audio hardware that accelerates various tasks for user space such as sample rate converters, compressed stream decoders, etc. This is description for the API extension for the compress ALSA API which is able to handle "tasks" that are not bound to real-time operations and allows for the serialization of operations. For details, refer to "compress-accel.rst" document. Cc: Mark Brown Cc: Shengjiu Wang Cc: Nicolas Dufresne Cc: Amadeusz SÅ‚awiÅ„ski Cc: Pierre-Louis Bossart Cc: Vinod Koul Signed-off-by: Jaroslav Kysela Reviewed-by: Amadeusz SÅ‚awiÅ„ski Tested-by: Shengjiu Wang Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20241002093904.1809799-1-perex@perex.cz Signed-off-by: Jaroslav Kysela --- .../sound/designs/compress-accel.rst | 134 +++++++ include/sound/compress_driver.h | 46 +++ include/uapi/sound/compress_offload.h | 64 +++- sound/core/Kconfig | 3 + sound/core/compress_offload.c | 348 +++++++++++++++++- 5 files changed, 587 insertions(+), 8 deletions(-) create mode 100644 Documentation/sound/designs/compress-accel.rst diff --git a/Documentation/sound/designs/compress-accel.rst b/Documentation/sound/designs/compress-accel.rst new file mode 100644 index 000000000000..abf1f76a8778 --- /dev/null +++ b/Documentation/sound/designs/compress-accel.rst @@ -0,0 +1,134 @@ +================================== +ALSA Co-processor Acceleration API +================================== + +Jaroslav Kysela + + +Overview +======== + +There is a requirement to expose the audio hardware that accelerates various +tasks for user space such as sample rate converters, compressed +stream decoders, etc. + +This is description for the API extension for the compress ALSA API which +is able to handle "tasks" that are not bound to real-time operations +and allows for the serialization of operations. + +Requirements +============ + +The main requirements are: + +- serialization of multiple tasks for user space to allow multiple + operations without user space intervention + +- separate buffers (input + output) for each operation + +- expose buffers using mmap to user space + +- signal user space when the task is finished (standard poll mechanism) + +Design +====== + +A new direction SND_COMPRESS_ACCEL is introduced to identify +the passthrough API. + +The API extension shares device enumeration and parameters handling from +the main compressed API. All other realtime streaming ioctls are deactivated +and a new set of task related ioctls are introduced. The standard +read/write/mmap I/O operations are not supported in the passthrough device. + +Device ("stream") state handling is reduced to OPEN/SETUP. All other +states are not available for the passthrough mode. + +Data I/O mechanism is using standard dma-buf interface with all advantages +like mmap, standard I/O, buffer sharing etc. One buffer is used for the +input data and second (separate) buffer is used for the output data. Each task +have separate I/O buffers. + +For the buffering parameters, the fragments means a limit of allocated tasks +for given device. The fragment_size limits the input buffer size for the given +device. The output buffer size is determined by the driver (may be different +from the input buffer size). + +State Machine +============= + +The passthrough audio stream state machine is described below : + + +----------+ + | | + | OPEN | + | | + +----------+ + | + | + | compr_set_params() + | + v + all passthrough task ops +----------+ + +------------------------------------| | + | | SETUP | + | | + | +----------+ + | | + +------------------------------------------+ + + +Passthrough operations (ioctls) +=============================== + +All operations are protected using stream->device->lock (mutex). + +CREATE +------ +Creates a set of input/output buffers. The input buffer size is +fragment_size. Allocates unique seqno. + +The hardware drivers allocate internal 'struct dma_buf' for both input and +output buffers (using 'dma_buf_export()' function). The anonymous +file descriptors for those buffers are passed to user space. + +FREE +---- +Free a set of input/output buffers. If a task is active, the stop +operation is executed before. If seqno is zero, operation is executed for all +tasks. + +START +----- +Starts (queues) a task. There are two cases of the task start - right after +the task is created. In this case, origin_seqno must be zero. +The second case is for reusing of already finished task. The origin_seqno +must identify the task to be reused. In both cases, a new seqno value +is allocated and returned to user space. + +The prerequisite is that application filled input dma buffer with +new source data and set input_size to pass the real data size to the driver. + +The order of data processing is preserved (first started job must be +finished at first). + +If the multiple tasks require a state handling (e.g. resampling operation), +the user space may set SND_COMPRESS_TFLG_NEW_STREAM flag to mark the +start of the new stream data. It is useful to keep the allocated buffers +for the new operation rather using open/close mechanism. + +STOP +---- +Stop (dequeues) a task. If seqno is zero, operation is executed for all +tasks. + +STATUS +------ +Obtain the task status (active, finished). Also, the driver will set +the real output data size (valid area in the output buffer). + +Credits +======= +- Shengjiu Wang +- Takashi Iwai +- Vinod Koul diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index bcf872c17dd3..5db4881b0681 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -19,6 +19,30 @@ struct snd_compr_ops; +/** + * struct snd_compr_task_runtime: task runtime description + * @list: list of all managed tasks + * @input: input DMA buffer + * @output: output DMA buffer + * @seqno: sequence number + * @input_size: really used data in the input buffer + * @output_size: really used data in the output buffer + * @flags: see SND_COMPRESS_TFLG_* + * @state: actual task state + * @private_value: used by the lowlevel driver (opaque) + */ +struct snd_compr_task_runtime { + struct list_head list; + struct dma_buf *input; + struct dma_buf *output; + u64 seqno; + u64 input_size; + u64 output_size; + u32 flags; + u8 state; + void *private_value; +}; + /** * struct snd_compr_runtime: runtime stream description * @state: stream state @@ -37,6 +61,10 @@ struct snd_compr_ops; * @dma_addr: physical buffer address (not accessible from main CPU) * @dma_bytes: size of DMA area * @dma_buffer_p: runtime dma buffer pointer + * @active_tasks: count of active tasks + * @total_tasks: count of all tasks + * @task_seqno: last task sequence number (!= 0) + * @tasks: list of all tasks */ struct snd_compr_runtime { snd_pcm_state_t state; @@ -54,6 +82,13 @@ struct snd_compr_runtime { dma_addr_t dma_addr; size_t dma_bytes; struct snd_dma_buffer *dma_buffer_p; + +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) + u32 active_tasks; + u32 total_tasks; + u64 task_seqno; + struct list_head tasks; +#endif }; /** @@ -132,6 +167,12 @@ struct snd_compr_ops { struct snd_compr_caps *caps); int (*get_codec_caps) (struct snd_compr_stream *stream, struct snd_compr_codec_caps *codec); +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) + int (*task_create) (struct snd_compr_stream *stream, struct snd_compr_task_runtime *task); + int (*task_start) (struct snd_compr_stream *stream, struct snd_compr_task_runtime *task); + int (*task_stop) (struct snd_compr_stream *stream, struct snd_compr_task_runtime *task); + int (*task_free) (struct snd_compr_stream *stream, struct snd_compr_task_runtime *task); +#endif }; /** @@ -242,4 +283,9 @@ int snd_compr_free_pages(struct snd_compr_stream *stream); int snd_compr_stop_error(struct snd_compr_stream *stream, snd_pcm_state_t state); +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) +void snd_compr_task_finished(struct snd_compr_stream *stream, + struct snd_compr_task_runtime *task); +#endif + #endif diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index d185957f3fe0..98772b0cbcb7 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -14,7 +14,7 @@ #include -#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 2, 0) +#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 0) /** * struct snd_compressed_buffer - compressed buffer * @fragment_size: size of buffer fragment in bytes @@ -68,7 +68,8 @@ struct snd_compr_avail { enum snd_compr_direction { SND_COMPRESS_PLAYBACK = 0, - SND_COMPRESS_CAPTURE + SND_COMPRESS_CAPTURE, + SND_COMPRESS_ACCEL }; /** @@ -127,6 +128,57 @@ struct snd_compr_metadata { __u32 value[8]; } __attribute__((packed, aligned(4))); +/* flags for struct snd_compr_task */ +#define SND_COMPRESS_TFLG_NEW_STREAM (1<<0) /* mark for the new stream data */ + +/** + * struct snd_compr_task - task primitive for non-realtime operation + * @seqno: sequence number (task identifier) + * @origin_seqno: previous sequence number (task identifier) - for reuse + * @input_fd: data input file descriptor (dma-buf) + * @output_fd: data output file descriptor (dma-buf) + * @input_size: filled data in bytes (from caller, must not exceed fragment size) + * @flags: see SND_COMPRESS_TFLG_* defines + */ +struct snd_compr_task { + __u64 seqno; + __u64 origin_seqno; + int input_fd; + int output_fd; + __u64 input_size; + __u32 flags; + __u8 reserved[16]; +} __attribute__((packed, aligned(4))); + +/** + * enum snd_compr_state - task state + * @SND_COMPRESS_TASK_STATE_IDLE: task is not queued + * @SND_COMPRESS_TASK_STATE_ACTIVE: task is in the queue + * @SND_COMPRESS_TASK_STATE_FINISHED: task was processed, output is available + */ +enum snd_compr_state { + SND_COMPRESS_TASK_STATE_IDLE = 0, + SND_COMPRESS_TASK_STATE_ACTIVE, + SND_COMPRESS_TASK_STATE_FINISHED +}; + +/** + * struct snd_compr_task_status - task status + * @seqno: sequence number (task identifier) + * @input_size: filled data in bytes (from user space) + * @output_size: filled data in bytes (from driver) + * @output_flags: reserved for future (all zeros - from driver) + * @state: actual task state (SND_COMPRESS_TASK_STATE_*) + */ +struct snd_compr_task_status { + __u64 seqno; + __u64 input_size; + __u64 output_size; + __u32 output_flags; + __u8 state; + __u8 reserved[15]; +} __attribute__((packed, aligned(4))); + /* * compress path ioctl definitions * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP @@ -164,6 +216,14 @@ struct snd_compr_metadata { #define SNDRV_COMPRESS_DRAIN _IO('C', 0x34) #define SNDRV_COMPRESS_NEXT_TRACK _IO('C', 0x35) #define SNDRV_COMPRESS_PARTIAL_DRAIN _IO('C', 0x36) + + +#define SNDRV_COMPRESS_TASK_CREATE _IOWR('C', 0x60, struct snd_compr_task) +#define SNDRV_COMPRESS_TASK_FREE _IOW('C', 0x61, __u64) +#define SNDRV_COMPRESS_TASK_START _IOWR('C', 0x62, struct snd_compr_task) +#define SNDRV_COMPRESS_TASK_STOP _IOW('C', 0x63, __u64) +#define SNDRV_COMPRESS_TASK_STATUS _IOWR('C', 0x68, struct snd_compr_task_status) + /* * TODO * 1. add mmap support diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 29d5dcc6bb54..8a2f14045bfc 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -59,6 +59,9 @@ config SND_CORE_TEST config SND_COMPRESS_OFFLOAD tristate +config SND_COMPRESS_ACCEL + bool + config SND_JACK bool diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index bdf1d78de833..5ecdad80a0d8 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,12 @@ struct snd_compr_file { static void error_delayed_work(struct work_struct *work); +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) +static void snd_compr_task_free_all(struct snd_compr_stream *stream); +#else +static inline void snd_compr_task_free_all(struct snd_compr_stream *stream) { } +#endif + /* * a note on stream states used: * we use following states in the compressed core @@ -85,6 +92,8 @@ static int snd_compr_open(struct inode *inode, struct file *f) dirn = SND_COMPRESS_PLAYBACK; else if ((f->f_flags & O_ACCMODE) == O_RDONLY) dirn = SND_COMPRESS_CAPTURE; + else if ((f->f_flags & O_ACCMODE) == O_RDWR) + dirn = SND_COMPRESS_ACCEL; else return -EINVAL; @@ -125,6 +134,9 @@ static int snd_compr_open(struct inode *inode, struct file *f) } runtime->state = SNDRV_PCM_STATE_OPEN; init_waitqueue_head(&runtime->sleep); +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) + INIT_LIST_HEAD(&runtime->tasks); +#endif data->stream.runtime = runtime; f->private_data = (void *)data; scoped_guard(mutex, &compr->lock) @@ -154,6 +166,8 @@ static int snd_compr_free(struct inode *inode, struct file *f) break; } + snd_compr_task_free_all(&data->stream); + data->stream.ops->free(&data->stream); if (!data->stream.runtime->dma_buffer_p) kfree(data->stream.runtime->buffer); @@ -226,6 +240,9 @@ snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg) struct snd_compr_avail ioctl_avail; size_t avail; + if (stream->direction == SND_COMPRESS_ACCEL) + return -EBADFD; + avail = snd_compr_calc_avail(stream, &ioctl_avail); ioctl_avail.avail = avail; @@ -287,6 +304,8 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf, return -EFAULT; stream = &data->stream; + if (stream->direction == SND_COMPRESS_ACCEL) + return -EBADFD; guard(mutex)(&stream->device->lock); /* write is allowed when stream is running or has been setup */ switch (stream->runtime->state) { @@ -336,6 +355,8 @@ static ssize_t snd_compr_read(struct file *f, char __user *buf, return -EFAULT; stream = &data->stream; + if (stream->direction == SND_COMPRESS_ACCEL) + return -EBADFD; guard(mutex)(&stream->device->lock); /* read is allowed when stream is running, paused, draining and setup @@ -385,6 +406,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; + struct snd_compr_runtime *runtime; size_t avail; __poll_t retval = 0; @@ -392,6 +414,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait) return EPOLLERR; stream = &data->stream; + runtime = stream->runtime; guard(mutex)(&stream->device->lock); @@ -405,6 +428,20 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait) poll_wait(f, &stream->runtime->sleep, wait); +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) + if (stream->direction == SND_COMPRESS_ACCEL) { + struct snd_compr_task_runtime *task; + if (runtime->fragments > runtime->active_tasks) + retval |= EPOLLOUT | EPOLLWRNORM; + task = list_first_entry_or_null(&runtime->tasks, + struct snd_compr_task_runtime, + list); + if (task && task->state == SND_COMPRESS_TASK_STATE_FINISHED) + retval |= EPOLLIN | EPOLLRDNORM; + return retval; + } +#endif + avail = snd_compr_get_avail(stream); pr_debug("avail is %ld\n", (unsigned long)avail); /* check if we have at least one fragment to fill */ @@ -521,6 +558,9 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, unsigned int buffer_size; void *buffer = NULL; + if (stream->direction == SND_COMPRESS_ACCEL) + goto params; + buffer_size = params->buffer.fragment_size * params->buffer.fragments; if (stream->ops->copy) { buffer = NULL; @@ -543,18 +583,30 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, if (!buffer) return -ENOMEM; } - stream->runtime->fragment_size = params->buffer.fragment_size; - stream->runtime->fragments = params->buffer.fragments; + stream->runtime->buffer = buffer; stream->runtime->buffer_size = buffer_size; +params: + stream->runtime->fragment_size = params->buffer.fragment_size; + stream->runtime->fragments = params->buffer.fragments; return 0; } -static int snd_compress_check_input(struct snd_compr_params *params) +static int +snd_compress_check_input(struct snd_compr_stream *stream, struct snd_compr_params *params) { + u32 max_fragments; + /* first let's check the buffer parameter's */ - if (params->buffer.fragment_size == 0 || - params->buffer.fragments > U32_MAX / params->buffer.fragment_size || + if (params->buffer.fragment_size == 0) + return -EINVAL; + + if (stream->direction == SND_COMPRESS_ACCEL) + max_fragments = 64; /* safe value */ + else + max_fragments = U32_MAX / params->buffer.fragment_size; + + if (params->buffer.fragments > max_fragments || params->buffer.fragments == 0) return -EINVAL; @@ -583,7 +635,7 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) if (IS_ERR(params)) return PTR_ERR(params); - retval = snd_compress_check_input(params); + retval = snd_compress_check_input(stream, params); if (retval) return retval; @@ -939,6 +991,264 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream) return snd_compress_wait_for_drain(stream); } +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) + +static struct snd_compr_task_runtime * +snd_compr_find_task(struct snd_compr_stream *stream, __u64 seqno) +{ + struct snd_compr_task_runtime *task; + + list_for_each_entry(task, &stream->runtime->tasks, list) { + if (task->seqno == seqno) + return task; + } + return NULL; +} + +static void snd_compr_task_free(struct snd_compr_task_runtime *task) +{ + if (task->output) + dma_buf_put(task->output); + if (task->input) + dma_buf_put(task->input); + kfree(task); +} + +static u64 snd_compr_seqno_next(struct snd_compr_stream *stream) +{ + u64 seqno = ++stream->runtime->task_seqno; + if (seqno == 0) + seqno = ++stream->runtime->task_seqno; + return seqno; +} + +static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_task *utask) +{ + struct snd_compr_task_runtime *task; + int retval; + + if (stream->runtime->total_tasks >= stream->runtime->fragments) + return -EBUSY; + if (utask->origin_seqno != 0 || utask->input_size != 0) + return -EINVAL; + task = kzalloc(sizeof(*task), GFP_KERNEL); + if (task == NULL) + return -ENOMEM; + task->seqno = utask->seqno = snd_compr_seqno_next(stream); + task->input_size = utask->input_size; + retval = stream->ops->task_create(stream, task); + if (retval < 0) + goto cleanup; + utask->input_fd = dma_buf_fd(task->input, O_WRONLY|O_CLOEXEC); + if (utask->input_fd < 0) { + retval = utask->input_fd; + goto cleanup; + } + utask->output_fd = dma_buf_fd(task->output, O_RDONLY|O_CLOEXEC); + if (utask->output_fd < 0) { + retval = utask->output_fd; + goto cleanup; + } + /* keep dmabuf reference until freed with task free ioctl */ + dma_buf_get(utask->input_fd); + dma_buf_get(utask->output_fd); + list_add_tail(&task->list, &stream->runtime->tasks); + stream->runtime->total_tasks++; + return 0; +cleanup: + snd_compr_task_free(task); + return retval; +} + +static int snd_compr_task_create(struct snd_compr_stream *stream, unsigned long arg) +{ + struct snd_compr_task *task __free(kfree) = NULL; + int retval; + + if (stream->runtime->state != SNDRV_PCM_STATE_SETUP) + return -EPERM; + task = memdup_user((void __user *)arg, sizeof(*task)); + if (IS_ERR(task)) + return PTR_ERR(no_free_ptr(task)); + retval = snd_compr_task_new(stream, task); + if (retval >= 0) + if (copy_to_user((void __user *)arg, task, sizeof(*task))) + retval = -EFAULT; + return retval; +} + +static int snd_compr_task_start_prepare(struct snd_compr_task_runtime *task, + struct snd_compr_task *utask) +{ + if (task == NULL) + return -EINVAL; + if (task->state >= SND_COMPRESS_TASK_STATE_FINISHED) + return -EBUSY; + if (utask->input_size > task->input->size) + return -EINVAL; + task->flags = utask->flags; + task->input_size = utask->input_size; + task->state = SND_COMPRESS_TASK_STATE_IDLE; + return 0; +} + +static int snd_compr_task_start(struct snd_compr_stream *stream, struct snd_compr_task *utask) +{ + struct snd_compr_task_runtime *task; + int retval; + + if (utask->origin_seqno > 0) { + task = snd_compr_find_task(stream, utask->origin_seqno); + retval = snd_compr_task_start_prepare(task, utask); + if (retval < 0) + return retval; + task->seqno = utask->seqno = snd_compr_seqno_next(stream); + utask->origin_seqno = 0; + list_move_tail(&task->list, &stream->runtime->tasks); + } else { + task = snd_compr_find_task(stream, utask->seqno); + if (task && task->state != SND_COMPRESS_TASK_STATE_IDLE) + return -EBUSY; + retval = snd_compr_task_start_prepare(task, utask); + if (retval < 0) + return retval; + } + retval = stream->ops->task_start(stream, task); + if (retval >= 0) { + task->state = SND_COMPRESS_TASK_STATE_ACTIVE; + stream->runtime->active_tasks++; + } + return retval; +} + +static int snd_compr_task_start_ioctl(struct snd_compr_stream *stream, unsigned long arg) +{ + struct snd_compr_task *task __free(kfree) = NULL; + int retval; + + if (stream->runtime->state != SNDRV_PCM_STATE_SETUP) + return -EPERM; + task = memdup_user((void __user *)arg, sizeof(*task)); + if (IS_ERR(task)) + return PTR_ERR(no_free_ptr(task)); + retval = snd_compr_task_start(stream, task); + if (retval >= 0) + if (copy_to_user((void __user *)arg, task, sizeof(*task))) + retval = -EFAULT; + return retval; +} + +static void snd_compr_task_stop_one(struct snd_compr_stream *stream, + struct snd_compr_task_runtime *task) +{ + if (task->state != SND_COMPRESS_TASK_STATE_ACTIVE) + return; + stream->ops->task_stop(stream, task); + if (!snd_BUG_ON(stream->runtime->active_tasks == 0)) + stream->runtime->active_tasks--; + list_move_tail(&task->list, &stream->runtime->tasks); + task->state = SND_COMPRESS_TASK_STATE_IDLE; +} + +static void snd_compr_task_free_one(struct snd_compr_stream *stream, + struct snd_compr_task_runtime *task) +{ + snd_compr_task_stop_one(stream, task); + stream->ops->task_free(stream, task); + list_del(&task->list); + snd_compr_task_free(task); + stream->runtime->total_tasks--; +} + +static void snd_compr_task_free_all(struct snd_compr_stream *stream) +{ + struct snd_compr_task_runtime *task, *temp; + + list_for_each_entry_safe_reverse(task, temp, &stream->runtime->tasks, list) + snd_compr_task_free_one(stream, task); +} + +typedef void (*snd_compr_seq_func_t)(struct snd_compr_stream *stream, + struct snd_compr_task_runtime *task); + +static int snd_compr_task_seq(struct snd_compr_stream *stream, unsigned long arg, + snd_compr_seq_func_t fcn) +{ + struct snd_compr_task_runtime *task; + __u64 seqno; + int retval; + + if (stream->runtime->state != SNDRV_PCM_STATE_SETUP) + return -EPERM; + retval = get_user(seqno, (__u64 __user *)arg); + if (retval < 0) + return retval; + retval = 0; + if (seqno == 0) { + list_for_each_entry_reverse(task, &stream->runtime->tasks, list) + fcn(stream, task); + } else { + task = snd_compr_find_task(stream, seqno); + if (task == NULL) { + retval = -EINVAL; + } else { + fcn(stream, task); + } + } + return retval; +} + +static int snd_compr_task_status(struct snd_compr_stream *stream, + struct snd_compr_task_status *status) +{ + struct snd_compr_task_runtime *task; + + task = snd_compr_find_task(stream, status->seqno); + if (task == NULL) + return -EINVAL; + status->input_size = task->input_size; + status->output_size = task->output_size; + status->state = task->state; + return 0; +} + +static int snd_compr_task_status_ioctl(struct snd_compr_stream *stream, unsigned long arg) +{ + struct snd_compr_task_status *status __free(kfree) = NULL; + int retval; + + if (stream->runtime->state != SNDRV_PCM_STATE_SETUP) + return -EPERM; + status = memdup_user((void __user *)arg, sizeof(*status)); + if (IS_ERR(status)) + return PTR_ERR(no_free_ptr(status)); + retval = snd_compr_task_status(stream, status); + if (retval >= 0) + if (copy_to_user((void __user *)arg, status, sizeof(*status))) + retval = -EFAULT; + return retval; +} + +/** + * snd_compr_task_finished: Notify that the task was finished + * @stream: pointer to stream + * @task: runtime task structure + * + * Set the finished task state and notify waiters. + */ +void snd_compr_task_finished(struct snd_compr_stream *stream, + struct snd_compr_task_runtime *task) +{ + guard(mutex)(&stream->device->lock); + if (!snd_BUG_ON(stream->runtime->active_tasks == 0)) + stream->runtime->active_tasks--; + task->state = SND_COMPRESS_TASK_STATE_FINISHED; + wake_up(&stream->runtime->sleep); +} +EXPORT_SYMBOL_GPL(snd_compr_task_finished); + +#endif /* CONFIG_SND_COMPRESS_ACCEL */ + static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { struct snd_compr_file *data = f->private_data; @@ -968,6 +1278,27 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) return snd_compr_set_metadata(stream, arg); case _IOC_NR(SNDRV_COMPRESS_GET_METADATA): return snd_compr_get_metadata(stream, arg); + } + + if (stream->direction == SND_COMPRESS_ACCEL) { +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) + switch (_IOC_NR(cmd)) { + case _IOC_NR(SNDRV_COMPRESS_TASK_CREATE): + return snd_compr_task_create(stream, arg); + case _IOC_NR(SNDRV_COMPRESS_TASK_FREE): + return snd_compr_task_seq(stream, arg, snd_compr_task_free_one); + case _IOC_NR(SNDRV_COMPRESS_TASK_START): + return snd_compr_task_start_ioctl(stream, arg); + case _IOC_NR(SNDRV_COMPRESS_TASK_STOP): + return snd_compr_task_seq(stream, arg, snd_compr_task_stop_one); + case _IOC_NR(SNDRV_COMPRESS_TASK_STATUS): + return snd_compr_task_status_ioctl(stream, arg); + } +#endif + return -ENOTTY; + } + + switch (_IOC_NR(cmd)) { case _IOC_NR(SNDRV_COMPRESS_TSTAMP): return snd_compr_tstamp(stream, arg); case _IOC_NR(SNDRV_COMPRESS_AVAIL): @@ -1140,6 +1471,11 @@ int snd_compress_new(struct snd_card *card, int device, }; int ret; +#if !IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) + if (snd_BUG_ON(dirn == SND_COMPRESS_ACCEL)) + return -EINVAL; +#endif + compr->card = card; compr->device = device; compr->direction = dirn; From 972acf7fb2f986e91c8ab7920451255f7b0ecd2c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:39:00 +0100 Subject: [PATCH 140/256] ASoC: rt1320: add mic function JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 20079dd9b364483db613186b289fe372bddf41b5 Author: Shuming Fan Date: Fri Oct 25 16:12:59 2024 +0800 ASoC: rt1320: add mic function This patch adds the mic function. Signed-off-by: Shuming Fan Link: https://patch.msgid.link/20241025081259.1419518-1-shumingf@realtek.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/rt1320-sdw.c | 323 ++++++++++++++++++++++++++++++++-- sound/soc/codecs/rt1320-sdw.h | 4 + 2 files changed, 313 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c index ebd6f09bd990..3510c3819074 100644 --- a/sound/soc/codecs/rt1320-sdw.c +++ b/sound/soc/codecs/rt1320-sdw.c @@ -21,6 +21,7 @@ #include #include #include "rt1320-sdw.h" +#include "rt-sdw-common.h" /* * The 'blind writes' is an SDCA term to deal with platform-specific initialization. @@ -106,6 +107,8 @@ static const struct reg_sequence rt1320_blind_write[] = { { 0x1000db09, 0x00 }, { 0x1000db0a, 0x40 }, { 0x0000d540, 0x01 }, + { 0xd172, 0x2a }, + { 0xc5d6, 0x01 }, }; static const struct reg_sequence rt1320_vc_blind_write[] = { @@ -225,22 +228,41 @@ static const struct reg_sequence rt1320_vc_blind_write[] = { { 0x0000d540, 0x01 }, { 0x0000c081, 0xfc }, { 0x0000f01e, 0x80 }, + { 0xc01b, 0xfc }, + { 0xc5d1, 0x89 }, + { 0xc5d8, 0x0a }, + { 0xc5f7, 0x22 }, + { 0xc5f6, 0x22 }, + { 0xc065, 0xa5 }, + { 0xc06b, 0x0a }, + { 0xd172, 0x2a }, + { 0xc5d6, 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, }; static const struct reg_default rt1320_reg_defaults[] = { + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x0b }, + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), 0x03 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE27, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PPU21, RT1320_SDCA_CTL_POSTURE_NUMBER, 0), 0x00 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x0b }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), 0x03 }, }; static const struct reg_default rt1320_mbq_defaults[] = { + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 }, }; @@ -306,6 +328,17 @@ static bool rt1320_readable_register(struct device *dev, unsigned int reg) case 0x1000f021: case 0x3fe2e000 ... 0x3fe2e003: case 0x3fc2ab80 ... 0x3fc2abd4: + /* 0x40801508/0x40801809/0x4080180a/0x40801909/0x4080190a */ + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01): + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_02): + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_MUTE, CH_01): + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_MUTE, CH_02): + /* 0x40880900/0x40880980 */ + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + /* 0x40881500 */ + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0): /* 0x41000189/0x4100018a */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02): @@ -388,6 +421,7 @@ static bool rt1320_volatile_register(struct device *dev, unsigned int reg) case 0x3fc2bf80 ... 0x3fc2bf83: case 0x3fc2bfc0 ... 0x3fc2bfc7: case 0x3fe2e000 ... 0x3fe2e003: + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_MODE, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): @@ -401,6 +435,10 @@ static bool rt1320_volatile_register(struct device *dev, unsigned int reg) static bool rt1320_mbq_readable_register(struct device *dev, unsigned int reg) { switch (reg) { + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01): + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_02): + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01): + case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_02): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_01): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_02): return true; @@ -456,7 +494,7 @@ static int rt1320_read_prop(struct sdw_slave *slave) prop->lane_control_support = true; /* first we need to allocate memory for set bits in port lists */ - prop->source_ports = BIT(4); + prop->source_ports = BIT(4) | BIT(8) | BIT(10); prop->sink_ports = BIT(1); nval = hweight32(prop->source_ports); @@ -500,7 +538,8 @@ static int rt1320_read_prop(struct sdw_slave *slave) return 0; } -static int rt1320_pde_transition_delay(struct rt1320_sdw_priv *rt1320, unsigned char ps) +static int rt1320_pde_transition_delay(struct rt1320_sdw_priv *rt1320, unsigned char func, + unsigned char entity, unsigned char ps) { unsigned int delay = 1000, val; @@ -509,8 +548,7 @@ static int rt1320_pde_transition_delay(struct rt1320_sdw_priv *rt1320, unsigned /* waiting for Actual PDE becomes to PS0/PS3 */ while (delay) { regmap_read(rt1320->regmap, - SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, - RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), &val); + SDW_SDCA_CTL(func, entity, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), &val); if (val == ps) break; @@ -627,7 +665,7 @@ static void rt1320_vc_preset(struct rt1320_sdw_priv *rt1320) usleep_range(delay, delay + 1000); if (reg == SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0)) - rt1320_pde_transition_delay(rt1320, val); + rt1320_pde_transition_delay(rt1320, FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, val); } } @@ -733,6 +771,34 @@ static int rt1320_update_status(struct sdw_slave *slave, return rt1320_io_init(&slave->dev, slave); } +static int rt1320_pde11_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, + RT1320_SDCA_CTL_REQ_POWER_STATE, 0), ps0); + rt1320_pde_transition_delay(rt1320, FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, + RT1320_SDCA_CTL_REQ_POWER_STATE, 0), ps3); + rt1320_pde_transition_delay(rt1320, FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, ps3); + break; + default: + break; + } + + return 0; +} + static int rt1320_pde23_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -746,13 +812,13 @@ static int rt1320_pde23_event(struct snd_soc_dapm_widget *w, regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), ps0); - rt1320_pde_transition_delay(rt1320, ps0); + rt1320_pde_transition_delay(rt1320, FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, ps0); break; case SND_SOC_DAPM_PRE_PMD: regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), ps3); - rt1320_pde_transition_delay(rt1320, ps3); + rt1320_pde_transition_delay(rt1320, FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, ps3); break; default: break; @@ -771,6 +837,13 @@ static int rt1320_set_gain_put(struct snd_kcontrol *kcontrol, unsigned int gain_l_val, gain_r_val; unsigned int lvalue, rvalue; const unsigned int interval_offset = 0xc0; + unsigned int changed = 0, reg_base; + struct rt_sdca_dmic_kctrl_priv *p; + unsigned int regvalue[4], gain_val[4], i; + int err; + + if (strstr(ucontrol->id.name, "FU Capture Volume")) + goto _dmic_vol_; regmap_read(rt1320->mbq_regmap, mc->reg, &lvalue); regmap_read(rt1320->mbq_regmap, mc->rreg, &rvalue); @@ -796,7 +869,48 @@ static int rt1320_set_gain_put(struct snd_kcontrol *kcontrol, regmap_write(rt1320->mbq_regmap, mc->reg, gain_l_val); /* Rch */ regmap_write(rt1320->mbq_regmap, mc->rreg, gain_r_val); + goto _done_; +_dmic_vol_: + p = (struct rt_sdca_dmic_kctrl_priv *)kcontrol->private_value; + + /* check all channels */ + for (i = 0; i < p->count; i++) { + if (i < 2) { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + regmap_read(rt1320->mbq_regmap, reg_base + i, ®value[i]); + } else { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + regmap_read(rt1320->mbq_regmap, reg_base + i - 2, ®value[i]); + } + + gain_val[i] = ucontrol->value.integer.value[i]; + if (gain_val[i] > p->max) + gain_val[i] = p->max; + + gain_val[i] = 0x1e00 - ((p->max - gain_val[i]) * interval_offset); + gain_val[i] &= 0xffff; + if (regvalue[i] != gain_val[i]) + changed = 1; + } + + if (!changed) + return 0; + + for (i = 0; i < p->count; i++) { + if (i < 2) { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + err = regmap_write(rt1320->mbq_regmap, reg_base + i, gain_val[i]); + } else { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + err = regmap_write(rt1320->mbq_regmap, reg_base + i - 2, gain_val[i]); + } + + if (err < 0) + dev_err(&rt1320->sdw_slave->dev, "0x%08x can't be set\n", reg_base + i); + } + +_done_: return 1; } @@ -809,6 +923,11 @@ static int rt1320_set_gain_get(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; unsigned int read_l, read_r, ctl_l = 0, ctl_r = 0; const unsigned int interval_offset = 0xc0; + unsigned int reg_base, regvalue, ctl, i; + struct rt_sdca_dmic_kctrl_priv *p; + + if (strstr(ucontrol->id.name, "FU Capture Volume")) + goto _dmic_vol_; regmap_read(rt1320->mbq_regmap, mc->reg, &read_l); regmap_read(rt1320->mbq_regmap, mc->rreg, &read_r); @@ -822,6 +941,121 @@ static int rt1320_set_gain_get(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] = ctl_l; ucontrol->value.integer.value[1] = ctl_r; + goto _done_; + +_dmic_vol_: + p = (struct rt_sdca_dmic_kctrl_priv *)kcontrol->private_value; + + /* check all channels */ + for (i = 0; i < p->count; i++) { + if (i < 2) { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + regmap_read(rt1320->mbq_regmap, reg_base + i, ®value); + } else { + reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01); + regmap_read(rt1320->mbq_regmap, reg_base + i - 2, ®value); + } + + ctl = p->max - (((0x1e00 - regvalue) & 0xffff) / interval_offset); + ucontrol->value.integer.value[i] = ctl; + } +_done_: + return 0; +} + +static int rt1320_set_fu_capture_ctl(struct rt1320_sdw_priv *rt1320) +{ + int err, i; + unsigned int ch_mute; + + for (i = 0; i < ARRAY_SIZE(rt1320->fu_mixer_mute); i++) { + ch_mute = (rt1320->fu_dapm_mute || rt1320->fu_mixer_mute[i]) ? 0x01 : 0x00; + + if (i < 2) + err = regmap_write(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, + RT1320_SDCA_CTL_FU_MUTE, CH_01) + i, ch_mute); + else + err = regmap_write(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, + RT1320_SDCA_CTL_FU_MUTE, CH_01) + i - 2, ch_mute); + if (err < 0) + return err; + } + + return 0; +} + +static int rt1320_dmic_fu_capture_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component); + struct rt_sdca_dmic_kctrl_priv *p = + (struct rt_sdca_dmic_kctrl_priv *)kcontrol->private_value; + unsigned int i; + + for (i = 0; i < p->count; i++) + ucontrol->value.integer.value[i] = !rt1320->fu_mixer_mute[i]; + + return 0; +} + +static int rt1320_dmic_fu_capture_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component); + struct rt_sdca_dmic_kctrl_priv *p = + (struct rt_sdca_dmic_kctrl_priv *)kcontrol->private_value; + int err, changed = 0, i; + + for (i = 0; i < p->count; i++) { + if (rt1320->fu_mixer_mute[i] != !ucontrol->value.integer.value[i]) + changed = 1; + rt1320->fu_mixer_mute[i] = !ucontrol->value.integer.value[i]; + } + + err = rt1320_set_fu_capture_ctl(rt1320); + if (err < 0) + return err; + + return changed; +} + +static int rt1320_dmic_fu_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct rt_sdca_dmic_kctrl_priv *p = + (struct rt_sdca_dmic_kctrl_priv *)kcontrol->private_value; + + if (p->max == 1) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = p->count; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = p->max; + return 0; +} + +static int rt1320_dmic_fu_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + rt1320->fu_dapm_mute = false; + rt1320_set_fu_capture_ctl(rt1320); + break; + case SND_SOC_DAPM_PRE_PMD: + rt1320->fu_dapm_mute = true; + rt1320_set_fu_capture_ctl(rt1320); + break; + } return 0; } @@ -842,6 +1076,7 @@ static SOC_ENUM_SINGLE_DECL(rt1320_rx_data_ch_enum, rt1320_rx_data_ch_select); static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0); +static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); static const struct snd_kcontrol_new rt1320_snd_controls[] = { SOC_DOUBLE_R_EXT_TLV("FU21 Playback Volume", @@ -849,6 +1084,13 @@ static const struct snd_kcontrol_new rt1320_snd_controls[] = { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_02), 0, 0x57, 0, rt1320_set_gain_get, rt1320_set_gain_put, out_vol_tlv), SOC_ENUM("RX Channel Select", rt1320_rx_data_ch_enum), + + RT_SDCA_FU_CTRL("FU Capture Switch", + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01), + 1, 1, 4, rt1320_dmic_fu_info, rt1320_dmic_fu_capture_get, rt1320_dmic_fu_capture_put), + RT_SDCA_EXT_TLV("FU Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01), + rt1320_set_gain_get, rt1320_set_gain_put, 4, 0x3f, in_vol_tlv, rt1320_dmic_fu_info), }; static const struct snd_kcontrol_new rt1320_spk_l_dac = @@ -864,12 +1106,19 @@ static const struct snd_soc_dapm_widget rt1320_dapm_widgets[] = { /* Audio Interface */ SND_SOC_DAPM_AIF_IN("DP1RX", "DP1 Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DP8-10TX", "DP8-10 Capture", 0, SND_SOC_NOPM, 0, 0), /* Digital Interface */ SND_SOC_DAPM_PGA("FU21", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("PDE 23", SND_SOC_NOPM, 0, 0, rt1320_pde23_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY("PDE 11", SND_SOC_NOPM, 0, 0, + rt1320_pde11_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_ADC("FU 113", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("FU 14", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_PGA_E("FU", SND_SOC_NOPM, 0, 0, NULL, 0, + rt1320_dmic_fu_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), /* Output */ SND_SOC_DAPM_SWITCH("OT23 L", SND_SOC_NOPM, 0, 0, &rt1320_spk_l_dac), @@ -880,6 +1129,8 @@ static const struct snd_soc_dapm_widget rt1320_dapm_widgets[] = { /* Input */ SND_SOC_DAPM_PGA("AEC Data", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_SIGGEN("AEC Gen"), + SND_SOC_DAPM_INPUT("DMIC1"), + SND_SOC_DAPM_INPUT("DMIC2"), }; static const struct snd_soc_dapm_route rt1320_dapm_routes[] = { @@ -892,6 +1143,13 @@ static const struct snd_soc_dapm_route rt1320_dapm_routes[] = { { "AEC Data", NULL, "AEC Gen" }, { "DP4TX", NULL, "AEC Data" }, + + {"DP8-10TX", NULL, "FU"}, + {"FU", NULL, "PDE 11"}, + {"FU", NULL, "FU 113"}, + {"FU", NULL, "FU 14"}, + {"FU 113", NULL, "DMIC1"}, + {"FU 14", NULL, "DMIC2"}, }; static int rt1320_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, @@ -915,6 +1173,7 @@ static int rt1320_sdw_hw_params(struct snd_pcm_substream *substream, snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config; struct sdw_port_config port_config; + struct sdw_port_config dmic_port_config[2]; struct sdw_stream_runtime *sdw_stream; int retval; unsigned int sampling_rate; @@ -939,12 +1198,23 @@ static int rt1320_sdw_hw_params(struct snd_pcm_substream *substream, } else { if (dai->id == RT1320_AIF1) port_config.num = 4; - else + else if (dai->id == RT1320_AIF2) { + dmic_port_config[0].ch_mask = BIT(0) | BIT(1); + dmic_port_config[0].num = 8; + dmic_port_config[1].ch_mask = BIT(0) | BIT(1); + dmic_port_config[1].num = 10; + } else return -EINVAL; } - retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config, + if (dai->id == RT1320_AIF1) + retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config, &port_config, 1, sdw_stream); + else if (dai->id == RT1320_AIF2) + retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config, + dmic_port_config, 2, sdw_stream); + else + return -EINVAL; if (retval) { dev_err(dai->dev, "%s: Unable to configure port\n", __func__); return retval; @@ -977,9 +1247,18 @@ static int rt1320_sdw_hw_params(struct snd_pcm_substream *substream, } /* set sampling frequency */ - regmap_write(rt1320->regmap, - SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), - sampling_rate); + if (dai->id == RT1320_AIF1) + regmap_write(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); + else { + regmap_write(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); + regmap_write(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); + } return 0; } @@ -1070,6 +1349,19 @@ static struct snd_soc_dai_driver rt1320_sdw_dai[] = { }, .ops = &rt1320_aif_dai_ops, }, + /* DMIC: DP8 2ch + DP10 2ch */ + { + .name = "rt1320-aif2", + .id = RT1320_AIF2, + .capture = { + .stream_name = "DP8-10 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = RT1320_STEREO_RATES, + .formats = RT1320_FORMATS, + }, + .ops = &rt1320_aif_dai_ops, + }, }; static int rt1320_sdw_init(struct device *dev, struct regmap *regmap, @@ -1097,6 +1389,9 @@ static int rt1320_sdw_init(struct device *dev, struct regmap *regmap, rt1320->hw_init = false; rt1320->first_hw_init = false; rt1320->version_id = -1; + rt1320->fu_dapm_mute = true; + rt1320->fu_mixer_mute[0] = rt1320->fu_mixer_mute[1] = + rt1320->fu_mixer_mute[2] = rt1320->fu_mixer_mute[3] = true; ret = devm_snd_soc_register_component(dev, &soc_component_sdw_rt1320, diff --git a/sound/soc/codecs/rt1320-sdw.h b/sound/soc/codecs/rt1320-sdw.h index 95ef9d37c6db..23b321aee6a9 100644 --- a/sound/soc/codecs/rt1320-sdw.h +++ b/sound/soc/codecs/rt1320-sdw.h @@ -26,6 +26,7 @@ /* RT1320 SDCA Control - function number */ #define FUNC_NUM_AMP 0x04 +#define FUNC_NUM_MIC 0x02 /* RT1320 SDCA entity */ #define RT1320_SDCA_ENT0 0x00 @@ -69,6 +70,7 @@ enum { RT1320_AIF1, + RT1320_AIF2, }; /* @@ -94,6 +96,8 @@ struct rt1320_sdw_priv { bool hw_init; bool first_hw_init; int version_id; + bool fu_dapm_mute; + bool fu_mixer_mute[4]; }; #endif /* __RT1320_SDW_H__ */ From 9969affaf471b3062fd5cf3290979b33ab71c480 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:39:00 +0100 Subject: [PATCH 141/256] ASoC: soc-devres: Remove unused devm_snd_soc_register_dai JIRA: https://issues.redhat.com/browse/RHEL-80681 commit dea15b2abdb09608af5909ed7d168ec20f36a81a Author: Dr. David Alan Gilbert Date: Mon Oct 28 02:12:26 2024 +0000 ASoC: soc-devres: Remove unused devm_snd_soc_register_dai The last use of devm_snd_soc_register_dai() was removed by commit fc4cb1e15f0c ("ASoC: topology: Properly unregister DAI on removal") in 2021. Remove it, and the helper it used. Signed-off-by: Dr. David Alan Gilbert Link: https://patch.msgid.link/20241028021226.477909-1-linux@treblig.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/soc.h | 4 ---- sound/soc/soc-devres.c | 37 ------------------------------------- 2 files changed, 41 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 41cb9f0fcef3..4af0302667be 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1428,10 +1428,6 @@ struct snd_soc_dai *snd_soc_get_dai_via_args(const struct of_phandle_args *dai_a struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, bool legacy_dai_naming); -struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev, - struct snd_soc_component *component, - struct snd_soc_dai_driver *dai_drv, - bool legacy_dai_naming); void snd_soc_unregister_dai(struct snd_soc_dai *dai); struct snd_soc_dai *snd_soc_find_dai( diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c index 4534a1c03e8e..c6364caabc0e 100644 --- a/sound/soc/soc-devres.c +++ b/sound/soc/soc-devres.c @@ -9,43 +9,6 @@ #include #include -static void devm_dai_release(struct device *dev, void *res) -{ - snd_soc_unregister_dai(*(struct snd_soc_dai **)res); -} - -/** - * devm_snd_soc_register_dai - resource-managed dai registration - * @dev: Device used to manage component - * @component: The component the DAIs are registered for - * @dai_drv: DAI driver to use for the DAI - * @legacy_dai_naming: if %true, use legacy single-name format; - * if %false, use multiple-name format; - */ -struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev, - struct snd_soc_component *component, - struct snd_soc_dai_driver *dai_drv, - bool legacy_dai_naming) -{ - struct snd_soc_dai **ptr; - struct snd_soc_dai *dai; - - ptr = devres_alloc(devm_dai_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return NULL; - - dai = snd_soc_register_dai(component, dai_drv, legacy_dai_naming); - if (dai) { - *ptr = dai; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } - - return dai; -} -EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai); - static void devm_component_release(struct device *dev, void *res) { const struct snd_soc_component_driver **cmpnt_drv = res; From 2b3e562485bce20a8c98dbc6271f53a940c85a08 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:39:00 +0100 Subject: [PATCH 142/256] ASoC: codecs: ES8326: Modify the configuration of and micbias JIRA: https://issues.redhat.com/browse/RHEL-80681 commit bc48c55557edea46939ffef8ab9fa807b5951948 Author: Zhang Yi Date: Mon Oct 28 14:05:29 2024 +0800 ASoC: codecs: ES8326: Modify the configuration of and micbias Because we designed a new version of ES8326, the configuration of micbias needed to be modified.We tested the new driver, on both the new version and the old one. It works well. Signed-off-by: Zhang Yi Link: https://patch.msgid.link/20241028060529.3359-1-zhangyi@everest-semi.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/es8326.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index d2130a313678..62a828cc519d 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -615,6 +615,10 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) } else { regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE, 0x0F, 0x0F); + if (es8326->version > ES8326_VERSION_B) { + regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x00); + } } } else { if (!es8326->calibrated) { @@ -641,6 +645,10 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) ES8326_MUTE_MASK, ~(ES8326_MUTE)); } else { msleep(300); + if (es8326->version > ES8326_VERSION_B) { + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x50); + regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x00); + } regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE, 0x0F, 0x00); } @@ -822,7 +830,7 @@ static void es8326_jack_detect_handler(struct work_struct *work) iface = snd_soc_component_read(comp, ES8326_HPDET_STA); dev_dbg(comp->dev, "gpio flag %#04x", iface); - if ((es8326->jack_remove_retry == 1) && (es8326->version != ES8326_VERSION_B)) { + if ((es8326->jack_remove_retry == 1) && (es8326->version < ES8326_VERSION_B)) { if (iface & ES8326_HPINSERT_FLAG) es8326->jack_remove_retry = 2; else @@ -860,7 +868,7 @@ static void es8326_jack_detect_handler(struct work_struct *work) /* * Inverted HPJACK_POL bit to trigger one IRQ to double check HP Removal event */ - if ((es8326->jack_remove_retry == 0) && (es8326->version != ES8326_VERSION_B)) { + if ((es8326->jack_remove_retry == 0) && (es8326->version < ES8326_VERSION_B)) { es8326->jack_remove_retry = 1; dev_dbg(comp->dev, "remove event check, invert HPJACK_POL, cnt = %d\n", es8326->jack_remove_retry); @@ -955,7 +963,7 @@ static int es8326_calibrate(struct snd_soc_component *component) regmap_read(es8326->regmap, ES8326_CHIP_VERSION, ®); es8326->version = reg; - if ((es8326->version == ES8326_VERSION_B) && (es8326->calibrated == false)) { + if ((es8326->version >= ES8326_VERSION_B) && (es8326->calibrated == false)) { dev_dbg(component->dev, "ES8326_VERSION_B, calibrating\n"); regmap_write(es8326->regmap, ES8326_CLK_INV, 0xc0); regmap_write(es8326->regmap, ES8326_CLK_DIV1, 0x03); @@ -1048,7 +1056,7 @@ static void es8326_init(struct snd_soc_component *component) regmap_write(es8326->regmap, ES8326_DAC_VPPSCALE, 0x15); regmap_write(es8326->regmap, ES8326_HPDET_TYPE, 0x80 | - ((es8326->version == ES8326_VERSION_B) ? + ((es8326->version >= ES8326_VERSION_B) ? (ES8326_HP_DET_SRC_PIN9 | es8326->jack_pol) : (ES8326_HP_DET_SRC_PIN9 | es8326->jack_pol | 0x04))); usleep_range(5000, 10000); @@ -1074,6 +1082,10 @@ static void es8326_init(struct snd_soc_component *component) regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x44); regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66); es8326_disable_micbias(es8326->component); + if (es8326->version > ES8326_VERSION_B) { + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x73, 0x03); + regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); + } msleep(200); regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9); From c01611e17cf05e689f2ad205fea72b06b0cca093 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:39:01 +0100 Subject: [PATCH 143/256] ALSA: docs: compress-accel: Format state machine flowchart as code block JIRA: https://issues.redhat.com/browse/RHEL-80681 commit f42eb4930923af90784339c313654c45b24c1d8f Author: Bagas Sanjaya Date: Mon Oct 28 18:16:46 2024 +0700 ALSA: docs: compress-accel: Format state machine flowchart as code block Stephen Rothwell reports multiple htmldocs indentation warnings when merging sound tree for linux-next: Documentation/sound/designs/compress-accel.rst:67: ERROR: Unexpected indentation. Documentation/sound/designs/compress-accel.rst:67: WARNING: Blank line required after table. Documentation/sound/designs/compress-accel.rst:68: WARNING: Line block ends without a blank line. Documentation/sound/designs/compress-accel.rst:72: WARNING: Block quote ends without a blank line; unexpected unindent. Documentation/sound/designs/compress-accel.rst:73: WARNING: Block quote ends without a blank line; unexpected unindent. Fix these above by wrapping passthrough audio stream state machine flowchart in a literal code block. Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode") Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/linux-next/20241028193242.11597640@canb.auug.org.au/ Signed-off-by: Bagas Sanjaya Link: https://patch.msgid.link/20241028111647.17378-2-bagasdotme@gmail.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- Documentation/sound/designs/compress-accel.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/sound/designs/compress-accel.rst b/Documentation/sound/designs/compress-accel.rst index abf1f76a8778..c9c1744b94c2 100644 --- a/Documentation/sound/designs/compress-accel.rst +++ b/Documentation/sound/designs/compress-accel.rst @@ -57,7 +57,7 @@ from the input buffer size). State Machine ============= -The passthrough audio stream state machine is described below : +The passthrough audio stream state machine is described below:: +----------+ | | From 87e271f5cd4fb21fbd28476c366a86cb1562294d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:39:01 +0100 Subject: [PATCH 144/256] ALSA: docs: Add toctree index entry for co-processor acceleration API JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9a0f6091060882881f2cefd1efbda658f207ee5c Author: Bagas Sanjaya Date: Mon Oct 28 18:16:47 2024 +0700 ALSA: docs: Add toctree index entry for co-processor acceleration API Sphinx reports missing toctree entry warning for co-processor acceleration API docs: Documentation/sound/designs/compress-accel.rst: WARNING: document isn't included in any toctree Add the missing entry to fix the warning. Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode") Signed-off-by: Bagas Sanjaya Link: https://patch.msgid.link/20241028111647.17378-3-bagasdotme@gmail.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- Documentation/sound/designs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/sound/designs/index.rst b/Documentation/sound/designs/index.rst index b79db9ad8732..6b825c5617fc 100644 --- a/Documentation/sound/designs/index.rst +++ b/Documentation/sound/designs/index.rst @@ -6,6 +6,7 @@ Designs and Implementations control-names channel-mapping-api + compress-accel compress-offload timestamping jack-controls From e36ee8c1431750da9feac46023692bae263729f9 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:39:01 +0100 Subject: [PATCH 145/256] ALSA: usb-audio: Add Pioneer DJ/AlphaTheta DJM-A9 Mixer JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 5289d00696396224507ee083f5aee6119569c8d3 Author: Sarah Grant Date: Fri Oct 25 16:39:28 2024 +0000 ALSA: usb-audio: Add Pioneer DJ/AlphaTheta DJM-A9 Mixer This also includes a change to the capture level as they differ with this device, as well as additional values for prefader channels. Acked-by: Olivia Mackintosh Signed-off-by: Sarah Grant Link: https://patch.msgid.link/20241025163927.12662-1-s@srd.tw Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/usb/mixer_quirks.c | 68 +++++++++++++++++++++++++++++++++++++--- sound/usb/quirks-table.h | 57 +++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 4 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index a95ebcf4e46e..23fcd680167d 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -3498,7 +3498,7 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer) } /* - * Pioneer DJ DJM Mixers + * Pioneer DJ / AlphaTheta DJM Mixers * * These devices generally have options for soft-switching the playback and * capture sources in addition to the recording level. Although different @@ -3515,17 +3515,23 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer) #define SND_DJM_CAP_CDLINE 0x01 #define SND_DJM_CAP_DIGITAL 0x02 #define SND_DJM_CAP_PHONO 0x03 +#define SND_DJM_CAP_PREFADER 0x05 #define SND_DJM_CAP_PFADER 0x06 #define SND_DJM_CAP_XFADERA 0x07 #define SND_DJM_CAP_XFADERB 0x08 #define SND_DJM_CAP_MIC 0x09 #define SND_DJM_CAP_AUX 0x0d #define SND_DJM_CAP_RECOUT 0x0a +#define SND_DJM_CAP_RECOUT_NOMIC 0x0e #define SND_DJM_CAP_NONE 0x0f #define SND_DJM_CAP_CH1PFADER 0x11 #define SND_DJM_CAP_CH2PFADER 0x12 #define SND_DJM_CAP_CH3PFADER 0x13 #define SND_DJM_CAP_CH4PFADER 0x14 +#define SND_DJM_CAP_CH1PREFADER 0x31 +#define SND_DJM_CAP_CH2PREFADER 0x32 +#define SND_DJM_CAP_CH3PREFADER 0x33 +#define SND_DJM_CAP_CH4PREFADER 0x34 // Playback types #define SND_DJM_PB_CH1 0x00 @@ -3551,6 +3557,7 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer) #define SND_DJM_900NXS2_IDX 0x3 #define SND_DJM_750MK2_IDX 0x4 #define SND_DJM_450_IDX 0x5 +#define SND_DJM_A9_IDX 0x6 #define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \ @@ -3579,7 +3586,7 @@ struct snd_djm_ctl { u16 wIndex; }; -static const char *snd_djm_get_label_caplevel(u16 wvalue) +static const char *snd_djm_get_label_caplevel_common(u16 wvalue) { switch (wvalue) { case 0x0000: return "-19dB"; @@ -3590,6 +3597,20 @@ static const char *snd_djm_get_label_caplevel(u16 wvalue) } }; +// The DJM-A9 has different capture levels than other, older models +static const char *snd_djm_get_label_caplevel_a9(u16 wvalue) +{ + switch (wvalue) { + case 0x0000: return "+15dB"; + case 0x0100: return "+12dB"; + case 0x0200: return "+9dB"; + case 0x0300: return "+6dB"; + case 0x0400: return "+3dB"; + case 0x0500: return "0dB"; + default: return NULL; + } +}; + static const char *snd_djm_get_label_cap_common(u16 wvalue) { switch (wvalue & 0x00ff) { @@ -3602,8 +3623,13 @@ static const char *snd_djm_get_label_cap_common(u16 wvalue) case SND_DJM_CAP_XFADERB: return "Cross Fader B"; case SND_DJM_CAP_MIC: return "Mic"; case SND_DJM_CAP_RECOUT: return "Rec Out"; + case SND_DJM_CAP_RECOUT_NOMIC: return "Rec Out without Mic"; case SND_DJM_CAP_AUX: return "Aux"; case SND_DJM_CAP_NONE: return "None"; + case SND_DJM_CAP_CH1PREFADER: return "Pre Fader Ch1"; + case SND_DJM_CAP_CH2PREFADER: return "Pre Fader Ch2"; + case SND_DJM_CAP_CH3PREFADER: return "Pre Fader Ch3"; + case SND_DJM_CAP_CH4PREFADER: return "Pre Fader Ch4"; case SND_DJM_CAP_CH1PFADER: return "Post Fader Ch1"; case SND_DJM_CAP_CH2PFADER: return "Post Fader Ch2"; case SND_DJM_CAP_CH3PFADER: return "Post Fader Ch3"; @@ -3623,6 +3649,14 @@ static const char *snd_djm_get_label_cap_850(u16 wvalue) } }; +static const char *snd_djm_get_label_caplevel(u8 device_idx, u16 wvalue) +{ + switch (device_idx) { + case SND_DJM_A9_IDX: return snd_djm_get_label_caplevel_a9(wvalue); + default: return snd_djm_get_label_caplevel_common(wvalue); + } +}; + static const char *snd_djm_get_label_cap(u8 device_idx, u16 wvalue) { switch (device_idx) { @@ -3644,7 +3678,7 @@ static const char *snd_djm_get_label_pb(u16 wvalue) static const char *snd_djm_get_label(u8 device_idx, u16 wvalue, u16 windex) { switch (windex) { - case SND_DJM_WINDEX_CAPLVL: return snd_djm_get_label_caplevel(wvalue); + case SND_DJM_WINDEX_CAPLVL: return snd_djm_get_label_caplevel(device_idx, wvalue); case SND_DJM_WINDEX_CAP: return snd_djm_get_label_cap(device_idx, wvalue); case SND_DJM_WINDEX_PB: return snd_djm_get_label_pb(wvalue); default: return NULL; @@ -3653,7 +3687,7 @@ static const char *snd_djm_get_label(u8 device_idx, u16 wvalue, u16 windex) // common DJM capture level option values static const u16 snd_djm_opts_cap_level[] = { - 0x0000, 0x0100, 0x0200, 0x0300 }; + 0x0000, 0x0100, 0x0200, 0x0300, 0x400, 0x500 }; // DJM-250MK2 @@ -3795,6 +3829,28 @@ static const struct snd_djm_ctl snd_djm_ctls_750mk2[] = { }; +// DJM-A9 +static const u16 snd_djm_opts_a9_cap1[] = { + 0x0107, 0x0108, 0x0109, 0x010a, 0x010e, + 0x111, 0x112, 0x113, 0x114, 0x0131, 0x132, 0x133, 0x134 }; +static const u16 snd_djm_opts_a9_cap2[] = { + 0x0201, 0x0202, 0x0203, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020e }; +static const u16 snd_djm_opts_a9_cap3[] = { + 0x0301, 0x0302, 0x0303, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a, 0x030e }; +static const u16 snd_djm_opts_a9_cap4[] = { + 0x0401, 0x0402, 0x0403, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040e }; +static const u16 snd_djm_opts_a9_cap5[] = { + 0x0501, 0x0502, 0x0503, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, 0x050a, 0x050e }; + +static const struct snd_djm_ctl snd_djm_ctls_a9[] = { + SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), + SND_DJM_CTL("Master Input", a9_cap1, 3, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch1 Input", a9_cap2, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch2 Input", a9_cap3, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch3 Input", a9_cap4, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch4 Input", a9_cap5, 2, SND_DJM_WINDEX_CAP) +}; + static const struct snd_djm_device snd_djm_devices[] = { [SND_DJM_250MK2_IDX] = SND_DJM_DEVICE(250mk2), [SND_DJM_750_IDX] = SND_DJM_DEVICE(750), @@ -3802,6 +3858,7 @@ static const struct snd_djm_device snd_djm_devices[] = { [SND_DJM_900NXS2_IDX] = SND_DJM_DEVICE(900nxs2), [SND_DJM_750MK2_IDX] = SND_DJM_DEVICE(750mk2), [SND_DJM_450_IDX] = SND_DJM_DEVICE(450), + [SND_DJM_A9_IDX] = SND_DJM_DEVICE(a9), }; @@ -4080,6 +4137,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */ err = snd_djm_controls_create(mixer, SND_DJM_900NXS2_IDX); break; + case USB_ID(0x2b73, 0x003c): /* Pioneer DJ / AlphaTheta DJM-A9 */ + err = snd_djm_controls_create(mixer, SND_DJM_A9_IDX); + break; } return err; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 3f8beacca27a..8954be23325c 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3131,6 +3131,63 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +{ + /* + * Pioneer DJ / AlphaTheta DJM-A9 + * 10 channels playback & 12 channels capture @ 44.1/48/96kHz S24LE + */ + USB_DEVICE_VENDOR_SPEC(0x2b73, 0x003c), + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { + QUIRK_DATA_AUDIOFORMAT(0) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 10, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_44100| + SNDRV_PCM_RATE_48000| + SNDRV_PCM_RATE_96000, + .rate_min = 44100, + .rate_max = 96000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { + 44100, 48000, 96000 + } + } + }, + { + QUIRK_DATA_AUDIOFORMAT(0) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 12, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x82, + .ep_idx = 1, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC| + USB_ENDPOINT_USAGE_IMPLICIT_FB, + .rates = SNDRV_PCM_RATE_44100| + SNDRV_PCM_RATE_48000| + SNDRV_PCM_RATE_96000, + .rate_min = 44100, + .rate_max = 96000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { + 44100, 48000, 96000 + } + } + }, + QUIRK_COMPOSITE_END + } + } +}, + /* * MacroSilicon MS2100/MS2106 based AV capture cards * From 18193deee284683930ee6f6999fa119571515f64 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:39:01 +0100 Subject: [PATCH 146/256] ASoC: cs42l84: remove incorrect of_match_ptr() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0d4f74febc9d92d88099aff01f121b7f5f942c8f Author: Arnd Bergmann Date: Tue Oct 29 09:23:55 2024 +0000 ASoC: cs42l84: remove incorrect of_match_ptr() The use of of_match_ptr() is incorrect here and just causes a warning: sound/soc/codecs/cs42l84.c:1084:34: error: unused variable 'cs42l84_of_match' [-Werror,-Wunused-const-variable] Fixes: 250304a0fb34 ("ASoC: cs42l84: Add new codec driver") Signed-off-by: Arnd Bergmann Link: https://patch.msgid.link/20241029092404.3874040-1-arnd@kernel.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/cs42l84.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l84.c b/sound/soc/codecs/cs42l84.c index 47731cdc0e67..d176add8c4a6 100644 --- a/sound/soc/codecs/cs42l84.c +++ b/sound/soc/codecs/cs42l84.c @@ -1096,7 +1096,7 @@ MODULE_DEVICE_TABLE(i2c, cs42l84_id); static struct i2c_driver cs42l84_i2c_driver = { .driver = { .name = "cs42l84", - .of_match_table = of_match_ptr(cs42l84_of_match), + .of_match_table = cs42l84_of_match, }, .id_table = cs42l84_id, .probe = cs42l84_i2c_probe, From 467ee6caf77bc51c8c5772b9d6ba013d5a7f0eae Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:39:01 +0100 Subject: [PATCH 147/256] ASoC: codecs: adau1373: add some kconfig text JIRA: https://issues.redhat.com/browse/RHEL-80681 commit bebf0f45326e6cbb6f96e405e4179962a5675aaf Author: Nuno Sa Date: Mon Oct 28 16:43:38 2024 +0100 ASoC: codecs: adau1373: add some kconfig text Add some text to 'tristate' so that we can actually enable the driver when using things like menuconfig. Signed-off-by: Nuno Sa Link: https://patch.msgid.link/20241028-adau1373-shutdown-v2-1-647f56bbd182@analog.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index deab09965010..e18289d70263 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -457,7 +457,7 @@ config SND_SOC_ADAU1372_SPI select REGMAP_SPI config SND_SOC_ADAU1373 - tristate + tristate "Analog Devices ADAU1373 CODEC" depends on I2C select SND_SOC_ADAU_UTILS From 7540c0c9840e6e641d553ce220c119e6f4ce0fd2 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:41:39 +0100 Subject: [PATCH 148/256] ASoC: dt-bindings: document the adau1373 Codec JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 6b26a56fc035971951299dc1330e1fc5d49866c9 Author: Nuno Sa Date: Mon Oct 28 16:43:39 2024 +0100 ASoC: dt-bindings: document the adau1373 Codec Describe the adau1373 Low Power Codec with Speaker and Headphone Amplifier. While at it, properly add a MAINTAINERS entry for ADI sound bindings. Signed-off-by: Nuno Sa Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20241028-adau1373-shutdown-v2-2-647f56bbd182@analog.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- .../bindings/sound/adi,adau1373.yaml | 111 ++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 112 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/adi,adau1373.yaml diff --git a/Documentation/devicetree/bindings/sound/adi,adau1373.yaml b/Documentation/devicetree/bindings/sound/adi,adau1373.yaml new file mode 100644 index 000000000000..97552bf5d951 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/adi,adau1373.yaml @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/adi,adau1373.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices ADAU1373 CODEC + +maintainers: + - Nuno Sá + +description: | + Analog Devices ADAU1373 Low power codec with speaker and headphone amplifiers. + https://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1373.pdf + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - adi,adau1373 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + + powerdown-gpios: + description: GPIO used for hardware power-down. + maxItems: 1 + + adi,micbias1-microvolt: + description: + This property sets the microphone bias voltage for the first microphone. + enum: [1800000, 2200000, 2600000, 2900000] + default: 2900000 + + adi,micbias2-microvolt: + description: + This property sets the microphone bias voltage for the second microphone. + enum: [1800000, 2200000, 2600000, 2900000] + default: 2900000 + + adi,input1-differential: + description: This property sets the first analog input as differential. + type: boolean + + adi,input2-differential: + description: This property sets the second analog input as differential. + type: boolean + + adi,input3-differential: + description: This property sets the third analog input as differential. + type: boolean + + adi,input4-differential: + description: This property sets the fourth analog input as differential. + type: boolean + + adi,lineout-differential: + description: This property sets the line output as differential. + type: boolean + + adi,lineout-gnd-sense: + description: This property enables the line output ground sense control. + type: boolean + + adi,drc-settings: + description: + This setting is used to control the dynamic range of the signal. The + device provides a maximum of three full band DRCs with 13 entries each. + $ref: /schemas/types.yaml#/definitions/uint8-array + oneOf: + - minItems: 13 + maxItems: 13 + - minItems: 26 + maxItems: 26 + - minItems: 39 + maxItems: 39 + +required: + - "#sound-dai-cells" + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + audio-codec@1a { + compatible = "adi,adau1373"; + reg = <0x1a>; + #sound-dai-cells = <0>; + powerdown-gpios = <&gpio 100 GPIO_ACTIVE_LOW>; + adi,input2-differential; + adi,input1-differential; + adi,lineout-differential; + adi,micbias2-microvolt = <1800000>; + adi,drc-settings = /bits/ 8 < + 0xff 0xff 0x1 0x2 0xa 0xa 0xd 0x1 0xff 0xff 0x5 0xd 0xff + >; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index eed52bedf6d3..d09d814b2351 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1224,6 +1224,7 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported W: http://wiki.analog.com/ W: http://ez.analog.com/community/linux-device-drivers +F: Documentation/devicetree/bindings/sound/adi,* F: sound/soc/codecs/ad1* F: sound/soc/codecs/ad7* F: sound/soc/codecs/adau* From 5723ba963e0099f19f70692c740bdfc41b4db8b7 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:00 +0100 Subject: [PATCH 149/256] ASoC: codecs: adau1373: drop patform_data JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 71743cbe28cf1d1f845a30bc9664c3b6a08f0d30 Author: Nuno Sa Date: Mon Oct 28 16:43:40 2024 +0100 ASoC: codecs: adau1373: drop patform_data struct adau1373_platform_data" was not being used by any platform. Hence, drop it and move to firmware based support. All the configurations quirks present in the platform_data are now supported as firmware properties. Signed-off-by: Nuno Sa Link: https://patch.msgid.link/20241028-adau1373-shutdown-v2-3-647f56bbd182@analog.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/adau1373.h | 33 ------- sound/soc/codecs/adau1373.c | 180 ++++++++++++++++++++++++++---------- 2 files changed, 132 insertions(+), 81 deletions(-) delete mode 100644 include/sound/adau1373.h diff --git a/include/sound/adau1373.h b/include/sound/adau1373.h deleted file mode 100644 index 4c32ba1328ed..000000000000 --- a/include/sound/adau1373.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Analog Devices ADAU1373 Audio Codec drive - * - * Copyright 2011 Analog Devices Inc. - * Author: Lars-Peter Clausen - */ - -#ifndef __SOUND_ADAU1373_H__ -#define __SOUND_ADAU1373_H__ - -enum adau1373_micbias_voltage { - ADAU1373_MICBIAS_2_9V = 0, - ADAU1373_MICBIAS_2_2V = 1, - ADAU1373_MICBIAS_2_6V = 2, - ADAU1373_MICBIAS_1_8V = 3, -}; - -#define ADAU1373_DRC_SIZE 13 - -struct adau1373_platform_data { - bool input_differential[4]; - bool lineout_differential; - bool lineout_ground_sense; - - unsigned int num_drc; - uint8_t drc_setting[3][ADAU1373_DRC_SIZE]; - - enum adau1373_micbias_voltage micbias1; - enum adau1373_micbias_voltage micbias2; -}; - -#endif diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 38517def1b69..5be158ddf5f0 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -18,7 +19,6 @@ #include #include #include -#include #include "adau1373.h" #include "adau-utils.h" @@ -30,9 +30,28 @@ struct adau1373_dai { bool clock_provider; }; +enum adau1373_micbias_voltage { + ADAU1373_MICBIAS_2_9V, + ADAU1373_MICBIAS_2_2V, + ADAU1373_MICBIAS_2_6V, + ADAU1373_MICBIAS_1_8V, +}; + +#define ADAU1373_DRC_SIZE 13 + struct adau1373 { struct regmap *regmap; struct adau1373_dai dais[3]; + + bool input_differential[4]; + bool lineout_differential; + bool lineout_ground_sense; + + unsigned int num_drc; + u8 drc_setting[3][ADAU1373_DRC_SIZE]; + + enum adau1373_micbias_voltage micbias1; + enum adau1373_micbias_voltage micbias2; }; #define ADAU1373_INPUT_MODE 0x00 @@ -1332,66 +1351,61 @@ static void adau1373_load_drc_settings(struct adau1373 *adau1373, regmap_write(adau1373->regmap, ADAU1373_DRC(nr) + i, drc[i]); } -static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias) +static int adau1373_get_micbias(unsigned int val, + enum adau1373_micbias_voltage *micbias) { - switch (micbias) { - case ADAU1373_MICBIAS_2_9V: - case ADAU1373_MICBIAS_2_2V: - case ADAU1373_MICBIAS_2_6V: - case ADAU1373_MICBIAS_1_8V: - return true; + switch (val) { + case 2900000: + *micbias = ADAU1373_MICBIAS_2_9V; + return 0; + case 2200000: + *micbias = ADAU1373_MICBIAS_2_2V; + return 0; + case 2600000: + *micbias = ADAU1373_MICBIAS_2_6V; + return 0; + case 1800000: + *micbias = ADAU1373_MICBIAS_1_8V; + return 0; default: - break; + return -EINVAL; } - return false; } static int adau1373_probe(struct snd_soc_component *component) { struct adau1373 *adau1373 = snd_soc_component_get_drvdata(component); - struct adau1373_platform_data *pdata = component->dev->platform_data; - bool lineout_differential = false; unsigned int val; int i; - if (pdata) { - if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting)) - return -EINVAL; - - if (!adau1373_valid_micbias(pdata->micbias1) || - !adau1373_valid_micbias(pdata->micbias2)) - return -EINVAL; - - for (i = 0; i < pdata->num_drc; ++i) { - adau1373_load_drc_settings(adau1373, i, - pdata->drc_setting[i]); - } - - snd_soc_add_component_controls(component, adau1373_drc_controls, - pdata->num_drc); - - val = 0; - for (i = 0; i < 4; ++i) { - if (pdata->input_differential[i]) - val |= BIT(i); - } - regmap_write(adau1373->regmap, ADAU1373_INPUT_MODE, val); - - val = 0; - if (pdata->lineout_differential) - val |= ADAU1373_OUTPUT_CTRL_LDIFF; - if (pdata->lineout_ground_sense) - val |= ADAU1373_OUTPUT_CTRL_LNFBEN; - regmap_write(adau1373->regmap, ADAU1373_OUTPUT_CTRL, val); - - lineout_differential = pdata->lineout_differential; - - regmap_write(adau1373->regmap, ADAU1373_EP_CTRL, - (pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) | - (pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET)); + for (i = 0; i < adau1373->num_drc; ++i) { + adau1373_load_drc_settings(adau1373, i, + adau1373->drc_setting[i]); } - if (!lineout_differential) { + snd_soc_add_component_controls(component, adau1373_drc_controls, + adau1373->num_drc); + + val = 0; + for (i = 0; i < ARRAY_SIZE(adau1373->input_differential); ++i) { + if (adau1373->input_differential[i]) + val |= BIT(i); + } + regmap_write(adau1373->regmap, ADAU1373_INPUT_MODE, val); + + val = 0; + if (adau1373->lineout_differential) + val |= ADAU1373_OUTPUT_CTRL_LDIFF; + if (adau1373->lineout_ground_sense) + val |= ADAU1373_OUTPUT_CTRL_LNFBEN; + + regmap_write(adau1373->regmap, ADAU1373_OUTPUT_CTRL, val); + + regmap_write(adau1373->regmap, ADAU1373_EP_CTRL, + (adau1373->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) | + (adau1373->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET)); + + if (!adau1373->lineout_differential) { snd_soc_add_component_controls(component, adau1373_lineout2_controls, ARRAY_SIZE(adau1373_lineout2_controls)); } @@ -1471,6 +1485,65 @@ static const struct snd_soc_component_driver adau1373_component_driver = { .endianness = 1, }; +static int adau1373_parse_fw(struct device *dev, struct adau1373 *adau1373) +{ + int ret, drc_count; + unsigned int val; + + if (device_property_present(dev, "adi,input1-differential")) + adau1373->input_differential[0] = true; + if (device_property_present(dev, "adi,input2-differential")) + adau1373->input_differential[1] = true; + if (device_property_present(dev, "adi,input3-differential")) + adau1373->input_differential[2] = true; + if (device_property_present(dev, "adi,input4-differential")) + adau1373->input_differential[3] = true; + + if (device_property_present(dev, "adi,lineout-differential")) + adau1373->lineout_differential = true; + if (device_property_present(dev, "adi,lineout-gnd-sense")) + adau1373->lineout_ground_sense = true; + + ret = device_property_read_u32(dev, "adi,micbias1-microvolt", &val); + if (!ret) { + ret = adau1373_get_micbias(val, &adau1373->micbias1); + if (ret) + return dev_err_probe(dev, ret, + "Failed to get micbias1(%u)\n", val); + } + + ret = device_property_read_u32(dev, "adi,micbias2-microvolt", &val); + if (!ret) { + ret = adau1373_get_micbias(val, &adau1373->micbias2); + if (ret) + return dev_err_probe(dev, ret, + "Failed to get micbias2(%u)\n", val); + } + + drc_count = device_property_count_u8(dev, "adi,drc-settings"); + if (drc_count < 0) + return 0; + if (drc_count % ADAU1373_DRC_SIZE != 0) + return dev_err_probe(dev, -EINVAL, + "DRC count(%u) not multiple of %u\n", + drc_count, ADAU1373_DRC_SIZE); + + adau1373->num_drc = drc_count / ADAU1373_DRC_SIZE; + if (adau1373->num_drc > ARRAY_SIZE(adau1373->drc_setting)) + return dev_err_probe(dev, -EINVAL, + "Too many DRC settings(%u)\n", + adau1373->num_drc); + + ret = device_property_read_u8_array(dev, "adi,drc-settings", + (u8 *)&adau1373->drc_setting[0], + drc_count); + if (ret) + return dev_err_probe(dev, ret, + "Failed to read DRC settings\n"); + + return 0; +} + static int adau1373_i2c_probe(struct i2c_client *client) { struct adau1373 *adau1373; @@ -1489,6 +1562,10 @@ static int adau1373_i2c_probe(struct i2c_client *client) dev_set_drvdata(&client->dev, adau1373); + ret = adau1373_parse_fw(&client->dev, adau1373); + if (ret) + return ret; + ret = devm_snd_soc_register_component(&client->dev, &adau1373_component_driver, adau1373_dai_driver, ARRAY_SIZE(adau1373_dai_driver)); @@ -1501,9 +1578,16 @@ static const struct i2c_device_id adau1373_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id); +static const struct of_device_id adau1373_of_match[] = { + { .compatible = "adi,adau1373", }, + { } +}; +MODULE_DEVICE_TABLE(of, adau1373_of_match); + static struct i2c_driver adau1373_i2c_driver = { .driver = { .name = "adau1373", + .of_match_table = adau1373_of_match, }, .probe_new = adau1373_i2c_probe, .id_table = adau1373_i2c_id, From 34f5fab1a1aeef65cbeb753c876cfec224c7823c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:00 +0100 Subject: [PATCH 150/256] ASoC: codecs: adau1373: add powerdown gpio JIRA: https://issues.redhat.com/browse/RHEL-80681 commit ba79bca407d3b7e6f5be209d9b3f73f81ee8d460 Author: Nuno Sa Date: Mon Oct 28 16:43:41 2024 +0100 ASoC: codecs: adau1373: add powerdown gpio If the powerdown GPIO is specified, we use it for reset. Otherwise, fallback to a software reset. Signed-off-by: Nuno Sa Link: https://patch.msgid.link/20241028-adau1373-shutdown-v2-4-647f56bbd182@analog.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/adau1373.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 5be158ddf5f0..767c11e70489 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -1485,6 +1486,11 @@ static const struct snd_soc_component_driver adau1373_component_driver = { .endianness = 1, }; +static void adau1373_reset(void *reset_gpio) +{ + gpiod_set_value_cansleep(reset_gpio, 1); +} + static int adau1373_parse_fw(struct device *dev, struct adau1373 *adau1373) { int ret, drc_count; @@ -1547,6 +1553,7 @@ static int adau1373_parse_fw(struct device *dev, struct adau1373 *adau1373) static int adau1373_i2c_probe(struct i2c_client *client) { struct adau1373 *adau1373; + struct gpio_desc *gpiod; int ret; adau1373 = devm_kzalloc(&client->dev, sizeof(*adau1373), GFP_KERNEL); @@ -1558,7 +1565,26 @@ static int adau1373_i2c_probe(struct i2c_client *client) if (IS_ERR(adau1373->regmap)) return PTR_ERR(adau1373->regmap); - regmap_write(adau1373->regmap, ADAU1373_SOFT_RESET, 0x00); + /* + * If the powerdown GPIO is specified, we use it for reset. Otherwise + * a software reset is done. + */ + gpiod = devm_gpiod_get_optional(&client->dev, "powerdown", + GPIOD_OUT_HIGH); + if (IS_ERR(gpiod)) + return PTR_ERR(gpiod); + + if (gpiod) { + gpiod_set_value_cansleep(gpiod, 0); + fsleep(10); + + ret = devm_add_action_or_reset(&client->dev, adau1373_reset, + gpiod); + if (ret) + return ret; + } else { + regmap_write(adau1373->regmap, ADAU1373_SOFT_RESET, 0x00); + } dev_set_drvdata(&client->dev, adau1373); From 287c2f00287f550a85249ac598460e8602375c42 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:33 +0100 Subject: [PATCH 151/256] ASoC: cs42l84: Remove unused including JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 334d538e176ce0c70bea5321d067432df2299bca Author: Jiapeng Chong Date: Wed Oct 30 10:10:47 2024 +0800 ASoC: cs42l84: Remove unused including ./sound/soc/codecs/cs42l84.c: 15 linux/version.h not needed. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=11570 Signed-off-by: Jiapeng Chong Link: https://patch.msgid.link/20241030021047.70543-1-jiapeng.chong@linux.alibaba.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/cs42l84.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/cs42l84.c b/sound/soc/codecs/cs42l84.c index d176add8c4a6..17d5c96e334d 100644 --- a/sound/soc/codecs/cs42l84.c +++ b/sound/soc/codecs/cs42l84.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include From ce9807b5b8646cc22dc3acb5de6107e6066e8b2d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:44 +0100 Subject: [PATCH 152/256] ASoC: codecs: wcd937x: Remove unused of_gpio.h JIRA: https://issues.redhat.com/browse/RHEL-80681 commit bd0aff85d5f3f3fc22735ab5869008dfd8ab4867 Author: Andy Shevchenko Date: Thu Oct 31 12:33:02 2024 +0200 ASoC: codecs: wcd937x: Remove unused of_gpio.h of_gpio.h is deprecated and subject to remove. The drivers in question don't use it, simply remove the unused header. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20241031103302.2450830-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/wcd937x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c index 3c1224d8f2df..466be1cb6fe2 100644 --- a/sound/soc/codecs/wcd937x.c +++ b/sound/soc/codecs/wcd937x.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include From 4d3ecde1b9368342293031572d8d08580193d777 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:44 +0100 Subject: [PATCH 153/256] ASoC: doc: update clock api details JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 019610566757a749dde7e0c92777d2c1613afef8 Author: anish kumar Date: Wed Oct 30 20:58:29 2024 -0700 ASoC: doc: update clock api details Added ASoC clock api kernel doc in this document. Signed-off-by: anish kumar Link: https://patch.msgid.link/20241031035829.54852-1-yesanishhere@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- Documentation/sound/soc/clocking.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/sound/soc/clocking.rst b/Documentation/sound/soc/clocking.rst index 32122d6877a3..25d016ea8b65 100644 --- a/Documentation/sound/soc/clocking.rst +++ b/Documentation/sound/soc/clocking.rst @@ -42,5 +42,17 @@ rate, number of channels and word size) to save on power. It is also desirable to use the codec (if possible) to drive (or master) the audio clocks as it usually gives more accurate sample rates than the CPU. +ASoC provided clock APIs +------------------------ +.. kernel-doc:: sound/soc/soc-dai.c + :identifiers: snd_soc_dai_set_sysclk +.. kernel-doc:: sound/soc/soc-dai.c + :identifiers: snd_soc_dai_set_clkdiv + +.. kernel-doc:: sound/soc/soc-dai.c + :identifiers: snd_soc_dai_set_pll + +.. kernel-doc:: sound/soc/soc-dai.c + :identifiers: snd_soc_dai_set_bclk_ratio From d3ee4d4ec5ef72c7f8306e3e1eb28b47ce271fb5 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:44 +0100 Subject: [PATCH 154/256] mfd: cs42l43: Disable IRQs during suspend JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 2bb0106db90f86c3c513c26bb42ef0798ae8164d Author: Charles Keepax Date: Mon Oct 14 10:52:02 2024 +0100 mfd: cs42l43: Disable IRQs during suspend The ASoC CODEC driver masks the IRQs whilst entering and exiting system suspend to avoid issues where the IRQ handler can run but PM runtime is disabled. However, as the IRQs could also be used from other parts of the driver, it would be better to move this handling to the MFD level. Remove the handling from the ASoC driver and move it to the MFD driver. Whilst moving also ensure the IRQs are all masked at the device level before powering down the device, as per hardware recommendations. Signed-off-by: Charles Keepax Acked-by: Mark Brown Link: https://lore.kernel.org/r/20241014095202.828194-1-ckeepax@opensource.cirrus.com Signed-off-by: Lee Jones Signed-off-by: Jaroslav Kysela --- drivers/mfd/cs42l43.c | 62 +++++++++++++++++++++++++++++++++----- sound/soc/codecs/cs42l43.c | 42 -------------------------- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/drivers/mfd/cs42l43.c b/drivers/mfd/cs42l43.c index 3b4efb294471..e5f17fc430e4 100644 --- a/drivers/mfd/cs42l43.c +++ b/drivers/mfd/cs42l43.c @@ -1109,16 +1109,39 @@ EXPORT_SYMBOL_NS_GPL(cs42l43_dev_remove, MFD_CS42L43); static int cs42l43_suspend(struct device *dev) { struct cs42l43 *cs42l43 = dev_get_drvdata(dev); + static const struct reg_sequence mask_all[] = { + { CS42L43_DECIM_MASK, 0xFFFFFFFF, }, + { CS42L43_EQ_MIX_MASK, 0xFFFFFFFF, }, + { CS42L43_ASP_MASK, 0xFFFFFFFF, }, + { CS42L43_PLL_MASK, 0xFFFFFFFF, }, + { CS42L43_SOFT_MASK, 0xFFFFFFFF, }, + { CS42L43_SWIRE_MASK, 0xFFFFFFFF, }, + { CS42L43_MSM_MASK, 0xFFFFFFFF, }, + { CS42L43_ACC_DET_MASK, 0xFFFFFFFF, }, + { CS42L43_I2C_TGT_MASK, 0xFFFFFFFF, }, + { CS42L43_SPI_MSTR_MASK, 0xFFFFFFFF, }, + { CS42L43_SW_TO_SPI_BRIDGE_MASK, 0xFFFFFFFF, }, + { CS42L43_OTP_MASK, 0xFFFFFFFF, }, + { CS42L43_CLASS_D_AMP_MASK, 0xFFFFFFFF, }, + { CS42L43_GPIO_INT_MASK, 0xFFFFFFFF, }, + { CS42L43_ASRC_MASK, 0xFFFFFFFF, }, + { CS42L43_HPOUT_MASK, 0xFFFFFFFF, }, + }; int ret; - /* - * Don't care about being resumed here, but the driver does want - * force_resume to always trigger an actual resume, so that register - * state for the MCU/GPIOs is returned as soon as possible after system - * resume. force_resume will resume if the reference count is resumed on - * suspend hence the get_noresume. - */ - pm_runtime_get_noresume(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) { + dev_err(cs42l43->dev, "Failed to resume for suspend: %d\n", ret); + return ret; + } + + /* The IRQs will be re-enabled on resume by the cache sync */ + ret = regmap_multi_reg_write_bypassed(cs42l43->regmap, + mask_all, ARRAY_SIZE(mask_all)); + if (ret) { + dev_err(cs42l43->dev, "Failed to mask IRQs: %d\n", ret); + return ret; + } ret = pm_runtime_force_suspend(dev); if (ret) { @@ -1133,6 +1156,26 @@ static int cs42l43_suspend(struct device *dev) if (ret) return ret; + disable_irq(cs42l43->irq); + + return 0; +} + +static int cs42l43_suspend_noirq(struct device *dev) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); + + enable_irq(cs42l43->irq); + + return 0; +} + +static int cs42l43_resume_noirq(struct device *dev) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); + + disable_irq(cs42l43->irq); + return 0; } @@ -1145,6 +1188,8 @@ static int cs42l43_resume(struct device *dev) if (ret) return ret; + enable_irq(cs42l43->irq); + ret = pm_runtime_force_resume(dev); if (ret) { dev_err(cs42l43->dev, "Failed to force resume: %d\n", ret); @@ -1212,6 +1257,7 @@ err: EXPORT_NS_GPL_DEV_PM_OPS(cs42l43_pm_ops, MFD_CS42L43) = { SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume) + NOIRQ_SYSTEM_SLEEP_PM_OPS(cs42l43_suspend_noirq, cs42l43_resume_noirq) RUNTIME_PM_OPS(cs42l43_runtime_suspend, cs42l43_runtime_resume, NULL) }; diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c index 288546214b35..acb0a9187ead 100644 --- a/sound/soc/codecs/cs42l43.c +++ b/sound/soc/codecs/cs42l43.c @@ -2404,49 +2404,7 @@ static int cs42l43_codec_runtime_resume(struct device *dev) return 0; } -static int cs42l43_codec_suspend(struct device *dev) -{ - struct cs42l43_codec *priv = dev_get_drvdata(dev); - struct cs42l43 *cs42l43 = priv->core; - - disable_irq(cs42l43->irq); - - return 0; -} - -static int cs42l43_codec_suspend_noirq(struct device *dev) -{ - struct cs42l43_codec *priv = dev_get_drvdata(dev); - struct cs42l43 *cs42l43 = priv->core; - - enable_irq(cs42l43->irq); - - return 0; -} - -static int cs42l43_codec_resume(struct device *dev) -{ - struct cs42l43_codec *priv = dev_get_drvdata(dev); - struct cs42l43 *cs42l43 = priv->core; - - enable_irq(cs42l43->irq); - - return 0; -} - -static int cs42l43_codec_resume_noirq(struct device *dev) -{ - struct cs42l43_codec *priv = dev_get_drvdata(dev); - struct cs42l43 *cs42l43 = priv->core; - - disable_irq(cs42l43->irq); - - return 0; -} - static const struct dev_pm_ops cs42l43_codec_pm_ops = { - SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend, cs42l43_codec_resume) - NOIRQ_SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend_noirq, cs42l43_codec_resume_noirq) RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL) }; From fccaf34d1737b7bdd5232433e6b27138fcd5b6af Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:44 +0100 Subject: [PATCH 155/256] ASoC: sdw_utils/intel/amd: refactor dai link init logic JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 485df22866559e2f821a9754d51a9755ce56e7aa Author: Vijendar Mukunda Date: Fri Nov 1 07:38:01 2024 +0530 ASoC: sdw_utils/intel/amd: refactor dai link init logic Add 'no_pcm' as parameter for asoc_sdw_init_dai_link() so that same function can be used for SOF and legacy(No DSP) stack. Pass 'no_pcm' as 1 for Intel and AMD SOF based machine drivers. Signed-off-by: Vijendar Mukunda Reviewed-by: Bard Liao Reviewed-by: Liam Girdwood Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241101020802.1103181-2-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/soc_sdw_utils.h | 5 +++-- sound/soc/amd/acp/acp-sdw-sof-mach.c | 8 ++++---- sound/soc/intel/boards/sof_sdw.c | 12 ++++++------ sound/soc/sdw_utils/soc_sdw_utils.c | 9 +++++---- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h index a25f94d6eb67..0e82598e10af 100644 --- a/include/sound/soc_sdw_utils.h +++ b/include/sound/soc_sdw_utils.h @@ -152,14 +152,15 @@ void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_lin struct snd_soc_dai_link_component *cpus, int cpus_num, struct snd_soc_dai_link_component *platform_component, int num_platforms, struct snd_soc_dai_link_component *codecs, - int codecs_num, int (*init)(struct snd_soc_pcm_runtime *rtd), + int codecs_num, int no_pcm, + int (*init)(struct snd_soc_pcm_runtime *rtd), const struct snd_soc_ops *ops); int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, int *be_id, char *name, int playback, int capture, const char *cpu_dai_name, const char *platform_comp_name, int num_platforms, const char *codec_name, - const char *codec_dai_name, + const char *codec_dai_name, int no_pcm, int (*init)(struct snd_soc_pcm_runtime *rtd), const struct snd_soc_ops *ops); diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c index 97176ac01c23..17d3552ba3fc 100644 --- a/sound/soc/amd/acp/acp-sdw-sof-mach.c +++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c @@ -236,7 +236,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture, cpus, num_cpus, platform_component, ARRAY_SIZE(platform_component), codecs, num_codecs, - asoc_sdw_rtd_init, &sdw_ops); + 1, asoc_sdw_rtd_init, &sdw_ops); /* * SoundWire DAILINKs use 'stream' functions and Bank Switch operations @@ -285,7 +285,7 @@ static int create_sdw_dailinks(struct snd_soc_card *card, } static int create_dmic_dailinks(struct snd_soc_card *card, - struct snd_soc_dai_link **dai_links, int *be_id) + struct snd_soc_dai_link **dai_links, int *be_id, int no_pcm) { struct device *dev = card->dev; int ret; @@ -294,7 +294,7 @@ static int create_dmic_dailinks(struct snd_soc_card *card, 0, 1, // DMIC only supports capture "acp-sof-dmic", platform_component->name, ARRAY_SIZE(platform_component), - "dmic-codec", "dmic-hifi", + "dmic-codec", "dmic-hifi", no_pcm, asoc_sdw_dmic_init, NULL); if (ret) return ret; @@ -377,7 +377,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) if (ctx->ignore_internal_dmic) { dev_warn(dev, "Ignoring ACP DMIC\n"); } else { - ret = create_dmic_dailinks(card, &dai_links, &be_id); + ret = create_dmic_dailinks(card, &dai_links, &be_id, 1); if (ret) return ret; } diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 0ec80228a107..9244f2f45f8b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -878,7 +878,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture, cpus, num_cpus, platform_component, ARRAY_SIZE(platform_component), codecs, num_codecs, - asoc_sdw_rtd_init, &sdw_ops); + 1, asoc_sdw_rtd_init, &sdw_ops); /* * SoundWire DAILINKs use 'stream' functions and Bank Switch operations @@ -955,7 +955,7 @@ static int create_ssp_dailinks(struct snd_soc_card *card, playback, capture, cpu_dai_name, platform_component->name, ARRAY_SIZE(platform_component), codec_name, - ssp_info->dais[0].dai_name, NULL, + ssp_info->dais[0].dai_name, 1, NULL, ssp_info->ops); if (ret) return ret; @@ -980,7 +980,7 @@ static int create_dmic_dailinks(struct snd_soc_card *card, 0, 1, // DMIC only supports capture "DMIC01 Pin", platform_component->name, ARRAY_SIZE(platform_component), - "dmic-codec", "dmic-hifi", + "dmic-codec", "dmic-hifi", 1, asoc_sdw_dmic_init, NULL); if (ret) return ret; @@ -991,7 +991,7 @@ static int create_dmic_dailinks(struct snd_soc_card *card, 0, 1, // DMIC only supports capture "DMIC16k Pin", platform_component->name, ARRAY_SIZE(platform_component), - "dmic-codec", "dmic-hifi", + "dmic-codec", "dmic-hifi", 1, /* don't call asoc_sdw_dmic_init() twice */ NULL, NULL); if (ret) @@ -1035,7 +1035,7 @@ static int create_hdmi_dailinks(struct snd_soc_card *card, 1, 0, // HDMI only supports playback cpu_dai_name, platform_component->name, ARRAY_SIZE(platform_component), - codec_name, codec_dai_name, + codec_name, codec_dai_name, 1, i == 0 ? sof_sdw_hdmi_init : NULL, NULL); if (ret) return ret; @@ -1063,7 +1063,7 @@ static int create_bt_dailinks(struct snd_soc_card *card, 1, 1, cpu_dai_name, platform_component->name, ARRAY_SIZE(platform_component), snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name, - NULL, NULL); + 1, NULL, NULL); if (ret) return ret; diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index 6610efe8af18..e7f5938701ef 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -1015,7 +1015,8 @@ void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_lin struct snd_soc_dai_link_component *cpus, int cpus_num, struct snd_soc_dai_link_component *platform_component, int num_platforms, struct snd_soc_dai_link_component *codecs, - int codecs_num, int (*init)(struct snd_soc_pcm_runtime *rtd), + int codecs_num, int no_pcm, + int (*init)(struct snd_soc_pcm_runtime *rtd), const struct snd_soc_ops *ops) { dev_dbg(dev, "create dai link %s, id %d\n", name, *be_id); @@ -1023,7 +1024,7 @@ void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_lin dai_links->name = name; dai_links->platforms = platform_component; dai_links->num_platforms = num_platforms; - dai_links->no_pcm = 1; + dai_links->no_pcm = no_pcm; dai_links->cpus = cpus; dai_links->num_cpus = cpus_num; dai_links->codecs = codecs; @@ -1039,7 +1040,7 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d int *be_id, char *name, int playback, int capture, const char *cpu_dai_name, const char *platform_comp_name, int num_platforms, const char *codec_name, - const char *codec_dai_name, + const char *codec_dai_name, int no_pcm, int (*init)(struct snd_soc_pcm_runtime *rtd), const struct snd_soc_ops *ops) { @@ -1058,7 +1059,7 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d asoc_sdw_init_dai_link(dev, dai_links, be_id, name, playback, capture, &dlc[0], 1, &dlc[1], num_platforms, - &dlc[2], 1, init, ops); + &dlc[2], 1, no_pcm, init, ops); return 0; } From 1c7f193c5a0e63cb394f41510af58125020db234 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:45 +0100 Subject: [PATCH 156/256] ASoC: sdw_utils: Update stream_name in dai_links structure JIRA: https://issues.redhat.com/browse/RHEL-80681 commit d280cf5fbfe3cdd373c98e858834ff87b6ea64de Author: Vijendar Mukunda Date: Fri Nov 1 07:38:02 2024 +0530 ASoC: sdw_utils: Update stream_name in dai_links structure For sof stack, dai_link->stream name will be assigned. For legacy(No DSP enabled) stack, dai_link->stream name should be updated explicitly. Update the stream_name in dai_link structure. Signed-off-by: Vijendar Mukunda Reviewed-by: Bard Liao Reviewed-by: Liam Girdwood Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241101020802.1103181-3-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sdw_utils/soc_sdw_utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index e7f5938701ef..19bd02e2cd6d 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -1022,6 +1022,7 @@ void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_lin dev_dbg(dev, "create dai link %s, id %d\n", name, *be_id); dai_links->id = (*be_id)++; dai_links->name = name; + dai_links->stream_name = name; dai_links->platforms = platform_component; dai_links->num_platforms = num_platforms; dai_links->no_pcm = no_pcm; From d8cff17f8265a0b092e9a29b0847cbbbfc9a8a57 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:45 +0100 Subject: [PATCH 157/256] ASoC: dt-bindings: Add schema for "awinic,aw88081" JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1d534bfb2b2ecec4e67a1667c67169f7a22e46f5 Author: Weidong Wang Date: Thu Oct 24 17:03:23 2024 +0800 ASoC: dt-bindings: Add schema for "awinic,aw88081" Add the awinic,aw88081 property to support the aw88081 chip, which is an I2S/TDM input, high efficiency digital Smart K audio amplifie. Signed-off-by: Weidong Wang Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20241024090324.131731-2-wangweidong.a@awinic.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- Documentation/devicetree/bindings/sound/awinic,aw88395.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml index ac5f2e0f42cb..3b0b743e49c4 100644 --- a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml +++ b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml @@ -17,8 +17,9 @@ description: properties: compatible: enum: - - awinic,aw88395 + - awinic,aw88081 - awinic,aw88261 + - awinic,aw88395 - awinic,aw88399 reg: @@ -56,6 +57,7 @@ allOf: compatible: contains: enum: + - awinic,aw88081 - awinic,aw88261 then: properties: From ac76c160ba05e1ec9f894a6af6cffe7dd170f76c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:45 +0100 Subject: [PATCH 158/256] ASoC: codecs: Add aw88081 amplifier driver JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 88264e4f0b6695245cea2810bf54bebf1c98c070 Author: Weidong Wang Date: Thu Oct 24 17:03:24 2024 +0800 ASoC: codecs: Add aw88081 amplifier driver The driver is for amplifiers aw88081 of Awinic Technology Corporation. The awinic AW88081 is an I2S/TDM input, high efficiency digital Smart K audio amplifier Signed-off-by: Weidong Wang Reviewed-by: anish kumar Link: https://patch.msgid.link/20241024090324.131731-3-wangweidong.a@awinic.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 12 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/aw88081.c | 1087 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/aw88081.h | 286 ++++++++++ 4 files changed, 1387 insertions(+) create mode 100644 sound/soc/codecs/aw88081.c create mode 100644 sound/soc/codecs/aw88081.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index e18289d70263..2e7b9ab67c09 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -57,6 +57,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_AW8738 imply SND_SOC_AW87390 imply SND_SOC_AW88395 + imply SND_SOC_AW88081 imply SND_SOC_AW88261 imply SND_SOC_AW88399 imply SND_SOC_BT_SCO @@ -681,6 +682,17 @@ config SND_SOC_AW88261 boost converter can be adjusted smartly according to the input amplitude. +config SND_SOC_AW88081 + tristate "Soc Audio for awinic aw88081" + depends on I2C + select REGMAP_I2C + select SND_SOC_AW88395_LIB + help + This option enables support for aw88081 Smart PA. + The awinic AW88081 is an I2S/TDM input, high efficiency + digital Smart K audio amplifier. Due to its 9uV noise + floor and ultra-low distortion, clean listening is guaranteed. + config SND_SOC_AW87390 tristate "Soc Audio for awinic aw87390" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index e7912ed26673..135682ae2fa4 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -49,6 +49,7 @@ snd-soc-arizona-y := arizona.o arizona-jack.o snd-soc-audio-iio-aux-y := audio-iio-aux.o snd-soc-aw8738-y := aw8738.o snd-soc-aw87390-y := aw87390.o +snd-soc-aw88081-y := aw88081.o snd-soc-aw88395-lib-y := aw88395/aw88395_lib.o snd-soc-aw88395-y := aw88395/aw88395.o \ aw88395/aw88395_device.o @@ -455,6 +456,7 @@ obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o obj-$(CONFIG_SND_SOC_AUDIO_IIO_AUX) += snd-soc-audio-iio-aux.o obj-$(CONFIG_SND_SOC_AW8738) += snd-soc-aw8738.o obj-$(CONFIG_SND_SOC_AW87390) += snd-soc-aw87390.o +obj-$(CONFIG_SND_SOC_AW88081) += snd-soc-aw88081.o obj-$(CONFIG_SND_SOC_AW88395_LIB) += snd-soc-aw88395-lib.o obj-$(CONFIG_SND_SOC_AW88395) +=snd-soc-aw88395.o obj-$(CONFIG_SND_SOC_AW88261) +=snd-soc-aw88261.o diff --git a/sound/soc/codecs/aw88081.c b/sound/soc/codecs/aw88081.c new file mode 100644 index 000000000000..58b8e002d76f --- /dev/null +++ b/sound/soc/codecs/aw88081.c @@ -0,0 +1,1087 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// aw88081.c -- AW88081 ALSA SoC Audio driver +// +// Copyright (c) 2024 awinic Technology CO., LTD +// +// Author: Weidong Wang +// + +#include +#include +#include +#include +#include "aw88081.h" +#include "aw88395/aw88395_device.h" + +struct aw88081 { + struct aw_device *aw_pa; + struct mutex lock; + struct delayed_work start_work; + struct regmap *regmap; + struct aw_container *aw_cfg; + + bool phase_sync; +}; + +static const struct regmap_config aw88081_regmap_config = { + .val_bits = 16, + .reg_bits = 8, + .max_register = AW88081_REG_MAX, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .val_format_endian = REGMAP_ENDIAN_BIG, +}; + +static int aw88081_dev_get_iis_status(struct aw_device *aw_dev) +{ + unsigned int reg_val; + int ret; + + ret = regmap_read(aw_dev->regmap, AW88081_SYSST_REG, ®_val); + if (ret) + return ret; + if ((reg_val & AW88081_BIT_PLL_CHECK) != AW88081_BIT_PLL_CHECK) { + dev_err(aw_dev->dev, "check pll lock fail,reg_val:0x%04x", reg_val); + return -EINVAL; + } + + return 0; +} + +static int aw88081_dev_check_mode1_pll(struct aw_device *aw_dev) +{ + int ret, i; + + for (i = 0; i < AW88081_DEV_SYSST_CHECK_MAX; i++) { + ret = aw88081_dev_get_iis_status(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "mode1 iis signal check error"); + usleep_range(AW88081_2000_US, AW88081_2000_US + 10); + } else { + return 0; + } + } + + return -EPERM; +} + +static int aw88081_dev_check_mode2_pll(struct aw_device *aw_dev) +{ + unsigned int reg_val; + int ret, i; + + ret = regmap_read(aw_dev->regmap, AW88081_PLLCTRL1_REG, ®_val); + if (ret) + return ret; + + reg_val &= (~AW88081_CCO_MUX_MASK); + if (reg_val == AW88081_CCO_MUX_DIVIDED_VALUE) { + dev_dbg(aw_dev->dev, "CCO_MUX is already divider"); + return -EPERM; + } + + /* change mode2 */ + ret = regmap_update_bits(aw_dev->regmap, AW88081_PLLCTRL1_REG, + ~AW88081_CCO_MUX_MASK, AW88081_CCO_MUX_DIVIDED_VALUE); + if (ret) + return ret; + + for (i = 0; i < AW88081_DEV_SYSST_CHECK_MAX; i++) { + ret = aw88081_dev_get_iis_status(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "mode2 iis check error"); + usleep_range(AW88081_2000_US, AW88081_2000_US + 10); + } else { + break; + } + } + + /* change mode1 */ + ret = regmap_update_bits(aw_dev->regmap, AW88081_PLLCTRL1_REG, + ~AW88081_CCO_MUX_MASK, AW88081_CCO_MUX_BYPASS_VALUE); + if (ret == 0) { + usleep_range(AW88081_2000_US, AW88081_2000_US + 10); + for (i = 0; i < AW88081_DEV_SYSST_CHECK_MAX; i++) { + ret = aw88081_dev_check_mode1_pll(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "mode2 switch to mode1, iis check error"); + usleep_range(AW88081_2000_US, AW88081_2000_US + 10); + } else { + break; + } + } + } + + return ret; +} + +static int aw88081_dev_check_syspll(struct aw_device *aw_dev) +{ + int ret; + + ret = aw88081_dev_check_mode1_pll(aw_dev); + if (ret) { + dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check"); + ret = aw88081_dev_check_mode2_pll(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "mode2 check iis failed"); + return ret; + } + } + + return 0; +} + +static int aw88081_dev_check_sysst(struct aw_device *aw_dev) +{ + unsigned int check_val; + unsigned int reg_val; + unsigned int value; + int ret, i; + + ret = regmap_read(aw_dev->regmap, AW88081_PWMCTRL4_REG, ®_val); + if (ret) + return ret; + + if (reg_val & (~AW88081_NOISE_GATE_EN_MASK)) + check_val = AW88081_NO_SWS_SYSST_CHECK; + else + check_val = AW88081_SWS_SYSST_CHECK; + + for (i = 0; i < AW88081_DEV_SYSST_CHECK_MAX; i++) { + ret = regmap_read(aw_dev->regmap, AW88081_SYSST_REG, ®_val); + if (ret) + return ret; + + value = reg_val & (~AW88081_BIT_SYSST_CHECK_MASK) & check_val; + if (value != check_val) { + dev_err(aw_dev->dev, "check sysst fail, reg_val=0x%04x, check:0x%x", + reg_val, check_val); + usleep_range(AW88081_2000_US, AW88081_2000_US + 10); + } else { + return 0; + } + } + + return -EPERM; +} + +static void aw88081_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag) +{ + if (flag) + regmap_update_bits(aw_dev->regmap, AW88081_I2SCTRL3_REG, + ~AW88081_I2STXEN_MASK, AW88081_I2STXEN_ENABLE_VALUE); + else + regmap_update_bits(aw_dev->regmap, AW88081_I2SCTRL3_REG, + ~AW88081_I2STXEN_MASK, AW88081_I2STXEN_DISABLE_VALUE); +} + +static void aw88081_dev_pwd(struct aw_device *aw_dev, bool pwd) +{ + if (pwd) + regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG, + ~AW88081_PWDN_MASK, AW88081_PWDN_POWER_DOWN_VALUE); + else + regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG, + ~AW88081_PWDN_MASK, AW88081_PWDN_WORKING_VALUE); +} + +static void aw88081_dev_amppd(struct aw_device *aw_dev, bool amppd) +{ + if (amppd) + regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG, + ~AW88081_EN_PA_MASK, AW88081_EN_PA_POWER_DOWN_VALUE); + else + regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG, + ~AW88081_EN_PA_MASK, AW88081_EN_PA_WORKING_VALUE); +} + +static void aw88081_dev_clear_int_status(struct aw_device *aw_dev) +{ + unsigned int int_status; + + /* read int status and clear */ + regmap_read(aw_dev->regmap, AW88081_SYSINT_REG, &int_status); + /* make sure int status is clear */ + regmap_read(aw_dev->regmap, AW88081_SYSINT_REG, &int_status); + + dev_dbg(aw_dev->dev, "read interrupt reg = 0x%04x", int_status); +} + +static void aw88081_dev_set_volume(struct aw_device *aw_dev, unsigned int value) +{ + struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; + unsigned int volume; + + volume = min((value + vol_desc->init_volume), (unsigned int)AW88081_MUTE_VOL); + + regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL2_REG, ~AW88081_VOL_MASK, volume); +} + +static void aw88081_dev_fade_in(struct aw_device *aw_dev) +{ + struct aw_volume_desc *desc = &aw_dev->volume_desc; + int fade_in_vol = desc->ctl_volume; + int fade_step = aw_dev->fade_step; + int i; + + if (fade_step == 0 || aw_dev->fade_in_time == 0) { + aw88081_dev_set_volume(aw_dev, fade_in_vol); + return; + } + + for (i = AW88081_MUTE_VOL; i >= fade_in_vol; i -= fade_step) { + aw88081_dev_set_volume(aw_dev, i); + usleep_range(aw_dev->fade_in_time, aw_dev->fade_in_time + 10); + } + + if (i != fade_in_vol) + aw88081_dev_set_volume(aw_dev, fade_in_vol); +} + +static void aw88081_dev_fade_out(struct aw_device *aw_dev) +{ + struct aw_volume_desc *desc = &aw_dev->volume_desc; + int fade_step = aw_dev->fade_step; + int i; + + if (fade_step == 0 || aw_dev->fade_out_time == 0) { + aw88081_dev_set_volume(aw_dev, AW88081_MUTE_VOL); + return; + } + + for (i = desc->ctl_volume; i <= AW88081_MUTE_VOL; i += fade_step) { + aw88081_dev_set_volume(aw_dev, i); + usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10); + } + + if (i != AW88081_MUTE_VOL) + aw88081_dev_set_volume(aw_dev, AW88081_MUTE_VOL); +} + +static void aw88081_dev_mute(struct aw_device *aw_dev, bool is_mute) +{ + if (is_mute) { + aw88081_dev_fade_out(aw_dev); + regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG, + ~AW88081_HMUTE_MASK, AW88081_HMUTE_ENABLE_VALUE); + } else { + regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG, + ~AW88081_HMUTE_MASK, AW88081_HMUTE_DISABLE_VALUE); + aw88081_dev_fade_in(aw_dev); + } +} + +static void aw88081_dev_uls_hmute(struct aw_device *aw_dev, bool uls_hmute) +{ + if (uls_hmute) + regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG, + ~AW88081_ULS_HMUTE_MASK, + AW88081_ULS_HMUTE_ENABLE_VALUE); + else + regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG, + ~AW88081_ULS_HMUTE_MASK, + AW88081_ULS_HMUTE_DISABLE_VALUE); +} + +static int aw88081_dev_reg_update(struct aw88081 *aw88081, + unsigned char *data, unsigned int len) +{ + struct aw_device *aw_dev = aw88081->aw_pa; + struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; + unsigned int read_vol; + int data_len, i, ret; + int16_t *reg_data; + u16 reg_val; + u8 reg_addr; + + if (!len || !data) { + dev_err(aw_dev->dev, "reg data is null or len is 0"); + return -EINVAL; + } + + reg_data = (int16_t *)data; + data_len = len >> 1; + + if (data_len & 0x1) { + dev_err(aw_dev->dev, "data len:%d unsupported", data_len); + return -EINVAL; + } + + for (i = 0; i < data_len; i += 2) { + reg_addr = reg_data[i]; + reg_val = reg_data[i + 1]; + + if (reg_addr == AW88081_SYSCTRL_REG) { + reg_val &= ~(~AW88081_EN_PA_MASK | + ~AW88081_PWDN_MASK | + ~AW88081_HMUTE_MASK | + ~AW88081_ULS_HMUTE_MASK); + + reg_val |= AW88081_EN_PA_POWER_DOWN_VALUE | + AW88081_PWDN_POWER_DOWN_VALUE | + AW88081_HMUTE_ENABLE_VALUE | + AW88081_ULS_HMUTE_ENABLE_VALUE; + } + + if (reg_addr == AW88081_SYSCTRL2_REG) { + read_vol = (reg_val & (~AW88081_VOL_MASK)) >> + AW88081_VOL_START_BIT; + aw_dev->volume_desc.init_volume = read_vol; + } + + /* i2stxen */ + if (reg_addr == AW88081_I2SCTRL3_REG) { + /* close tx */ + reg_val &= AW88081_I2STXEN_MASK; + reg_val |= AW88081_I2STXEN_DISABLE_VALUE; + } + + ret = regmap_write(aw_dev->regmap, reg_addr, reg_val); + if (ret) + return ret; + } + + if (aw_dev->prof_cur != aw_dev->prof_index) + vol_desc->ctl_volume = 0; + + /* keep min volume */ + aw88081_dev_set_volume(aw_dev, vol_desc->mute_volume); + + return 0; +} + +static int aw88081_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name) +{ + struct aw_prof_info *prof_info = &aw_dev->prof_info; + struct aw_prof_desc *prof_desc; + + if ((index >= aw_dev->prof_info.count) || (index < 0)) { + dev_err(aw_dev->dev, "index[%d] overflow count[%d]", + index, aw_dev->prof_info.count); + return -EINVAL; + } + + prof_desc = &aw_dev->prof_info.prof_desc[index]; + + *prof_name = prof_info->prof_name_list[prof_desc->id]; + + return 0; +} + +static int aw88081_dev_get_prof_data(struct aw_device *aw_dev, int index, + struct aw_prof_desc **prof_desc) +{ + if ((index >= aw_dev->prof_info.count) || (index < 0)) { + dev_err(aw_dev->dev, "%s: index[%d] overflow count[%d]\n", + __func__, index, aw_dev->prof_info.count); + return -EINVAL; + } + + *prof_desc = &aw_dev->prof_info.prof_desc[index]; + + return 0; +} + +static int aw88081_dev_fw_update(struct aw88081 *aw88081) +{ + struct aw_device *aw_dev = aw88081->aw_pa; + struct aw_prof_desc *prof_index_desc; + struct aw_sec_data_desc *sec_desc; + char *prof_name; + int ret; + + ret = aw88081_dev_get_prof_name(aw_dev, aw_dev->prof_index, &prof_name); + if (ret) { + dev_err(aw_dev->dev, "get prof name failed"); + return -EINVAL; + } + + dev_dbg(aw_dev->dev, "start update %s", prof_name); + + ret = aw88081_dev_get_prof_data(aw_dev, aw_dev->prof_index, &prof_index_desc); + if (ret) + return ret; + + /* update reg */ + sec_desc = prof_index_desc->sec_desc; + ret = aw88081_dev_reg_update(aw88081, sec_desc[AW88395_DATA_TYPE_REG].data, + sec_desc[AW88395_DATA_TYPE_REG].len); + if (ret) { + dev_err(aw_dev->dev, "update reg failed"); + return ret; + } + + aw_dev->prof_cur = aw_dev->prof_index; + + return 0; +} + +static int aw88081_dev_start(struct aw88081 *aw88081) +{ + struct aw_device *aw_dev = aw88081->aw_pa; + int ret; + + if (aw_dev->status == AW88081_DEV_PW_ON) { + dev_dbg(aw_dev->dev, "already power on"); + return 0; + } + + /* power on */ + aw88081_dev_pwd(aw_dev, false); + usleep_range(AW88081_2000_US, AW88081_2000_US + 10); + + ret = aw88081_dev_check_syspll(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "pll check failed cannot start"); + goto pll_check_fail; + } + + /* amppd on */ + aw88081_dev_amppd(aw_dev, false); + usleep_range(AW88081_1000_US, AW88081_1000_US + 50); + + /* check i2s status */ + ret = aw88081_dev_check_sysst(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "sysst check failed"); + goto sysst_check_fail; + } + + /* enable tx feedback */ + aw88081_dev_i2s_tx_enable(aw_dev, true); + + /* close uls mute */ + aw88081_dev_uls_hmute(aw_dev, false); + + /* close mute */ + aw88081_dev_mute(aw_dev, false); + + /* clear inturrupt */ + aw88081_dev_clear_int_status(aw_dev); + aw_dev->status = AW88081_DEV_PW_ON; + + return 0; + +sysst_check_fail: + aw88081_dev_i2s_tx_enable(aw_dev, false); + aw88081_dev_clear_int_status(aw_dev); + aw88081_dev_amppd(aw_dev, true); +pll_check_fail: + aw88081_dev_pwd(aw_dev, true); + aw_dev->status = AW88081_DEV_PW_OFF; + + return ret; +} + +static int aw88081_dev_stop(struct aw_device *aw_dev) +{ + if (aw_dev->status == AW88081_DEV_PW_OFF) { + dev_dbg(aw_dev->dev, "already power off"); + return 0; + } + + aw_dev->status = AW88081_DEV_PW_OFF; + + /* clear inturrupt */ + aw88081_dev_clear_int_status(aw_dev); + + aw88081_dev_uls_hmute(aw_dev, true); + /* set mute */ + aw88081_dev_mute(aw_dev, true); + + /* close tx feedback */ + aw88081_dev_i2s_tx_enable(aw_dev, false); + usleep_range(AW88081_1000_US, AW88081_1000_US + 100); + + /* enable amppd */ + aw88081_dev_amppd(aw_dev, true); + + /* set power down */ + aw88081_dev_pwd(aw_dev, true); + + return 0; +} + +static int aw88081_reg_update(struct aw88081 *aw88081, bool force) +{ + struct aw_device *aw_dev = aw88081->aw_pa; + int ret; + + if (force) { + ret = regmap_write(aw_dev->regmap, + AW88081_ID_REG, AW88081_SOFT_RESET_VALUE); + if (ret) + return ret; + + ret = aw88081_dev_fw_update(aw88081); + if (ret) + return ret; + } else { + if (aw_dev->prof_cur != aw_dev->prof_index) { + ret = aw88081_dev_fw_update(aw88081); + if (ret) + return ret; + } + } + + aw_dev->prof_cur = aw_dev->prof_index; + + return 0; +} + +static void aw88081_start_pa(struct aw88081 *aw88081) +{ + int ret, i; + + for (i = 0; i < AW88081_START_RETRIES; i++) { + ret = aw88081_reg_update(aw88081, aw88081->phase_sync); + if (ret) { + dev_err(aw88081->aw_pa->dev, "fw update failed, cnt:%d\n", i); + continue; + } + ret = aw88081_dev_start(aw88081); + if (ret) { + dev_err(aw88081->aw_pa->dev, "aw88081 device start failed. retry = %d", i); + continue; + } else { + dev_dbg(aw88081->aw_pa->dev, "start success\n"); + break; + } + } +} + +static void aw88081_startup_work(struct work_struct *work) +{ + struct aw88081 *aw88081 = + container_of(work, struct aw88081, start_work.work); + + mutex_lock(&aw88081->lock); + aw88081_start_pa(aw88081); + mutex_unlock(&aw88081->lock); +} + +static void aw88081_start(struct aw88081 *aw88081, bool sync_start) +{ + if (aw88081->aw_pa->fw_status != AW88081_DEV_FW_OK) + return; + + if (aw88081->aw_pa->status == AW88081_DEV_PW_ON) + return; + + if (sync_start == AW88081_SYNC_START) + aw88081_start_pa(aw88081); + else + queue_delayed_work(system_wq, + &aw88081->start_work, + AW88081_START_WORK_DELAY_MS); +} + +static struct snd_soc_dai_driver aw88081_dai[] = { + { + .name = "aw88081-aif", + .id = 1, + .playback = { + .stream_name = "Speaker_Playback", + .channels_min = 1, + .channels_max = 2, + .rates = AW88081_RATES, + .formats = AW88081_FORMATS, + }, + .capture = { + .stream_name = "Speaker_Capture", + .channels_min = 1, + .channels_max = 2, + .rates = AW88081_RATES, + .formats = AW88081_FORMATS, + }, + }, +}; + +static int aw88081_get_fade_in_time(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component); + struct aw_device *aw_dev = aw88081->aw_pa; + + ucontrol->value.integer.value[0] = aw_dev->fade_in_time; + + return 0; +} + +static int aw88081_set_fade_in_time(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct aw_device *aw_dev = aw88081->aw_pa; + int time; + + time = ucontrol->value.integer.value[0]; + + if (time < mc->min || time > mc->max) + return -EINVAL; + + if (time != aw_dev->fade_in_time) { + aw_dev->fade_in_time = time; + return 1; + } + + return 0; +} + +static int aw88081_get_fade_out_time(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component); + struct aw_device *aw_dev = aw88081->aw_pa; + + ucontrol->value.integer.value[0] = aw_dev->fade_out_time; + + return 0; +} + +static int aw88081_set_fade_out_time(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct aw_device *aw_dev = aw88081->aw_pa; + int time; + + time = ucontrol->value.integer.value[0]; + if (time < mc->min || time > mc->max) + return -EINVAL; + + if (time != aw_dev->fade_out_time) { + aw_dev->fade_out_time = time; + return 1; + } + + return 0; +} + +static int aw88081_dev_set_profile_index(struct aw_device *aw_dev, int index) +{ + /* check the index whether is valid */ + if ((index >= aw_dev->prof_info.count) || (index < 0)) + return -EINVAL; + /* check the index whether change */ + if (aw_dev->prof_index == index) + return -EPERM; + + aw_dev->prof_index = index; + + return 0; +} + +static int aw88081_profile_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec); + char *prof_name; + int count, ret; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + + count = aw88081->aw_pa->prof_info.count; + if (count <= 0) { + uinfo->value.enumerated.items = 0; + return 0; + } + + uinfo->value.enumerated.items = count; + + if (uinfo->value.enumerated.item >= count) + uinfo->value.enumerated.item = count - 1; + + count = uinfo->value.enumerated.item; + + ret = aw88081_dev_get_prof_name(aw88081->aw_pa, count, &prof_name); + if (ret) { + strscpy(uinfo->value.enumerated.name, "null", + sizeof(uinfo->value.enumerated.name)); + return 0; + } + + strscpy(uinfo->value.enumerated.name, prof_name, sizeof(uinfo->value.enumerated.name)); + + return 0; +} + +static int aw88081_profile_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec); + + ucontrol->value.integer.value[0] = aw88081->aw_pa->prof_index; + + return 0; +} + +static int aw88081_profile_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec); + int ret; + + /* pa stop or stopping just set profile */ + mutex_lock(&aw88081->lock); + ret = aw88081_dev_set_profile_index(aw88081->aw_pa, ucontrol->value.integer.value[0]); + if (ret) { + dev_dbg(codec->dev, "profile index does not change"); + mutex_unlock(&aw88081->lock); + return 0; + } + + if (aw88081->aw_pa->status) { + aw88081_dev_stop(aw88081->aw_pa); + aw88081_start(aw88081, AW88081_SYNC_START); + } + + mutex_unlock(&aw88081->lock); + + return 1; +} + +static int aw88081_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec); + struct aw_volume_desc *vol_desc = &aw88081->aw_pa->volume_desc; + + ucontrol->value.integer.value[0] = vol_desc->ctl_volume; + + return 0; +} + +static int aw88081_volume_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec); + struct aw_volume_desc *vol_desc = &aw88081->aw_pa->volume_desc; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int value; + + value = ucontrol->value.integer.value[0]; + + if (value < mc->min || value > mc->max) + return -EINVAL; + + if (vol_desc->ctl_volume != value) { + vol_desc->ctl_volume = value; + aw88081_dev_set_volume(aw88081->aw_pa, vol_desc->ctl_volume); + return 1; + } + + return 0; +} + +static int aw88081_get_fade_step(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec); + + ucontrol->value.integer.value[0] = aw88081->aw_pa->fade_step; + + return 0; +} + +static int aw88081_set_fade_step(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int value; + + value = ucontrol->value.integer.value[0]; + if (value < mc->min || value > mc->max) + return -EINVAL; + + if (aw88081->aw_pa->fade_step != value) { + aw88081->aw_pa->fade_step = value; + return 1; + } + + return 0; +} + +static const struct snd_kcontrol_new aw88081_controls[] = { + SOC_SINGLE_EXT("PCM Playback Volume", AW88081_SYSCTRL2_REG, + 0, AW88081_MUTE_VOL, 0, aw88081_volume_get, + aw88081_volume_set), + SOC_SINGLE_EXT("Fade Step", 0, 0, AW88081_MUTE_VOL, 0, + aw88081_get_fade_step, aw88081_set_fade_step), + SOC_SINGLE_EXT("Volume Ramp Up Step", 0, 0, FADE_TIME_MAX, 0, + aw88081_get_fade_in_time, aw88081_set_fade_in_time), + SOC_SINGLE_EXT("Volume Ramp Down Step", 0, 0, FADE_TIME_MAX, 0, + aw88081_get_fade_out_time, aw88081_set_fade_out_time), + AW88081_PROFILE_EXT("Profile Set", aw88081_profile_info, + aw88081_profile_get, aw88081_profile_set), +}; + +static void aw88081_parse_channel_dt(struct aw88081 *aw88081) +{ + struct aw_device *aw_dev = aw88081->aw_pa; + struct device_node *np = aw_dev->dev->of_node; + u32 channel_value = AW88081_DEV_DEFAULT_CH; + + of_property_read_u32(np, "awinic,audio-channel", &channel_value); + aw88081->phase_sync = of_property_read_bool(np, "awinic,sync-flag"); + + aw_dev->channel = channel_value; +} + +static int aw88081_init(struct aw88081 *aw88081, struct i2c_client *i2c, struct regmap *regmap) +{ + struct aw_device *aw_dev; + unsigned int chip_id; + int ret; + + /* read chip id */ + ret = regmap_read(regmap, AW88081_ID_REG, &chip_id); + if (ret) { + dev_err(&i2c->dev, "%s read chipid error. ret = %d", __func__, ret); + return ret; + } + if (chip_id != AW88081_CHIP_ID) { + dev_err(&i2c->dev, "unsupported device"); + return -ENXIO; + } + + dev_dbg(&i2c->dev, "chip id = %x\n", chip_id); + + aw_dev = devm_kzalloc(&i2c->dev, sizeof(*aw_dev), GFP_KERNEL); + if (!aw_dev) + return -ENOMEM; + + aw88081->aw_pa = aw_dev; + aw_dev->i2c = i2c; + aw_dev->regmap = regmap; + aw_dev->dev = &i2c->dev; + aw_dev->chip_id = AW88081_CHIP_ID; + aw_dev->acf = NULL; + aw_dev->prof_info.prof_desc = NULL; + aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID; + aw_dev->fade_step = AW88081_VOLUME_STEP_DB; + aw_dev->volume_desc.mute_volume = AW88081_MUTE_VOL; + aw88081_parse_channel_dt(aw88081); + + return 0; +} + +static int aw88081_dev_init(struct aw88081 *aw88081, struct aw_container *aw_cfg) +{ + struct aw_device *aw_dev = aw88081->aw_pa; + int ret; + + ret = aw88395_dev_cfg_load(aw_dev, aw_cfg); + if (ret) { + dev_err(aw_dev->dev, "aw_dev acf parse failed"); + return -EINVAL; + } + + ret = regmap_write(aw_dev->regmap, AW88081_ID_REG, AW88081_SOFT_RESET_VALUE); + if (ret) + return ret; + + aw_dev->fade_in_time = AW88081_500_US; + aw_dev->fade_out_time = AW88081_500_US; + aw_dev->prof_cur = AW88081_INIT_PROFILE; + aw_dev->prof_index = AW88081_INIT_PROFILE; + + ret = aw88081_dev_fw_update(aw88081); + if (ret) { + dev_err(aw_dev->dev, "fw update failed ret = %d\n", ret); + return ret; + } + + aw88081_dev_clear_int_status(aw_dev); + + aw88081_dev_uls_hmute(aw_dev, true); + + aw88081_dev_mute(aw_dev, true); + + usleep_range(AW88081_5000_US, AW88081_5000_US + 10); + + aw88081_dev_i2s_tx_enable(aw_dev, false); + + usleep_range(AW88081_1000_US, AW88081_1000_US + 100); + + aw88081_dev_amppd(aw_dev, true); + + aw88081_dev_pwd(aw_dev, true); + + return 0; +} + +static int aw88081_request_firmware_file(struct aw88081 *aw88081) +{ + const struct firmware *cont = NULL; + int ret; + + aw88081->aw_pa->fw_status = AW88081_DEV_FW_FAILED; + + ret = request_firmware(&cont, AW88081_ACF_FILE, aw88081->aw_pa->dev); + if (ret) + return ret; + + dev_dbg(aw88081->aw_pa->dev, "loaded %s - size: %zu\n", + AW88081_ACF_FILE, cont ? cont->size : 0); + + aw88081->aw_cfg = devm_kzalloc(aw88081->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL); + if (!aw88081->aw_cfg) { + release_firmware(cont); + return -ENOMEM; + } + aw88081->aw_cfg->len = (int)cont->size; + memcpy(aw88081->aw_cfg->data, cont->data, cont->size); + release_firmware(cont); + + ret = aw88395_dev_load_acf_check(aw88081->aw_pa, aw88081->aw_cfg); + if (ret) + return ret; + + mutex_lock(&aw88081->lock); + ret = aw88081_dev_init(aw88081, aw88081->aw_cfg); + mutex_unlock(&aw88081->lock); + + return ret; +} + +static int aw88081_playback_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component); + + mutex_lock(&aw88081->lock); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + aw88081_start(aw88081, AW88081_ASYNC_START); + break; + case SND_SOC_DAPM_POST_PMD: + aw88081_dev_stop(aw88081->aw_pa); + break; + default: + break; + } + mutex_unlock(&aw88081->lock); + + return 0; +} + +static const struct snd_soc_dapm_widget aw88081_dapm_widgets[] = { + /* playback */ + SND_SOC_DAPM_AIF_IN_E("AIF_RX", "Speaker_Playback", 0, SND_SOC_NOPM, 0, 0, + aw88081_playback_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUTPUT("DAC Output"), + + /* capture */ + SND_SOC_DAPM_AIF_OUT("AIF_TX", "Speaker_Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_INPUT("ADC Input"), +}; + +static const struct snd_soc_dapm_route aw88081_audio_map[] = { + {"DAC Output", NULL, "AIF_RX"}, + {"AIF_TX", NULL, "ADC Input"}, +}; + +static int aw88081_codec_probe(struct snd_soc_component *component) +{ + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component); + int ret; + + INIT_DELAYED_WORK(&aw88081->start_work, aw88081_startup_work); + + ret = aw88081_request_firmware_file(aw88081); + if (ret) + dev_err(aw88081->aw_pa->dev, "%s: request firmware failed\n", __func__); + + return ret; +} + +static void aw88081_codec_remove(struct snd_soc_component *aw_codec) +{ + struct aw88081 *aw88081 = snd_soc_component_get_drvdata(aw_codec); + + cancel_delayed_work_sync(&aw88081->start_work); +} + +static const struct snd_soc_component_driver soc_codec_dev_aw88081 = { + .probe = aw88081_codec_probe, + .remove = aw88081_codec_remove, + .dapm_widgets = aw88081_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aw88081_dapm_widgets), + .dapm_routes = aw88081_audio_map, + .num_dapm_routes = ARRAY_SIZE(aw88081_audio_map), + .controls = aw88081_controls, + .num_controls = ARRAY_SIZE(aw88081_controls), +}; + +static int aw88081_i2c_probe(struct i2c_client *i2c) +{ + struct aw88081 *aw88081; + int ret; + + ret = i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C); + if (!ret) + return dev_err_probe(&i2c->dev, -ENXIO, "check_functionality failed"); + + aw88081 = devm_kzalloc(&i2c->dev, sizeof(*aw88081), GFP_KERNEL); + if (!aw88081) + return -ENOMEM; + + mutex_init(&aw88081->lock); + + i2c_set_clientdata(i2c, aw88081); + + aw88081->regmap = devm_regmap_init_i2c(i2c, &aw88081_regmap_config); + if (IS_ERR(aw88081->regmap)) + return dev_err_probe(&i2c->dev, PTR_ERR(aw88081->regmap), + "failed to init regmap\n"); + + /* aw pa init */ + ret = aw88081_init(aw88081, i2c, aw88081->regmap); + if (ret) + return ret; + + return devm_snd_soc_register_component(&i2c->dev, + &soc_codec_dev_aw88081, + aw88081_dai, ARRAY_SIZE(aw88081_dai)); +} + +static const struct i2c_device_id aw88081_i2c_id[] = { + { AW88081_I2C_NAME }, + { } +}; +MODULE_DEVICE_TABLE(i2c, aw88081_i2c_id); + +static struct i2c_driver aw88081_i2c_driver = { + .driver = { + .name = AW88081_I2C_NAME, + }, + .probe = aw88081_i2c_probe, + .id_table = aw88081_i2c_id, +}; +module_i2c_driver(aw88081_i2c_driver); + +MODULE_DESCRIPTION("ASoC AW88081 Smart PA Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/aw88081.h b/sound/soc/codecs/aw88081.h new file mode 100644 index 000000000000..b4bf7288021a --- /dev/null +++ b/sound/soc/codecs/aw88081.h @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// aw88081.h -- AW88081 ALSA SoC Audio driver +// +// Copyright (c) 2024 awinic Technology CO., LTD +// +// Author: Weidong Wang +// + +#ifndef __AW88081_H__ +#define __AW88081_H__ + +#define AW88081_ID_REG (0x00) +#define AW88081_SYSST_REG (0x01) +#define AW88081_SYSINT_REG (0x02) +#define AW88081_SYSINTM_REG (0x03) +#define AW88081_SYSCTRL_REG (0x04) +#define AW88081_SYSCTRL2_REG (0x05) +#define AW88081_I2SCTRL1_REG (0x06) +#define AW88081_I2SCTRL2_REG (0x07) +#define AW88081_I2SCTRL3_REG (0x08) +#define AW88081_DACCFG1_REG (0x09) +#define AW88081_DACCFG2_REG (0x0A) +#define AW88081_DACCFG3_REG (0x0B) +#define AW88081_DACCFG4_REG (0x0C) +#define AW88081_DACCFG5_REG (0x0D) +#define AW88081_DACCFG6_REG (0x0E) +#define AW88081_DACCFG7_REG (0x11) +#define AW88081_PWMCTRL1_REG (0x13) +#define AW88081_PWMCTRL2_REG (0x14) +#define AW88081_PWMCTRL3_REG (0x15) +#define AW88081_PWMCTRL4_REG (0x16) +#define AW88081_I2SCFG1_REG (0x17) +#define AW88081_DBGCTRL_REG (0x18) +#define AW88081_PDMCTRL_REG (0x19) +#define AW88081_DACST_REG (0x20) +#define AW88081_PATTERNST_REG (0x21) +#define AW88081_I2SINT_REG (0x26) +#define AW88081_I2SCAPCNT_REG (0x27) +#define AW88081_ANASTA1_REG (0x28) +#define AW88081_ANASTA2_REG (0x29) +#define AW88081_ANASTA3_REG (0x2A) +#define AW88081_VBAT_REG (0x21) +#define AW88081_TEMP_REG (0x22) +#define AW88081_PVDD_REG (0x23) +#define AW88081_ISNDAT_REG (0x24) +#define AW88081_VSNDAT_REG (0x25) +#define AW88081_DSMCFG1_REG (0x30) +#define AW88081_DSMCFG2_REG (0x31) +#define AW88081_DSMCFG3_REG (0x32) +#define AW88081_DSMCFG4_REG (0x33) +#define AW88081_DSMCFG5_REG (0x34) +#define AW88081_DSMCFG6_REG (0x35) +#define AW88081_DSMCFG7_REG (0x36) +#define AW88081_DSMCFG8_REG (0x37) +#define AW88081_TESTIN_REG (0x38) +#define AW88081_TESTOUT_REG (0x39) +#define AW88081_BOPCTRL1_REG (0x40) +#define AW88081_BOPCTRL2_REG (0x41) +#define AW88081_BOPCTRL3_REG (0x42) +#define AW88081_BOPSTA_REG (0x43) +#define AW88081_PLLCTRL1_REG (0x54) +#define AW88081_PLLCTRL2_REG (0x55) +#define AW88081_PLLCTRL3_REG (0x56) +#define AW88081_CDACTRL1_REG (0x57) +#define AW88081_CDACTRL2_REG (0x58) +#define AW88081_CDACTRL3_REG (0x59) +#define AW88081_DITHERCFG1_REG (0x5A) +#define AW88081_DITHERCFG2_REG (0x5B) +#define AW88081_DITHERCFG3_REG (0x5C) +#define AW88081_TM_REG (0x6E) +#define AW88081_TM2_REG (0x6F) +#define AW88081_TESTCTRL1_REG (0x70) +#define AW88081_TESTCTRL2_REG (0x71) + +#define AW88081_REG_MAX (0x72) + +#define AW88081_UVLS_START_BIT (14) +#define AW88081_UVLS_UVLO (1) +#define AW88081_UVLS_UVLO_VALUE \ + (AW88081_UVLS_UVLO << AW88081_UVLS_START_BIT) + +#define AW88081_SWS_START_BIT (8) +#define AW88081_SWS_SWITCHING (1) +#define AW88081_SWS_SWITCHING_VALUE \ + (AW88081_SWS_SWITCHING << AW88081_SWS_START_BIT) + +#define AW88081_NOCLKS_START_BIT (5) +#define AW88081_NOCLKS_NO_CLOCK (1) +#define AW88081_NOCLKS_NO_CLOCK_VALUE \ + (AW88081_NOCLKS_NO_CLOCK << AW88081_NOCLKS_START_BIT) + +#define AW88081_CLKS_START_BIT (4) +#define AW88081_CLKS_STABLE (1) +#define AW88081_CLKS_STABLE_VALUE \ + (AW88081_CLKS_STABLE << AW88081_CLKS_START_BIT) + +#define AW88081_OCDS_START_BIT (3) +#define AW88081_OCDS_OC (1) +#define AW88081_OCDS_OC_VALUE \ + (AW88081_OCDS_OC << AW88081_OCDS_START_BIT) + +#define AW88081_OTHS_START_BIT (1) +#define AW88081_OTHS_OT (1) +#define AW88081_OTHS_OT_VALUE \ + (AW88081_OTHS_OT << AW88081_OTHS_START_BIT) + +#define AW88081_PLLS_START_BIT (0) +#define AW88081_PLLS_LOCKED (1) +#define AW88081_PLLS_LOCKED_VALUE \ + (AW88081_PLLS_LOCKED << AW88081_PLLS_START_BIT) + +#define AW88081_BIT_PLL_CHECK \ + (AW88081_CLKS_STABLE_VALUE | \ + AW88081_PLLS_LOCKED_VALUE) + +#define AW88081_BIT_SYSST_CHECK_MASK \ + (~(AW88081_UVLS_UVLO_VALUE | \ + AW88081_SWS_SWITCHING_VALUE | \ + AW88081_NOCLKS_NO_CLOCK_VALUE | \ + AW88081_CLKS_STABLE_VALUE | \ + AW88081_OCDS_OC_VALUE | \ + AW88081_OTHS_OT_VALUE | \ + AW88081_PLLS_LOCKED_VALUE)) + +#define AW88081_NO_SWS_SYSST_CHECK \ + (AW88081_CLKS_STABLE_VALUE | \ + AW88081_PLLS_LOCKED_VALUE) + +#define AW88081_SWS_SYSST_CHECK \ + (AW88081_SWS_SWITCHING_VALUE | \ + AW88081_CLKS_STABLE_VALUE | \ + AW88081_PLLS_LOCKED_VALUE) + +#define AW88081_ULS_HMUTE_START_BIT (14) +#define AW88081_ULS_HMUTE_BITS_LEN (1) +#define AW88081_ULS_HMUTE_MASK \ + (~(((1< Date: Mon, 17 Mar 2025 13:42:45 +0100 Subject: [PATCH 159/256] ASoC: rename rtd->num to rtd->id JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 40e47e2db6864aa053a62477bd71a16be9dd4066 Author: Kuninori Morimoto Date: Thu Oct 24 01:29:13 2024 +0000 ASoC: rename rtd->num to rtd->id Current rtd has "num". It sounds/looks like size of rtd or something, but it will be mainly used at snd_pcm_new() as "device index". This naming is confusable. Let's rename it to "id" Some drivers are using rtd->num, so let's keep it so far, and remove it if all user was switched. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87zfmub85z.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/soc-dai.h | 4 ++-- include/sound/soc.h | 9 +++++---- sound/soc/soc-compress.c | 10 +++++----- sound/soc/soc-core.c | 15 ++++++++------- sound/soc/soc-dai.c | 4 ++-- sound/soc/soc-pcm.c | 16 ++++++++-------- 6 files changed, 30 insertions(+), 28 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 0d1b215f24f4..9dbeedf6da13 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -217,7 +217,7 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); int snd_soc_dai_compress_new(struct snd_soc_dai *dai, - struct snd_soc_pcm_runtime *rtd, int num); + struct snd_soc_pcm_runtime *rtd, int id); bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int stream); void snd_soc_dai_action(struct snd_soc_dai *dai, int stream, int action); @@ -275,7 +275,7 @@ struct snd_soc_dai_ops { int (*probe)(struct snd_soc_dai *dai); int (*remove)(struct snd_soc_dai *dai); /* compress dai */ - int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num); + int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int id); /* Optional Callback used at pcm creation*/ int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); diff --git a/include/sound/soc.h b/include/sound/soc.h index 4af0302667be..e70e69c5afb4 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -476,11 +476,11 @@ struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, struct snd_soc_component *snd_soc_lookup_component(struct device *dev, const char *driver_name); -int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); +int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int id); #ifdef CONFIG_SND_SOC_COMPRESS -int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num); +int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int id); #else -static inline int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) +static inline int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int id) { return 0; } @@ -1185,7 +1185,8 @@ struct snd_soc_pcm_runtime { struct dentry *debugfs_dpcm_root; #endif - unsigned int num; /* 0-based and monotonic increasing */ + unsigned int num; /* REMOVE ME */ + unsigned int id; /* 0-based and monotonic increasing */ struct list_head list; /* rtd list of the soc card */ /* function mark */ diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index a0c55246f424..fb664c775dda 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -537,11 +537,11 @@ static struct snd_compr_ops soc_compr_dyn_ops = { * snd_soc_new_compress - create a new compress. * * @rtd: The runtime for which we will create compress - * @num: the device index number (zero based - shared with normal PCMs) + * @id: the device index number (zero based - shared with normal PCMs) * * Return: 0 for success, else error. */ -int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) +int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int id) { struct snd_soc_component *component; struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); @@ -617,7 +617,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) snprintf(new_name, sizeof(new_name), "(%s)", rtd->dai_link->stream_name); - ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, + ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, id, playback, capture, &be_pcm); if (ret < 0) { dev_err(rtd->card->dev, @@ -638,7 +638,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); } else { snprintf(new_name, sizeof(new_name), "%s %s-%d", - rtd->dai_link->stream_name, codec_dai->name, num); + rtd->dai_link->stream_name, codec_dai->name, id); memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); } @@ -652,7 +652,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) break; } - ret = snd_compress_new(rtd->card->snd_card, num, direction, + ret = snd_compress_new(rtd->card->snd_card, id, direction, new_name, compr); if (ret < 0) { component = snd_soc_rtd_to_codec(rtd, 0)->component; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f04b671ce33e..3cb748279166 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -558,7 +558,8 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( */ rtd->card = card; rtd->dai_link = dai_link; - rtd->num = card->num_rtd++; + rtd->id = card->num_rtd++; + rtd->num = rtd->id; /* REMOVE ME */ rtd->pmdown_time = pmdown_time; /* default power off timeout */ /* see for_each_card_rtds */ @@ -1458,7 +1459,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_component *component; - int ret, num, i; + int ret, id, i; /* do machine specific initialization */ ret = snd_soc_link_init(rtd); @@ -1473,7 +1474,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, /* add DPCM sysfs entries */ soc_dpcm_debugfs_add(rtd); - num = rtd->num; + id = rtd->id; /* * most drivers will register their PCMs using DAI link ordering but @@ -1485,18 +1486,18 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, continue; if (rtd->dai_link->no_pcm) - num += component->driver->be_pcm_base; + id += component->driver->be_pcm_base; else - num = rtd->dai_link->id; + id = rtd->dai_link->id; } /* create compress_device if possible */ - ret = snd_soc_dai_compress_new(cpu_dai, rtd, num); + ret = snd_soc_dai_compress_new(cpu_dai, rtd, id); if (ret != -ENOTSUPP) goto err; /* create the pcm */ - ret = soc_new_pcm(rtd, num); + ret = soc_new_pcm(rtd, id); if (ret < 0) { dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", dai_link->stream_name, ret); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 4a1c85ad5a8d..2feb76bf57bb 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -457,12 +457,12 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, } int snd_soc_dai_compress_new(struct snd_soc_dai *dai, - struct snd_soc_pcm_runtime *rtd, int num) + struct snd_soc_pcm_runtime *rtd, int id) { int ret = -ENOTSUPP; if (dai->driver->ops && dai->driver->ops->compress_new) - ret = dai->driver->ops->compress_new(rtd, num); + ret = dai->driver->ops->compress_new(rtd, id); return soc_dai_ret(dai, ret); } diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 678400e76e53..81b63e547a09 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2891,7 +2891,7 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, static int soc_create_pcm(struct snd_pcm **pcm, struct snd_soc_pcm_runtime *rtd, - int playback, int capture, int num) + int playback, int capture, int id) { char new_name[64]; int ret; @@ -2901,13 +2901,13 @@ static int soc_create_pcm(struct snd_pcm **pcm, snprintf(new_name, sizeof(new_name), "codec2codec(%s)", rtd->dai_link->stream_name); - ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, + ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, id, playback, capture, pcm); } else if (rtd->dai_link->no_pcm) { snprintf(new_name, sizeof(new_name), "(%s)", rtd->dai_link->stream_name); - ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, + ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, id, playback, capture, pcm); } else { if (rtd->dai_link->dynamic) @@ -2916,9 +2916,9 @@ static int soc_create_pcm(struct snd_pcm **pcm, else snprintf(new_name, sizeof(new_name), "%s %s-%d", rtd->dai_link->stream_name, - soc_codec_dai_name(rtd), num); + soc_codec_dai_name(rtd), id); - ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback, + ret = snd_pcm_new(rtd->card->snd_card, new_name, id, playback, capture, pcm); } if (ret < 0) { @@ -2926,13 +2926,13 @@ static int soc_create_pcm(struct snd_pcm **pcm, new_name, rtd->dai_link->name, ret); return ret; } - dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name); + dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n", id, new_name); return 0; } /* create a new pcm */ -int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) +int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int id) { struct snd_soc_component *component; struct snd_pcm *pcm; @@ -2943,7 +2943,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (ret < 0) return ret; - ret = soc_create_pcm(&pcm, rtd, playback, capture, num); + ret = soc_create_pcm(&pcm, rtd, playback, capture, id); if (ret < 0) return ret; From 27f6473b2b67ec6eed6cbcb7ed41d430addaa095 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:45 +0100 Subject: [PATCH 160/256] ASoC: fsl: switch to use rtd->id from rtd->num JIRA: https://issues.redhat.com/browse/RHEL-80681 commit eae33f737c7a929d92b559fe1a1002d597b7b903 Author: Kuninori Morimoto Date: Thu Oct 24 01:29:20 2024 +0000 ASoC: fsl: switch to use rtd->id from rtd->num Now rtd->num is renamed to rtd->id. Let's switch. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87y12eb85r.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/fsl/imx-card.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index 306168b164d3..20ab30619b5b 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -275,7 +275,7 @@ static unsigned long akcodec_get_mclk_rate(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct imx_card_data *data = snd_soc_card_get_drvdata(rtd->card); const struct imx_card_plat_data *plat_data = data->plat_data; - struct dai_link_data *link_data = &data->link_data[rtd->num]; + struct dai_link_data *link_data = &data->link_data[rtd->id]; unsigned int width = slots * slot_width; unsigned int rate = params_rate(params); int i; @@ -313,7 +313,7 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_card *card = rtd->card; struct imx_card_data *data = snd_soc_card_get_drvdata(card); - struct dai_link_data *link_data = &data->link_data[rtd->num]; + struct dai_link_data *link_data = &data->link_data[rtd->id]; struct imx_card_plat_data *plat_data = data->plat_data; struct device *dev = card->dev; struct snd_soc_dai *codec_dai; @@ -435,7 +435,7 @@ static int imx_aif_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct imx_card_data *data = snd_soc_card_get_drvdata(card); - struct dai_link_data *link_data = &data->link_data[rtd->num]; + struct dai_link_data *link_data = &data->link_data[rtd->id]; static struct snd_pcm_hw_constraint_list constraint_rates; static struct snd_pcm_hw_constraint_list constraint_channels; int ret = 0; From 915ca3cc92d3ea4c654628f92c066c7e9ba3547e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:45 +0100 Subject: [PATCH 161/256] ASoC: meson: switch to use rtd->id from rtd->num JIRA: https://issues.redhat.com/browse/RHEL-80681 commit b19f75df8fa9f8d4aa8b5886dca0f2d832a76baa Author: Kuninori Morimoto Date: Thu Oct 24 01:29:27 2024 +0000 ASoC: meson: switch to use rtd->id from rtd->num Now rtd->num is renamed to rtd->id. Let's switch. Signed-off-by: Kuninori Morimoto Acked-by: Jerome Brunet Link: https://patch.msgid.link/87wmhyb85l.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/meson/axg-card.c | 6 +++--- sound/soc/meson/gx-card.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index ac5dbd5dc6d2..83ed4e387eaf 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -43,7 +43,7 @@ static int axg_card_tdm_be_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct axg_dai_link_tdm_data *be = - (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; + (struct axg_dai_link_tdm_data *)priv->link_data[rtd->id]; return meson_card_i2s_set_sysclk(substream, params, be->mclk_fs); } @@ -56,7 +56,7 @@ static int axg_card_tdm_dai_init(struct snd_soc_pcm_runtime *rtd) { struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct axg_dai_link_tdm_data *be = - (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; + (struct axg_dai_link_tdm_data *)priv->link_data[rtd->id]; struct snd_soc_dai *codec_dai; int ret, i; @@ -86,7 +86,7 @@ static int axg_card_tdm_dai_lb_init(struct snd_soc_pcm_runtime *rtd) { struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct axg_dai_link_tdm_data *be = - (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; + (struct axg_dai_link_tdm_data *)priv->link_data[rtd->id]; int ret; /* The loopback rx_mask is the pad tx_mask */ diff --git a/sound/soc/meson/gx-card.c b/sound/soc/meson/gx-card.c index c9ded8d3cb03..537605028158 100644 --- a/sound/soc/meson/gx-card.c +++ b/sound/soc/meson/gx-card.c @@ -32,7 +32,7 @@ static int gx_card_i2s_be_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct gx_dai_link_i2s_data *be = - (struct gx_dai_link_i2s_data *)priv->link_data[rtd->num]; + (struct gx_dai_link_i2s_data *)priv->link_data[rtd->id]; return meson_card_i2s_set_sysclk(substream, params, be->mclk_fs); } From ab8701f855cab62032050088d3ffdd733f38dc81 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:46 +0100 Subject: [PATCH 162/256] ASoC: sh: switch to use rtd->id from rtd->num JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 970a874b76d09d6a5880e8832e572850cfcb4008 Author: Kuninori Morimoto Date: Thu Oct 24 01:29:34 2024 +0000 ASoC: sh: switch to use rtd->id from rtd->num Now rtd->num is renamed to rtd->id. Let's switch. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87v7xib85e.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sh/rcar/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 6fd647edba58..c2a142c4dbe8 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1769,7 +1769,7 @@ int rsnd_kctrl_new(struct rsnd_mod *mod, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = name, .info = rsnd_kctrl_info, - .index = rtd->num, + .index = rtd->id, .get = rsnd_kctrl_get, .put = rsnd_kctrl_put, }; From 13d35423254cbd7adebf88ef6ac4e0836f3fbddb Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:46 +0100 Subject: [PATCH 163/256] ASoC: generic: switch to use rtd->id from rtd->num JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 742e622db67efc32affb5893fdcc0149f374533e Author: Kuninori Morimoto Date: Thu Oct 24 01:29:39 2024 +0000 ASoC: generic: switch to use rtd->id from rtd->num Now rtd->num is renamed to rtd->id. Let's switch. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ttd2b858.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/generic/simple-card-utils.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index f73763f54ddf..044a0c903ef5 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -296,7 +296,7 @@ int simple_util_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); + struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id); struct simple_util_dai *dai; unsigned int fixed_sysclk = 0; int i1, i2, i; @@ -357,7 +357,7 @@ void simple_util_shutdown(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); + struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id); struct simple_util_dai *dai; int i; @@ -448,7 +448,7 @@ int simple_util_hw_params(struct snd_pcm_substream *substream, struct simple_util_dai *pdai; struct snd_soc_dai *sdai; struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); + struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id); unsigned int mclk, mclk_fs = 0; int i, ret; @@ -517,7 +517,7 @@ int simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num); + struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->id); struct simple_util_data *data = &dai_props->adata; struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); @@ -628,7 +628,7 @@ static int simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd) { struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); + struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id); struct simple_util_dai *dai; int i, ret; From 70729cbf33676a07c024384dc701ecd6c5a85672 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:46 +0100 Subject: [PATCH 164/256] ASoC: remove rtd->num JIRA: https://issues.redhat.com/browse/RHEL-80681 commit c59db5ed233a19f6aadd086fb89149ec5f6fa855 Author: Kuninori Morimoto Date: Thu Oct 24 01:29:45 2024 +0000 ASoC: remove rtd->num No one is using rtd->num. Let's remove it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87sesmb852.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/soc.h | 1 - sound/soc/soc-core.c | 1 - 2 files changed, 2 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index e70e69c5afb4..488f65c2d837 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1185,7 +1185,6 @@ struct snd_soc_pcm_runtime { struct dentry *debugfs_dpcm_root; #endif - unsigned int num; /* REMOVE ME */ unsigned int id; /* 0-based and monotonic increasing */ struct list_head list; /* rtd list of the soc card */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3cb748279166..233c91e60f0c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -559,7 +559,6 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( rtd->card = card; rtd->dai_link = dai_link; rtd->id = card->num_rtd++; - rtd->num = rtd->id; /* REMOVE ME */ rtd->pmdown_time = pmdown_time; /* default power off timeout */ /* see for_each_card_rtds */ From 0a8cf24b6625f85ac28fe3ecd51a963051ca9ba8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:46 +0100 Subject: [PATCH 165/256] ASoC: soc-core: do rtd->id trick at snd_soc_add_pcm_runtime() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit cb18cd26039f5cdecb0ac53fb447b6f0859f3d1c Author: Kuninori Morimoto Date: Thu Oct 24 01:29:52 2024 +0000 ASoC: soc-core: do rtd->id trick at snd_soc_add_pcm_runtime() qcom/qdsp6 want to use irregular rtd->id because of its topology. Current code is calculating it at soc_init_pcm_runtime() which calls soc_new_pcm(), and it doesn't save it to rtd->id. Let's calculate and save it to rtd at snd_soc_add_pcm_runtime() which create rtd and connect related components. But, this feature should be implemented by using "dai_link" instead of "component". Add FIXME as comment. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87r086b84w.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/soc-core.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 233c91e60f0c..4f0bfe73fe15 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1166,7 +1166,7 @@ static int snd_soc_add_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai_link_component *codec, *platform, *cpu; struct snd_soc_component *component; - int i, ret; + int i, id, ret; lockdep_assert_held(&client_mutex); @@ -1225,6 +1225,28 @@ static int snd_soc_add_pcm_runtime(struct snd_soc_card *card, } } + /* + * Most drivers will register their PCMs using DAI link ordering but + * topology based drivers can use the DAI link id field to set PCM + * device number and then use rtd + a base offset of the BEs. + * + * FIXME + * + * This should be implemented by using "dai_link" feature instead of + * "component" feature. + */ + id = rtd->id; + for_each_rtd_components(rtd, i, component) { + if (!component->driver->use_dai_pcm_id) + continue; + + if (rtd->dai_link->no_pcm) + id += component->driver->be_pcm_base; + else + id = rtd->dai_link->id; + } + rtd->id = id; + return 0; _err_defer: @@ -1457,8 +1479,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, { struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct snd_soc_component *component; - int ret, id, i; + int ret, id; /* do machine specific initialization */ ret = snd_soc_link_init(rtd); @@ -1475,21 +1496,6 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, id = rtd->id; - /* - * most drivers will register their PCMs using DAI link ordering but - * topology based drivers can use the DAI link id field to set PCM - * device number and then use rtd + a base offset of the BEs. - */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->use_dai_pcm_id) - continue; - - if (rtd->dai_link->no_pcm) - id += component->driver->be_pcm_base; - else - id = rtd->dai_link->id; - } - /* create compress_device if possible */ ret = snd_soc_dai_compress_new(cpu_dai, rtd, id); if (ret != -ENOTSUPP) From b81c45164611d84f1925fa82fcb56167bd67f8a0 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:42:46 +0100 Subject: [PATCH 166/256] ASoC: cleanup function parameter for rtd and its id JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 8b12da9a18f4dd53e4b3a7393829a555e84f073c Author: Kuninori Morimoto Date: Thu Oct 24 01:29:58 2024 +0000 ASoC: cleanup function parameter for rtd and its id some functions had parameter like below xxx(..., rtd, ..., id); This "id" is rtd->id. We don't need to have "id" on each functions because we can get it from "rtd". Let's cleanup it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87plnqb84p.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/soc-dai.h | 5 ++--- include/sound/soc.h | 6 +++--- sound/soc/soc-compress.c | 9 ++++----- sound/soc/soc-core.c | 8 +++----- sound/soc/soc-dai.c | 4 ++-- sound/soc/soc-pcm.c | 16 ++++++++-------- 6 files changed, 22 insertions(+), 26 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 9dbeedf6da13..b275201b02f6 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -216,8 +216,7 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int rollback); void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); -int snd_soc_dai_compress_new(struct snd_soc_dai *dai, - struct snd_soc_pcm_runtime *rtd, int id); +int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd); bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int stream); void snd_soc_dai_action(struct snd_soc_dai *dai, int stream, int action); @@ -275,7 +274,7 @@ struct snd_soc_dai_ops { int (*probe)(struct snd_soc_dai *dai); int (*remove)(struct snd_soc_dai *dai); /* compress dai */ - int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int id); + int (*compress_new)(struct snd_soc_pcm_runtime *rtd); /* Optional Callback used at pcm creation*/ int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); diff --git a/include/sound/soc.h b/include/sound/soc.h index 488f65c2d837..dd9ef4ee23ee 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -476,11 +476,11 @@ struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, struct snd_soc_component *snd_soc_lookup_component(struct device *dev, const char *driver_name); -int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int id); +int soc_new_pcm(struct snd_soc_pcm_runtime *rtd); #ifdef CONFIG_SND_SOC_COMPRESS -int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int id); +int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd); #else -static inline int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int id) +static inline int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd) { return 0; } diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index fb664c775dda..3c514703fa33 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -537,11 +537,10 @@ static struct snd_compr_ops soc_compr_dyn_ops = { * snd_soc_new_compress - create a new compress. * * @rtd: The runtime for which we will create compress - * @id: the device index number (zero based - shared with normal PCMs) * * Return: 0 for success, else error. */ -int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int id) +int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_component *component; struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); @@ -617,7 +616,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int id) snprintf(new_name, sizeof(new_name), "(%s)", rtd->dai_link->stream_name); - ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, id, + ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, rtd->id, playback, capture, &be_pcm); if (ret < 0) { dev_err(rtd->card->dev, @@ -638,7 +637,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int id) memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); } else { snprintf(new_name, sizeof(new_name), "%s %s-%d", - rtd->dai_link->stream_name, codec_dai->name, id); + rtd->dai_link->stream_name, codec_dai->name, rtd->id); memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); } @@ -652,7 +651,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int id) break; } - ret = snd_compress_new(rtd->card->snd_card, id, direction, + ret = snd_compress_new(rtd->card->snd_card, rtd->id, direction, new_name, compr); if (ret < 0) { component = snd_soc_rtd_to_codec(rtd, 0)->component; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4f0bfe73fe15..a1dace4bb616 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1479,7 +1479,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, { struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - int ret, id; + int ret; /* do machine specific initialization */ ret = snd_soc_link_init(rtd); @@ -1494,15 +1494,13 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, /* add DPCM sysfs entries */ soc_dpcm_debugfs_add(rtd); - id = rtd->id; - /* create compress_device if possible */ - ret = snd_soc_dai_compress_new(cpu_dai, rtd, id); + ret = snd_soc_dai_compress_new(cpu_dai, rtd); if (ret != -ENOTSUPP) goto err; /* create the pcm */ - ret = soc_new_pcm(rtd, id); + ret = soc_new_pcm(rtd); if (ret < 0) { dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", dai_link->stream_name, ret); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 2feb76bf57bb..34ba1a93a4c9 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -457,12 +457,12 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, } int snd_soc_dai_compress_new(struct snd_soc_dai *dai, - struct snd_soc_pcm_runtime *rtd, int id) + struct snd_soc_pcm_runtime *rtd) { int ret = -ENOTSUPP; if (dai->driver->ops && dai->driver->ops->compress_new) - ret = dai->driver->ops->compress_new(rtd, id); + ret = dai->driver->ops->compress_new(rtd); return soc_dai_ret(dai, ret); } diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 81b63e547a09..fb7f25fd8ec5 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2891,7 +2891,7 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, static int soc_create_pcm(struct snd_pcm **pcm, struct snd_soc_pcm_runtime *rtd, - int playback, int capture, int id) + int playback, int capture) { char new_name[64]; int ret; @@ -2901,13 +2901,13 @@ static int soc_create_pcm(struct snd_pcm **pcm, snprintf(new_name, sizeof(new_name), "codec2codec(%s)", rtd->dai_link->stream_name); - ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, id, + ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, rtd->id, playback, capture, pcm); } else if (rtd->dai_link->no_pcm) { snprintf(new_name, sizeof(new_name), "(%s)", rtd->dai_link->stream_name); - ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, id, + ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, rtd->id, playback, capture, pcm); } else { if (rtd->dai_link->dynamic) @@ -2916,9 +2916,9 @@ static int soc_create_pcm(struct snd_pcm **pcm, else snprintf(new_name, sizeof(new_name), "%s %s-%d", rtd->dai_link->stream_name, - soc_codec_dai_name(rtd), id); + soc_codec_dai_name(rtd), rtd->id); - ret = snd_pcm_new(rtd->card->snd_card, new_name, id, playback, + ret = snd_pcm_new(rtd->card->snd_card, new_name, rtd->id, playback, capture, pcm); } if (ret < 0) { @@ -2926,13 +2926,13 @@ static int soc_create_pcm(struct snd_pcm **pcm, new_name, rtd->dai_link->name, ret); return ret; } - dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n", id, new_name); + dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n", rtd->id, new_name); return 0; } /* create a new pcm */ -int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int id) +int soc_new_pcm(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_component *component; struct snd_pcm *pcm; @@ -2943,7 +2943,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int id) if (ret < 0) return ret; - ret = soc_create_pcm(&pcm, rtd, playback, capture, id); + ret = soc_create_pcm(&pcm, rtd, playback, capture); if (ret < 0) return ret; From 7f6804fbf7923b473d32d08e51b5d4b1ab5c5520 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:03 +0100 Subject: [PATCH 167/256] ALSA: hda: intel: Don't free interrupt when suspending JIRA: https://issues.redhat.com/browse/RHEL-80681 commit cac99f73f0752e1c83674e12fb2c605dca9ce474 Author: Heiner Kallweit Date: Thu Oct 31 20:32:52 2024 +0100 ALSA: hda: intel: Don't free interrupt when suspending There's no need to free/re-request the interrupt on system suspend. PCI core takes care, using functions like pci_restore_msi_state(). Signed-off-by: Heiner Kallweit Link: https://patch.msgid.link/1b7e109b-eb69-4542-8022-4ac8f9116474@gmail.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_intel.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d729cae66e49..49a503b14c86 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1039,14 +1039,6 @@ static int azx_suspend(struct device *dev) chip = card->private_data; bus = azx_bus(chip); azx_shutdown_chip(chip); - if (bus->irq >= 0) { - free_irq(bus->irq, chip); - bus->irq = -1; - chip->card->sync_irq = -1; - } - - if (chip->msi) - pci_disable_msi(chip->pci); trace_azx_suspend(chip); return 0; @@ -1061,11 +1053,6 @@ static int __maybe_unused azx_resume(struct device *dev) return 0; chip = card->private_data; - if (chip->msi) - if (pci_enable_msi(chip->pci) < 0) - chip->msi = 0; - if (azx_acquire_irq(chip, 1) < 0) - return -EIO; __azx_runtime_resume(chip); From 99aa9139db71704267303d074e2d493c99c24b85 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:03 +0100 Subject: [PATCH 168/256] ALSA: hda: intel: Switch to pci_alloc_irq_vectors API JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 149cb7d9537e241b43056fb4133f56832ac51b7a Author: Heiner Kallweit Date: Thu Oct 31 20:41:12 2024 +0100 ALSA: hda: intel: Switch to pci_alloc_irq_vectors API Switch from legacy pci_msi_enable()/pci_intx() API to the pci_alloc_irq_vectors API. Signed-off-by: Heiner Kallweit Link: https://patch.msgid.link/11c60429-9435-4666-8e27-77160abef68e@gmail.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_intel.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 49a503b14c86..e265104034a1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -772,6 +772,14 @@ static void azx_clear_irq_pending(struct azx *chip) static int azx_acquire_irq(struct azx *chip, int do_disconnect) { struct hdac_bus *bus = azx_bus(chip); + int ret; + + if (!chip->msi || pci_alloc_irq_vectors(chip->pci, 1, 1, PCI_IRQ_MSI) < 0) { + ret = pci_alloc_irq_vectors(chip->pci, 1, 1, PCI_IRQ_INTX); + if (ret < 0) + return ret; + chip->msi = 0; + } if (request_irq(chip->pci->irq, azx_interrupt, chip->msi ? 0 : IRQF_SHARED, @@ -785,7 +793,6 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) } bus->irq = chip->pci->irq; chip->card->sync_irq = bus->irq; - pci_intx(chip->pci, !chip->msi); return 0; } @@ -1878,13 +1885,9 @@ static int azx_first_init(struct azx *chip) chip->gts_present = true; #endif - if (chip->msi) { - if (chip->driver_caps & AZX_DCAPS_NO_MSI64) { - dev_dbg(card->dev, "Disabling 64bit MSI\n"); - pci->no_64bit_msi = true; - } - if (pci_enable_msi(pci) < 0) - chip->msi = 0; + if (chip->msi && chip->driver_caps & AZX_DCAPS_NO_MSI64) { + dev_dbg(card->dev, "Disabling 64bit MSI\n"); + pci->no_64bit_msi = true; } pci_set_master(pci); @@ -2036,7 +2039,7 @@ static int disable_msi_reset_irq(struct azx *chip) free_irq(bus->irq, chip); bus->irq = -1; chip->card->sync_irq = -1; - pci_disable_msi(chip->pci); + pci_free_irq_vectors(chip->pci); chip->msi = 0; err = azx_acquire_irq(chip, 1); if (err < 0) From 34fc4a737748de65601dd3b6d59dbb13d3eb15b9 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:04 +0100 Subject: [PATCH 169/256] ALSA: hda: Fix unused variable warning JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 8ae4c65d7ae82fead83202448453e47078ddfde7 Author: Takashi Iwai Date: Mon Nov 4 20:06:53 2024 +0100 ALSA: hda: Fix unused variable warning The previous code cleanup made a variable not really used, which now leads to a compile warning. Let's fix it. Fixes: cac99f73f075 ("ALSA: hda: intel: Don't free interrupt when suspending") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202411050247.3esQz7Am-lkp@intel.com/ Link: https://patch.msgid.link/20241104190654.32216-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_intel.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index e265104034a1..aa032bc94db3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1038,13 +1038,11 @@ static int azx_suspend(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; - struct hdac_bus *bus; if (!azx_is_pm_ready(card)) return 0; chip = card->private_data; - bus = azx_bus(chip); azx_shutdown_chip(chip); trace_azx_suspend(chip); From f8de738481f8075f17aef71174c39c6f7b7bf29a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:04 +0100 Subject: [PATCH 170/256] ASoC: amd: acp: Fix for ACP SOF dmic tplg component load failure JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 224b898f7c5ff575b02911e21383f271761bdeb6 Author: Venkata Prasad Potturu Date: Mon Nov 4 14:43:10 2024 +0530 ASoC: amd: acp: Fix for ACP SOF dmic tplg component load failure Stream name mismatch with topology file causes tplg load failure. As SOF framework assigns dailink->stream name, overriding stream name other than link name causes SOF dmic component load failure. [ 35.474995] snd_sof_amd_acp70 0000:c4:00.5: error: can't connect DAI ACPDMIC0.IN stream acp-dmic-codec [ 35.475001] snd_sof_amd_acp70 0000:c4:00.5: failed to add widget type 28 name : ACPDMIC0.IN stream acp-dmic-codec [ 35.475013] sof_mach acp70-dsp: ASoC: failed to load widget ACPDMIC0.IN [ 35.475018] sof_mach acp70-dsp: ASoC: topology: could not load header: -22 [ 35.475072] snd_sof_amd_acp70 0000:c4:00.5: error: tplg component load failed -22 [ 35.475083] snd_sof_amd_acp70 0000:c4:00.5: error: failed to load DSP topology -22 [ 35.475090] snd_sof_amd_acp70 0000:c4:00.5: ASoC: error at snd_soc_component_probe on 0000:c4:00.5: -22 [ 35.475117] sof_mach acp70-dsp: ASoC: failed to instantiate card -22 [ 35.475254] sof_mach acp70-dsp: error -EINVAL: Failed to register card(sof-acp70-dsp) [ 35.475261] sof_mach acp70-dsp: probe with driver sof_mach failed with error -22 Fixes: b2385de2ae11 ("ASoC: amd: acp: Add stream name to ACP PDM DMIC devices") Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20241104091312.1108299-1-venkataprasad.potturu@amd.com Reviewed-by: Mario Limonciello Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/acp-mach-common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index 67aa0ad83486..d314253207d5 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -1561,7 +1561,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) if (drv_data->dmic_cpu_id == DMIC) { links[i].name = "acp-dmic-codec"; - links[i].stream_name = "DMIC capture"; links[i].id = DMIC_BE_ID; links[i].codecs = dmic_codec; links[i].num_codecs = ARRAY_SIZE(dmic_codec); From 9c96c94c8f95e305e862f48092673c04e6e6b9e2 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:04 +0100 Subject: [PATCH 171/256] ASoC: codecs: ES8326: Reduce pop noise JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 8f5fab5329b7e966344d59fd1c17adbf9f025c52 Author: Zhang Yi Date: Thu Oct 31 14:02:53 2024 +0800 ASoC: codecs: ES8326: Reduce pop noise We modify the value of ES8326_ANA_MICBIAS to reduce the pop noise Signed-off-by: Zhang Yi Link: https://patch.msgid.link/20241031060253.21001-1-zhangyi@everest-semi.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/es8326.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index 62a828cc519d..096772b35127 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -617,7 +617,7 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) 0x0F, 0x0F); if (es8326->version > ES8326_VERSION_B) { regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); - regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x00); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x10); } } } else { @@ -1083,7 +1083,7 @@ static void es8326_init(struct snd_soc_component *component) regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66); es8326_disable_micbias(es8326->component); if (es8326->version > ES8326_VERSION_B) { - regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x73, 0x03); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x73, 0x13); regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); } From b4a1fa640245bf18e35204610da3da966fc26d77 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:04 +0100 Subject: [PATCH 172/256] ASoC: qcom: x1e80100: Support boards with two speakers JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 159098859bf6d46b34a1e1f7d44d28987b875878 Author: Krzysztof Kozlowski Date: Wed Oct 23 14:41:52 2024 +0200 ASoC: qcom: x1e80100: Support boards with two speakers Some Qualcomm X1E laptops have only two speakers. Regardless whether this sound card driver is suitable for them (we could re-use one for some older SoC), we should set reasonable channel map depending on the number of channels, not always 4-speaker setup. This change is necessary for bringing audio support on Lenovo Thinkpad T14s with Qualcomm X1E78100 and only two speakers. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20241023124152.130706-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/qcom/x1e80100.c | 40 ++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/sound/soc/qcom/x1e80100.c b/sound/soc/qcom/x1e80100.c index 898b5c26bf1e..8eb57fc12f0d 100644 --- a/sound/soc/qcom/x1e80100.c +++ b/sound/soc/qcom/x1e80100.c @@ -95,23 +95,53 @@ static int x1e80100_snd_hw_params(struct snd_pcm_substream *substream, return qcom_snd_sdw_hw_params(substream, params, &data->sruntime[cpu_dai->id]); } +static int x1e80100_snd_hw_map_channels(unsigned int *ch_map, int num) +{ + switch (num) { + case 1: + ch_map[0] = PCM_CHANNEL_FC; + break; + case 2: + ch_map[0] = PCM_CHANNEL_FL; + ch_map[1] = PCM_CHANNEL_FR; + break; + case 3: + ch_map[0] = PCM_CHANNEL_FL; + ch_map[1] = PCM_CHANNEL_FR; + ch_map[2] = PCM_CHANNEL_FC; + break; + case 4: + ch_map[0] = PCM_CHANNEL_FL; + ch_map[1] = PCM_CHANNEL_LB; + ch_map[2] = PCM_CHANNEL_FR; + ch_map[3] = PCM_CHANNEL_RB; + break; + default: + return -EINVAL; + } + + return 0; +} + static int x1e80100_snd_prepare(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - const unsigned int rx_slot[4] = { PCM_CHANNEL_FL, - PCM_CHANNEL_LB, - PCM_CHANNEL_FR, - PCM_CHANNEL_RB }; + unsigned int channels = substream->runtime->channels; + unsigned int rx_slot[4]; int ret; switch (cpu_dai->id) { case WSA_CODEC_DMA_RX_0: case WSA_CODEC_DMA_RX_1: + ret = x1e80100_snd_hw_map_channels(rx_slot, channels); + if (ret) + return ret; + ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL, - ARRAY_SIZE(rx_slot), rx_slot); + channels, rx_slot); if (ret) return ret; break; From dcb0e100dbf63dffcb6c5e3bf68e577fa74ef6bf Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:04 +0100 Subject: [PATCH 173/256] ASoC: bcm63xx-pcm-whistler: fix uninit-value in i2s_dma_isr JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 28f7aa0c015036db260adbec37891984a31ed4c2 Author: Suraj Sonawane Date: Sat Nov 2 18:06:30 2024 +0530 ASoC: bcm63xx-pcm-whistler: fix uninit-value in i2s_dma_isr Fix an issue detected by the Smatch tool: sound/soc/bcm/bcm63xx-pcm-whistler.c:264 i2s_dma_isr() error: uninitialized symbol 'val_1'. sound/soc/bcm/bcm63xx-pcm-whistler.c:264 i2s_dma_isr() error: uninitialized symbol 'val_2'. These errors were triggered because the variables 'val_1' and 'val_2' could remain uninitialized if 'offlevel' is zero, meaning the loop that assigns values to them does not execute. In this case, 'dma_addr_next' would use uninitialized data, potentially leading to undefined behavior. To resolve this, a conditional update for 'dma_addr_next' is added, ensuring it is assigned only when 'val_1' and 'val_2' are read. A new boolean variable 'val_read' flags when the values have been retrieved, setting 'dma_addr_next' only if valid data is available. This solution prevents the use of uninitialized data, maintaining defined behavior for 'dma_addr_next' in all cases, and aligns with expected usage of I2S RX descriptor data. Signed-off-by: Suraj Sonawane Link: https://patch.msgid.link/20241102123630.25446-1-surajsonawane0215@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/bcm/bcm63xx-pcm-whistler.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/bcm/bcm63xx-pcm-whistler.c b/sound/soc/bcm/bcm63xx-pcm-whistler.c index 018f2372e892..e3a4fcc63a56 100644 --- a/sound/soc/bcm/bcm63xx-pcm-whistler.c +++ b/sound/soc/bcm/bcm63xx-pcm-whistler.c @@ -256,12 +256,16 @@ static irqreturn_t i2s_dma_isr(int irq, void *bcm_i2s_priv) offlevel = (int_status & I2S_RX_DESC_OFF_LEVEL_MASK) >> I2S_RX_DESC_OFF_LEVEL_SHIFT; + bool val_read = false; while (offlevel) { regmap_read(regmap_i2s, I2S_RX_DESC_OFF_ADDR, &val_1); regmap_read(regmap_i2s, I2S_RX_DESC_OFF_LEN, &val_2); + val_read = true; offlevel--; } - prtd->dma_addr_next = val_1 + val_2; + if (val_read) + prtd->dma_addr_next = val_1 + val_2; + ifflevel = (int_status & I2S_RX_DESC_IFF_LEVEL_MASK) >> I2S_RX_DESC_IFF_LEVEL_SHIFT; From 673fbe3ae19fc43317a773ee8bb0e33f3ae37183 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:05 +0100 Subject: [PATCH 174/256] ASoC: dt-bindings: qcom,sm8250: Add SM8750 sound card JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 393de01870bcf2ea1eadd21ad12f927d78cbb726 Author: Krzysztof Kozlowski Date: Fri Nov 1 17:51:58 2024 +0100 ASoC: dt-bindings: qcom,sm8250: Add SM8750 sound card Add bindings for SM8750 sound card, compatible with older SM8450 variant. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20241101165159.370619-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- Documentation/devicetree/bindings/sound/qcom,sm8250.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index 38316073e35b..28356155851c 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -25,6 +25,7 @@ properties: - enum: - qcom,sm8550-sndcard - qcom,sm8650-sndcard + - qcom,sm8750-sndcard - const: qcom,sm8450-sndcard - enum: - qcom,apq8016-sbc-sndcard From 983840623814019cbfac921cb3a61c81460fa68b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:05 +0100 Subject: [PATCH 175/256] ASoC: qcom: sc8280xp Add SM8750 sound card JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 4b9f02b6c5376b65dac398c4f06804c914cbb7be Author: Krzysztof Kozlowski Date: Fri Nov 1 17:51:59 2024 +0100 ASoC: qcom: sc8280xp Add SM8750 sound card Add OF device ID entry for SM8750 sound card with its own model name, used to load proper Audioreach topology file. The sound card is compatible with SM8450 and newer family. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20241101165159.370619-2-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/qcom/sc8280xp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index b9b60cb4647b..12837a32e6bf 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -191,6 +191,7 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = { {.compatible = "qcom,sm8450-sndcard", "sm8450"}, {.compatible = "qcom,sm8550-sndcard", "sm8550"}, {.compatible = "qcom,sm8650-sndcard", "sm8650"}, + {.compatible = "qcom,sm8750-sndcard", "sm8750"}, {} }; From 57087172416650d67f69b00340bb3d0eaeb927b9 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:05 +0100 Subject: [PATCH 176/256] ASoC: rt722: change the interrupt mask for jack type detection JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 93b763a5ab13509e9a2bcbcac3002607736e601b Author: Shuming Fan Date: Tue Nov 5 18:05:57 2024 +0800 ASoC: rt722: change the interrupt mask for jack type detection This patch changed the interrupt mask from XU to GE. Signed-off-by: Shuming Fan Link: https://patch.msgid.link/20241105100557.1987917-1-shumingf@realtek.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/rt722-sdca-sdw.c | 12 ++++-------- sound/soc/codecs/rt722-sdca.c | 7 ++++--- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c index d5c985ff5ac5..25fc13687bc8 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.c +++ b/sound/soc/codecs/rt722-sdca-sdw.c @@ -177,7 +177,7 @@ static int rt722_sdca_update_status(struct sdw_slave *slave, * This also could sync with the cache value as the rt722_sdca_jack_init set. */ sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK1, - SDW_SCP_SDCA_INTMASK_SDCA_6); + SDW_SCP_SDCA_INTMASK_SDCA_0); sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8); } @@ -308,12 +308,8 @@ static int rt722_sdca_interrupt_callback(struct sdw_slave *slave, SDW_SCP_SDCA_INT_SDCA_0, SDW_SCP_SDCA_INT_SDCA_0); if (ret < 0) goto io_error; - } else if (ret & SDW_SCP_SDCA_INTMASK_SDCA_6) { - ret = sdw_update_no_pm(rt722->slave, SDW_SCP_SDCA_INT1, - SDW_SCP_SDCA_INT_SDCA_6, SDW_SCP_SDCA_INT_SDCA_6); - if (ret < 0) - goto io_error; } + ret = sdw_read_no_pm(rt722->slave, SDW_SCP_SDCA_INT2); if (ret < 0) goto io_error; @@ -444,7 +440,7 @@ static int __maybe_unused rt722_sdca_dev_system_suspend(struct device *dev) mutex_lock(&rt722_sdca->disable_irq_lock); rt722_sdca->disable_irq = true; ret1 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK1, - SDW_SCP_SDCA_INTMASK_SDCA_0 | SDW_SCP_SDCA_INTMASK_SDCA_6, 0); + SDW_SCP_SDCA_INTMASK_SDCA_0, 0); ret2 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8, 0); mutex_unlock(&rt722_sdca->disable_irq_lock); @@ -471,7 +467,7 @@ static int __maybe_unused rt722_sdca_dev_resume(struct device *dev) if (!slave->unattach_request) { mutex_lock(&rt722->disable_irq_lock); if (rt722->disable_irq == true) { - sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_6); + sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0); sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8); rt722->disable_irq = false; } diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c index 9a0747c4bdea..e17a142d03b9 100644 --- a/sound/soc/codecs/rt722-sdca.c +++ b/sound/soc/codecs/rt722-sdca.c @@ -190,8 +190,8 @@ static void rt722_sdca_jack_detect_handler(struct work_struct *work) if (!rt722->component->card || !rt722->component->card->instantiated) return; - /* SDW_SCP_SDCA_INT_SDCA_6 is used for jack detection */ - if (rt722->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_6) { + /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */ + if (rt722->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_0) { ret = rt722_sdca_headset_detect(rt722); if (ret < 0) return; @@ -294,7 +294,7 @@ static void rt722_sdca_jack_init(struct rt722_sdca_priv *rt722) if (rt722->hs_jack) { /* set SCP_SDCA_IntMask1[0]=1 */ sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK1, - SDW_SCP_SDCA_INTMASK_SDCA_0 | SDW_SCP_SDCA_INTMASK_SDCA_6); + SDW_SCP_SDCA_INTMASK_SDCA_0); /* set SCP_SDCA_IntMask2[0]=1 */ sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8); @@ -308,6 +308,7 @@ static void rt722_sdca_jack_init(struct rt722_sdca_priv *rt722) regmap_write(rt722->regmap, SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU0D, RT722_SDCA_CTL_SELECTED_MODE, 0), 0); + rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_GE_RELATED_CTL1, 0x0000); /* trigger GE interrupt */ rt722_sdca_index_update_bits(rt722, RT722_VENDOR_HDA_CTL, RT722_GE_RELATED_CTL2, 0x4000, 0x4000); From 96f5d718633a66134c426a6825e2582fc1ae4518 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:05 +0100 Subject: [PATCH 177/256] ASoC: rt721-sdca: change interrupt mask from XU to GE JIRA: https://issues.redhat.com/browse/RHEL-80681 commit b3cb7f2a3a1732a775861a2279d951e79c0e614c Author: Jack Yu Date: Tue Nov 5 08:51:32 2024 +0000 ASoC: rt721-sdca: change interrupt mask from XU to GE Change interrupt mask from XU to GE to fix jack detection interrupt issue. Signed-off-by: Jack Yu Link: https://patch.msgid.link/cbc81e324673467a96b70e4e219766b5@realtek.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/rt721-sdca-sdw.c | 13 ++++--------- sound/soc/codecs/rt721-sdca.c | 6 ++++-- sound/soc/codecs/rt721-sdca.h | 1 + 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/rt721-sdca-sdw.c b/sound/soc/codecs/rt721-sdca-sdw.c index c0f8cccae3b2..c71453da088a 100644 --- a/sound/soc/codecs/rt721-sdca-sdw.c +++ b/sound/soc/codecs/rt721-sdca-sdw.c @@ -203,7 +203,7 @@ static int rt721_sdca_update_status(struct sdw_slave *slave, * This also could sync with the cache value as the rt721_sdca_jack_init set. */ sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK1, - SDW_SCP_SDCA_INTMASK_SDCA_6); + SDW_SCP_SDCA_INTMASK_SDCA_0); sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8); } @@ -280,7 +280,7 @@ static int rt721_sdca_read_prop(struct sdw_slave *slave) } /* set the timeout values */ - prop->clk_stop_timeout = 900; + prop->clk_stop_timeout = 1380; /* wake-up event */ prop->wake_capable = 1; @@ -337,11 +337,6 @@ static int rt721_sdca_interrupt_callback(struct sdw_slave *slave, SDW_SCP_SDCA_INT_SDCA_0, SDW_SCP_SDCA_INT_SDCA_0); if (ret < 0) goto io_error; - } else if (ret & SDW_SCP_SDCA_INTMASK_SDCA_6) { - ret = sdw_update_no_pm(rt721->slave, SDW_SCP_SDCA_INT1, - SDW_SCP_SDCA_INT_SDCA_6, SDW_SCP_SDCA_INT_SDCA_6); - if (ret < 0) - goto io_error; } ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2); if (ret < 0) @@ -475,7 +470,7 @@ static int __maybe_unused rt721_sdca_dev_system_suspend(struct device *dev) mutex_lock(&rt721_sdca->disable_irq_lock); rt721_sdca->disable_irq = true; ret1 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK1, - SDW_SCP_SDCA_INTMASK_SDCA_0 | SDW_SCP_SDCA_INTMASK_SDCA_6, 0); + SDW_SCP_SDCA_INTMASK_SDCA_0, 0); ret2 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8, 0); mutex_unlock(&rt721_sdca->disable_irq_lock); @@ -502,7 +497,7 @@ static int __maybe_unused rt721_sdca_dev_resume(struct device *dev) if (!slave->unattach_request) { mutex_lock(&rt721->disable_irq_lock); if (rt721->disable_irq == true) { - sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_6); + sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0); sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8); rt721->disable_irq = false; } diff --git a/sound/soc/codecs/rt721-sdca.c b/sound/soc/codecs/rt721-sdca.c index bdd160b80b64..1c9f32e405cf 100644 --- a/sound/soc/codecs/rt721-sdca.c +++ b/sound/soc/codecs/rt721-sdca.c @@ -39,7 +39,7 @@ static void rt721_sdca_jack_detect_handler(struct work_struct *work) return; /* SDW_SCP_SDCA_INT_SDCA_6 is used for jack detection */ - if (rt721->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_6) { + if (rt721->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_0) { rt721->jack_type = rt_sdca_headset_detect(rt721->regmap, RT721_SDCA_ENT_GE49); if (rt721->jack_type < 0) @@ -286,7 +286,7 @@ static void rt721_sdca_jack_init(struct rt721_sdca_priv *rt721) mutex_lock(&rt721->calibrate_mutex); if (rt721->hs_jack) { sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK1, - SDW_SCP_SDCA_INTMASK_SDCA_0 | SDW_SCP_SDCA_INTMASK_SDCA_6); + SDW_SCP_SDCA_INTMASK_SDCA_0); sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8); dev_dbg(&rt721->slave->dev, "in %s enable\n", __func__); @@ -298,6 +298,8 @@ static void rt721_sdca_jack_init(struct rt721_sdca_priv *rt721) regmap_write(rt721->regmap, SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XU0D, RT721_SDCA_CTL_SELECTED_MODE, 0), 0); + rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, + RT721_XU_REL_CTRL, 0x0000); rt_sdca_index_update_bits(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, RT721_GE_REL_CTRL1, 0x4000, 0x4000); } diff --git a/sound/soc/codecs/rt721-sdca.h b/sound/soc/codecs/rt721-sdca.h index e2f071909da8..0a82c107b19a 100644 --- a/sound/soc/codecs/rt721-sdca.h +++ b/sound/soc/codecs/rt721-sdca.h @@ -133,6 +133,7 @@ struct rt721_sdca_dmic_kctrl_priv { #define RT721_HDA_LEGACY_UAJ_CTL 0x02 #define RT721_HDA_LEGACY_CTL1 0x05 #define RT721_HDA_LEGACY_RESET_CTL 0x06 +#define RT721_XU_REL_CTRL 0x0c #define RT721_GE_REL_CTRL1 0x0d #define RT721_HDA_LEGACY_GPIO_WAKE_EN_CTL 0x0e #define RT721_GE_SDCA_RST_CTRL 0x10 From 90cfe203c0f3436f4e64b07b7042f44976c06600 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:06 +0100 Subject: [PATCH 178/256] ALSA: compress_offload: Use runtime pointer in snd_compr_poll() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9e096b3cbbecfeecb544ec5a94dbd6e10df2219b Author: Peter Ujfalusi Date: Wed Nov 6 09:53:12 2024 +0200 ALSA: compress_offload: Use runtime pointer in snd_compr_poll() runtime is not used as seen with W=1 : sound/core/compress_offload.c: In function ‘snd_compr_poll’: sound/core/compress_offload.c:409:35: error: variable ‘runtime’ set but not used [-Werror=unused-but-set-variable] 409 | struct snd_compr_runtime *runtime; | ^~~~~~~ Instead of dropping the runtime, use it in the function in place of stream->runtime Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode") Signed-off-by: Peter Ujfalusi Reviewed-by: Jaroslav Kysela Link: https://patch.msgid.link/20241106075312.15601-1-peter.ujfalusi@linux.intel.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/core/compress_offload.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 5ecdad80a0d8..86ed2fbee0c8 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -418,7 +418,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait) guard(mutex)(&stream->device->lock); - switch (stream->runtime->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_XRUN: return snd_compr_get_poll(stream) | EPOLLERR; @@ -426,7 +426,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait) break; } - poll_wait(f, &stream->runtime->sleep, wait); + poll_wait(f, &runtime->sleep, wait); #if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) if (stream->direction == SND_COMPRESS_ACCEL) { @@ -445,18 +445,18 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait) avail = snd_compr_get_avail(stream); pr_debug("avail is %ld\n", (unsigned long)avail); /* check if we have at least one fragment to fill */ - switch (stream->runtime->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_DRAINING: /* stream has been woken up after drain is complete * draining done so set stream state to stopped */ retval = snd_compr_get_poll(stream); - stream->runtime->state = SNDRV_PCM_STATE_SETUP; + runtime->state = SNDRV_PCM_STATE_SETUP; break; case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_PAUSED: - if (avail >= stream->runtime->fragment_size) + if (avail >= runtime->fragment_size) retval = snd_compr_get_poll(stream); break; default: From caebe07954825a53d3ccfb1ce74cddc695c086a5 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:06 +0100 Subject: [PATCH 179/256] ASoC: Intel: Kconfig: make SND_SOC_ACPI_INTEL_MATCH depend on ACPI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit b6bd3f3b6357f727a177f31861144788eceda3c1 Author: Bard Liao Date: Wed Nov 6 13:58:09 2024 +0800 ASoC: Intel: Kconfig: make SND_SOC_ACPI_INTEL_MATCH depend on ACPI SND_SOC_ACPI_INTEL_MATCH relies on ACPI functions. It will not work if ACPI is not selected. Signed-off-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Liam Girdwood Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241106055810.10123-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/intel/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 7fa191851e9b..69587143e7c7 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -193,7 +193,8 @@ if SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL config SND_SOC_ACPI_INTEL_MATCH tristate - select SND_SOC_ACPI if ACPI + depends on ACPI + select SND_SOC_ACPI select SND_SOC_ACPI_INTEL_SDCA_QUIRKS # this option controls the compilation of ACPI matching tables and # helpers and is not meant to be selected by the user. From 064a817da15b338b7b118e5ede445dbdeecd7f95 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:06 +0100 Subject: [PATCH 180/256] ASoC: Intel: Kconfig: select SND_SOC_SDCA by SND_SOC_ACPI_INTEL_SDCA_QUIRKS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 845cb1ddf1fc2212f876db6df9d3277badd35709 Author: Bard Liao Date: Wed Nov 6 13:58:10 2024 +0800 ASoC: Intel: Kconfig: select SND_SOC_SDCA by SND_SOC_ACPI_INTEL_SDCA_QUIRKS SND_SOC_SDCA can't be optional when SND_SOC_ACPI_INTEL_SDCA_QUIRKS is selected. IS_REACHABLE can prevent the link error. However it is not suitable for this case. When CONFIG_SND_SOC_ACPI_INTEL_SDCA_QUIRKS is Y and CONFIG_SND_SOC_SDCA is M, the SDCA helpers will be empty and return false. But we need the helpers to do their jobs whenSND_SOC_SDCA is M. IOW, the SDCA library is not optional for Intel platforms where the SDCA_QUIRK is selected. Also, make SND_SOC_SDCA invisible. SND_SOC_SDCA should be selected if a device supports SDCA. User should not unselect it. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202411021722.DiX1Y5sf-lkp@intel.com/ Suggested-by: Peter Ujfalusi Signed-off-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Liam Girdwood Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241106055810.10123-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/intel/Kconfig | 2 +- sound/soc/sdca/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 69587143e7c7..870f88e95718 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -201,7 +201,7 @@ config SND_SOC_ACPI_INTEL_MATCH config SND_SOC_ACPI_INTEL_SDCA_QUIRKS tristate - imply SND_SOC_SDCA + select SND_SOC_SDCA endif ## SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL diff --git a/sound/soc/sdca/Kconfig b/sound/soc/sdca/Kconfig index 07f6822fa614..ee20b9914aa1 100644 --- a/sound/soc/sdca/Kconfig +++ b/sound/soc/sdca/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config SND_SOC_SDCA - tristate "ASoC SDCA library" + tristate depends on ACPI help This option enables support for the MIPI SoundWire Device From e4bce83e90faa4ba5fcdaa918d84411bb2d82996 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:06 +0100 Subject: [PATCH 181/256] ASoC: dt-bindings: irondevice,sma1307: Add initial DT JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 82a1ccdf616d396c99f535febb6c997781c5c26c Author: Kiseok Jo Date: Wed Nov 6 09:57:59 2024 +0900 ASoC: dt-bindings: irondevice,sma1307: Add initial DT This adds the schema binding for the Iron Device SMA1307 Amp Signed-off-by: Kiseok Jo Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20241106005800.7520-2-kiseok.jo@irondevice.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- .../bindings/sound/irondevice,sma1307.yaml | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/irondevice,sma1307.yaml diff --git a/Documentation/devicetree/bindings/sound/irondevice,sma1307.yaml b/Documentation/devicetree/bindings/sound/irondevice,sma1307.yaml new file mode 100644 index 000000000000..1e2a038d0048 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/irondevice,sma1307.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/irondevice,sma1307.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Iron Device SMA1307 Audio Amplifier + +maintainers: + - Kiseok Jo + +description: + SMA1307 boosted digital speaker amplifier with feedback-loop. + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - irondevice,sma1307a + - irondevice,sma1307aq + description: + If a 'q' is added, it indicated the product is AEC-Q100 + qualified for automotive applications. SMA1307A supports + both WLCSP and QFN packages. However, SMA1307AQ only + supports the QFN package. + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 1 + +required: + - compatible + - reg + - '#sound-dai-cells' + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + amplifier@1e { + compatible = "irondevice,sma1307a"; + reg = <0x1e>; + #sound-dai-cells = <1>; + }; + }; From 396cbc666f27ef1843f90dce6280580b26432cd6 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:06 +0100 Subject: [PATCH 182/256] ASoC: sma1307: Add driver for Iron Device SMA1307 JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 576c57e6b4c1d734bcb7cc33dde9a99a9383b520 Author: Kiseok Jo Date: Wed Nov 6 09:58:00 2024 +0900 ASoC: sma1307: Add driver for Iron Device SMA1307 The Iron Device SMA1307 is a boosted digital speaker amplifier Signed-off-by: Kiseok Jo Link: https://patch.msgid.link/20241106005800.7520-3-kiseok.jo@irondevice.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 10 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/sma1307.c | 2052 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/sma1307.h | 444 ++++++++ 4 files changed, 2508 insertions(+) create mode 100644 sound/soc/codecs/sma1307.c create mode 100644 sound/soc/codecs/sma1307.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 2e7b9ab67c09..9659190c854e 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -233,6 +233,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_SIMPLE_AMPLIFIER imply SND_SOC_SIMPLE_MUX imply SND_SOC_SMA1303 + imply SND_SOC_SMA1307 imply SND_SOC_SPDIF imply SND_SOC_SRC4XXX_I2C imply SND_SOC_SSM2305 @@ -1797,6 +1798,15 @@ config SND_SOC_SMA1303 help Enable support for Iron Device SMA1303 Boosted Class-D amplifier +config SND_SOC_SMA1307 + tristate "Iron Device SMA1307 Audio Amplifier" + depends on I2C + help + Enable support for Iron Device SMA1307 boosted digital speaker + amplifier with feedback-loop. + If you are using a system with an SMA1307 amplifier connected + via I2C, enable this option. + config SND_SOC_SPDIF tristate "S/PDIF CODEC" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 135682ae2fa4..eba330568a26 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -270,6 +270,7 @@ snd-soc-sigmadsp-i2c-y := sigmadsp-i2c.o snd-soc-sigmadsp-regmap-y := sigmadsp-regmap.o snd-soc-si476x-y := si476x.o snd-soc-sma1303-y := sma1303.o +snd-soc-sma1307-y := sma1307.o snd-soc-spdif-tx-y := spdif_transmitter.o snd-soc-spdif-rx-y := spdif_receiver.o snd-soc-src4xxx-y := src4xxx.o @@ -670,6 +671,7 @@ obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o obj-$(CONFIG_SND_SOC_SMA1303) += snd-soc-sma1303.o +obj-$(CONFIG_SND_SOC_SMA1307) += snd-soc-sma1307.o obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o obj-$(CONFIG_SND_SOC_SRC4XXX) += snd-soc-src4xxx.o obj-$(CONFIG_SND_SOC_SRC4XXX_I2C) += snd-soc-src4xxx-i2c.o diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c new file mode 100644 index 000000000000..985a247b3310 --- /dev/null +++ b/sound/soc/codecs/sma1307.c @@ -0,0 +1,2052 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// sma1307.c -- sma1307 ALSA SoC Audio driver +// +// Copyright 2024 Iron Device Corporation +// +// Auther: Gyuhwa Park +// Auther: Kiseok Jo + +#include +#include +#include +#include +#include +#include +#include "sma1307.h" + +#define CHECK_PERIOD_TIME 1 /* sec per HZ */ +#define PLL_MATCH(_input_clk_name, _output_clk_name, _input_clk,\ + _post_n, _n, _vco, _p_cp)\ +{\ + .input_clk_name = _input_clk_name,\ + .output_clk_name = _output_clk_name,\ + .input_clk = _input_clk,\ + .post_n = _post_n,\ + .n = _n,\ + .vco = _vco,\ + .p_cp = _p_cp,\ +} + +static const char *setting_file = "sma1307_setting.bin"; +#define SMA1307_SETTING_CHECKSUM 0x100000 + +/* PLL clock setting Table */ +struct sma1307_pll_match { + char *input_clk_name; + char *output_clk_name; + unsigned int input_clk; + unsigned int post_n; + unsigned int n; + unsigned int vco; + unsigned int p_cp; +}; + +struct sma1307_data { + char *name; + void (*init)(struct regmap *regmap); +}; + +struct sma1307_priv { + bool check_fault_status; + bool force_mute_status; + bool sw_ot1_prot; + char *name; + enum sma1307_mode amp_mode; + int binary_mode; + int dapm_aif_in; + int dapm_aif_out0; + int dapm_aif_out1; + int dapm_sdo_en; + int dapm_sdo_setting; + int num_of_pll_matches; + int check_fault_period; + struct delayed_work check_fault_work; + struct device *dev; + struct kobject *kobj; + struct mutex default_lock; + struct regmap *regmap; + struct sma1307_setting_file set; + const struct sma1307_pll_match *pll_matches; + const struct sma1307_data *data; + unsigned int cur_vol; + unsigned int format; + unsigned int frame_size; + unsigned int init_vol; + unsigned int last_bclk; + unsigned int otp_trm2; + unsigned int otp_trm3; + unsigned int rev_num; + unsigned int sys_clk_id; + unsigned int tdm_slot0_rx; + unsigned int tdm_slot1_rx; + unsigned int tdm_slot0_tx; + unsigned int tdm_slot1_tx; + unsigned int tsdw_cnt; +}; + +static const struct sma1307_pll_match sma1307_pll_matches[] = { + /* in_clk_name, out_clk_name, input_clk post_n, n, vco, p_cp */ + PLL_MATCH("1.411MHz", "24.554MHz", + 1411200, 0x06, 0xD1, 0x88, 0x00), + PLL_MATCH("1.536MHz", "24.576MHz", + 1536000, 0x06, 0xC0, 0x88, 0x00), + PLL_MATCH("2.822MHz", "24.554MHz", + 2822400, 0x06, 0xD1, 0x88, 0x04), + PLL_MATCH("3.072MHz", "24.576MHz", + 3072000, 0x06, 0x60, 0x88, 0x00), + PLL_MATCH("6.144MHz", "24.576MHz", + 6144000, 0x06, 0x60, 0x88, 0x04), + PLL_MATCH("12.288MHz", "24.576MHz", + 12288000, 0x06, 0x60, 0x88, 0x08), + PLL_MATCH("19.2MHz", "24.48MHz", + 19200000, 0x06, 0x7B, 0x88, 0x0C), + PLL_MATCH("24.576MHz", "24.576MHz", + 24576000, 0x06, 0x60, 0x88, 0x0C), +}; + +static struct snd_soc_component *sma1307_amp_component; + +static void sma1307_startup(struct snd_soc_component *); +static void sma1307_shutdown(struct snd_soc_component *); +static void sma1307_reset(struct snd_soc_component *); +static void sma1307_set_binary(struct snd_soc_component *); +static void sma1307_set_default(struct snd_soc_component *); + +/* Initial register value - 6.0W SPK (8ohm load) */ +static const struct reg_default sma1307_reg_def[] = { + { 0x00, 0x80 }, + { 0x01, 0x00 }, + { 0x02, 0x52 }, + { 0x03, 0x4C }, + { 0x04, 0x47 }, + { 0x05, 0x42 }, + { 0x06, 0x40 }, + { 0x07, 0x40 }, + { 0x08, 0x3C }, + { 0x09, 0x2F }, + { 0x0A, 0x32 }, + { 0x0B, 0x50 }, + { 0x0C, 0x8C }, + { 0x0D, 0x00 }, + { 0x0E, 0x3F }, + { 0x0F, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x09 }, + { 0x14, 0x12 }, + { 0x1C, 0x00 }, + { 0x1D, 0x85 }, + { 0x1E, 0xA1 }, + { 0x1F, 0x67 }, + { 0x22, 0x00 }, + { 0x23, 0x1F }, + { 0x24, 0x7A }, + { 0x25, 0x00 }, + { 0x26, 0xFF }, + { 0x27, 0x39 }, + { 0x28, 0x54 }, + { 0x29, 0x92 }, + { 0x2A, 0xB0 }, + { 0x2B, 0xED }, + { 0x2C, 0xED }, + { 0x2D, 0xFF }, + { 0x2E, 0xFF }, + { 0x2F, 0xFF }, + { 0x30, 0xFF }, + { 0x31, 0xFF }, + { 0x32, 0xFF }, + { 0x34, 0x01 }, + { 0x35, 0x17 }, + { 0x36, 0x92 }, + { 0x37, 0x00 }, + { 0x38, 0x01 }, + { 0x39, 0x10 }, + { 0x3E, 0x01 }, + { 0x3F, 0x08 }, + { 0x8B, 0x05 }, + { 0x8C, 0x50 }, + { 0x8D, 0x80 }, + { 0x8E, 0x10 }, + { 0x8F, 0x02 }, + { 0x90, 0x02 }, + { 0x91, 0x83 }, + { 0x92, 0xC0 }, + { 0x93, 0x00 }, + { 0x94, 0xA4 }, + { 0x95, 0x74 }, + { 0x96, 0x57 }, + { 0xA2, 0xCC }, + { 0xA3, 0x28 }, + { 0xA4, 0x40 }, + { 0xA5, 0x01 }, + { 0xA6, 0x41 }, + { 0xA7, 0x08 }, + { 0xA8, 0x04 }, + { 0xA9, 0x27 }, + { 0xAA, 0x10 }, + { 0xAB, 0x10 }, + { 0xAC, 0x10 }, + { 0xAD, 0x0F }, + { 0xAE, 0xCD }, + { 0xAF, 0x70 }, + { 0xB0, 0x03 }, + { 0xB1, 0xEF }, + { 0xB2, 0x03 }, + { 0xB3, 0xEF }, + { 0xB4, 0xF3 }, + { 0xB5, 0x3D }, +}; + +static bool sma1307_readable_register(struct device *dev, unsigned int reg) +{ + if (reg > SMA1307_FF_DEVICE_INDEX) + return false; + + switch (reg) { + case SMA1307_00_SYSTEM_CTRL ... SMA1307_1F_TONE_FINE_VOLUME: + case SMA1307_22_COMP_HYS_SEL ... SMA1307_32_BROWN_OUT_PROT19: + case SMA1307_34_OCP_SPK ... SMA1307_39_PMT_NZ_VAL: + case SMA1307_3B_TEST1 ... SMA1307_3F_ATEST2: + case SMA1307_8B_PLL_POST_N ... SMA1307_9A_OTP_TRM3: + case SMA1307_A0_PAD_CTRL0 ... SMA1307_BE_MCBS_CTRL2: + case SMA1307_F5_READY_FOR_V_SAR: + case SMA1307_F7_READY_FOR_T_SAR ... SMA1307_FF_DEVICE_INDEX: + break; + default: + return false; + } + return true; +} + +static bool sma1307_writeable_register(struct device *dev, unsigned int reg) +{ + if (reg > SMA1307_FF_DEVICE_INDEX) + return false; + + switch (reg) { + case SMA1307_00_SYSTEM_CTRL ... SMA1307_1F_TONE_FINE_VOLUME: + case SMA1307_22_COMP_HYS_SEL ... SMA1307_32_BROWN_OUT_PROT19: + case SMA1307_34_OCP_SPK ... SMA1307_39_PMT_NZ_VAL: + case SMA1307_3B_TEST1 ... SMA1307_3F_ATEST2: + case SMA1307_8B_PLL_POST_N ... SMA1307_9A_OTP_TRM3: + case SMA1307_A0_PAD_CTRL0 ... SMA1307_BE_MCBS_CTRL2: + break; + default: + return false; + } + return true; +} + +static bool sma1307_volatile_register(struct device *dev, unsigned int reg) +{ + if (reg > SMA1307_FF_DEVICE_INDEX) + return false; + + switch (reg) { + case SMA1307_F8_STATUS_T1 ... SMA1307_FF_DEVICE_INDEX: + break; + default: + return false; + } + return true; +} + +/* DB scale conversion of speaker volume */ +static const DECLARE_TLV_DB_SCALE(sma1307_spk_tlv, -6000, 50, 0); + +static const char *const sma1307_aif_in_source_text[] = { + "Mono", "Left", "Right" +}; + +static const char *const sma1307_sdo_setting_text[] = { + "Data_One_48k", "Data_Two_48k", "Data_Two_24k", + "Clk_PLL", "Clk_OSC" +}; + +static const char *const sma1307_aif_out_source_text[] = { + "Disable", "After_FmtC", "After_Mixer", "After_DSP", + "Vrms2_Avg", "Battery", "Temperature", "After_Delay" +}; + +static const char *const sma1307_tdm_slot_text[] = { + "Slot0", "Slot1", "Slot2", "Slot3", + "Slot4", "Slot5", "Slot6", "Slot7" +}; + +static const char *const sma1307_binary_mode_text[] = { + "Mode0", "Mode1", "Mode2", "Mode3", "Mode4" +}; + +static const char *const sma1307_reset_text[] = { + "Reset" +}; + +static const struct soc_enum sma1307_aif_in_source_enum = +SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_aif_in_source_text), + sma1307_aif_in_source_text); +static const struct soc_enum sma1307_sdo_setting_enum = +SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_sdo_setting_text), + sma1307_sdo_setting_text); +static const struct soc_enum sma1307_aif_out_source_enum = +SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_aif_out_source_text), + sma1307_aif_out_source_text); +static const struct soc_enum sma1307_tdm_slot_enum = +SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_tdm_slot_text), + sma1307_tdm_slot_text); +static const struct soc_enum sma1307_binary_mode_enum = +SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_binary_mode_text), + sma1307_binary_mode_text); +static const struct soc_enum sma1307_reset_enum = +SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_reset_text), + sma1307_reset_text); + +static int sma1307_force_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = (int)sma1307->force_mute_status; + + return 0; +} + +static int sma1307_force_mute_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + bool change = false, val = (bool)ucontrol->value.integer.value[0]; + + if (sma1307->force_mute_status == val) { + change = false; + } else { + change = true; + sma1307->force_mute_status = val; + } + + return change; +} + +static int sma1307_tdm_slot_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + int val1, val2; + + regmap_read(sma1307->regmap, SMA1307_A5_TDM1, &val1); + regmap_read(sma1307->regmap, SMA1307_A6_TDM2, &val2); + + if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX0_POS_NAME)) { + ucontrol->value.integer.value[0] + = (val1 & SMA1307_TDM_SLOT0_RX_POS_MASK) >> 3; + sma1307->tdm_slot0_rx = ucontrol->value.integer.value[0]; + } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX1_POS_NAME)) { + ucontrol->value.integer.value[0] + = val1 & SMA1307_TDM_SLOT1_RX_POS_MASK; + sma1307->tdm_slot1_rx = ucontrol->value.integer.value[0]; + } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX0_POS_NAME)) { + ucontrol->value.integer.value[0] + = (val2 & SMA1307_TDM_SLOT0_TX_POS_MASK) >> 3; + sma1307->tdm_slot0_tx = ucontrol->value.integer.value[0]; + } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX1_POS_NAME)) { + ucontrol->value.integer.value[0] + = val2 & SMA1307_TDM_SLOT1_TX_POS_MASK; + sma1307->tdm_slot1_tx = ucontrol->value.integer.value[0]; + } else { + return -EINVAL; + } + + return 0; +} + +static int sma1307_tdm_slot_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + int val = (int)ucontrol->value.integer.value[0]; + bool change; + + if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX0_POS_NAME)) { + if (sma1307->tdm_slot0_rx == val) + change = false; + else { + change = true; + sma1307->tdm_slot0_rx = val; + regmap_update_bits(sma1307->regmap, SMA1307_A5_TDM1, + SMA1307_TDM_SLOT0_RX_POS_MASK, val << 3); + } + } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX1_POS_NAME)) { + if (sma1307->tdm_slot1_rx == val) + change = false; + else { + change = true; + sma1307->tdm_slot1_rx = val; + regmap_update_bits(sma1307->regmap, SMA1307_A5_TDM1, + SMA1307_TDM_SLOT1_RX_POS_MASK, val); + } + } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX0_POS_NAME)) { + if (sma1307->tdm_slot0_tx == val) + change = false; + else { + change = true; + sma1307->tdm_slot0_tx = val; + regmap_update_bits(sma1307->regmap, SMA1307_A6_TDM2, + SMA1307_TDM_SLOT0_TX_POS_MASK, val << 3); + } + } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX1_POS_NAME)) { + if (sma1307->tdm_slot1_tx == val) + change = false; + else { + change = true; + sma1307->tdm_slot1_tx = val; + regmap_update_bits(sma1307->regmap, SMA1307_A6_TDM2, + SMA1307_TDM_SLOT1_TX_POS_MASK, val); + } + } else { + dev_err(sma1307->dev, "%s: Invalid Control ID - %s\n", + __func__, kcontrol->id.name); + return -EINVAL; + } + + return change; +} + +static int sma1307_sw_ot1_prot_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = (int)sma1307->sw_ot1_prot; + + return 0; +} + +static int sma1307_sw_ot1_prot_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + bool change = false, val = (bool)ucontrol->value.integer.value[0]; + + if (sma1307->sw_ot1_prot == val) + change = false; + else { + change = true; + sma1307->sw_ot1_prot = val; + } + + return change; +} + +static int sma1307_check_fault_status_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = (int)sma1307->check_fault_status; + + return 0; +} + +static int sma1307_check_fault_status_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + bool change = false, val = (bool)ucontrol->value.integer.value[0]; + + if (sma1307->check_fault_status == val) { + change = false; + } else { + change = true; + sma1307->check_fault_status = val; + } + + return change; +} + +static int sma1307_check_fault_period_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = sma1307->check_fault_period; + + return 0; +} + +static int sma1307_check_fault_period_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + bool change = false; + int val = ucontrol->value.integer.value[0]; + + if (val < mc->min || val > mc->max) + return -EINVAL; + if (sma1307->check_fault_period == val) { + change = false; + } else { + change = true; + sma1307->check_fault_period = val; + } + + return change; +} + +static int sma1307_reset_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + regmap_update_bits(sma1307->regmap, SMA1307_00_SYSTEM_CTRL, + SMA1307_RESET_MASK, SMA1307_RESET_ON); + sma1307_reset(component); + + snd_ctl_notify(component->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, + &kcontrol->id); + + return true; +} + +static int sma1307_binary_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct sma1307_priv *sma1307 = snd_kcontrol_chip(kcontrol); + + sma1307->binary_mode = (int)ucontrol->value.enumerated.item[0]; + if (sma1307->set.status) + sma1307_set_binary(component); + + return snd_soc_put_enum_double(kcontrol, ucontrol); +} + +static void sma1307_startup(struct snd_soc_component *component) +{ + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + regmap_update_bits(sma1307->regmap, SMA1307_A2_TOP_MAN1, + SMA1307_PLL_MASK, SMA1307_PLL_ON); + regmap_update_bits(sma1307->regmap, SMA1307_00_SYSTEM_CTRL, + SMA1307_POWER_MASK, SMA1307_POWER_ON); + + if (sma1307->amp_mode == SMA1307_MONO_MODE) { + regmap_update_bits(sma1307->regmap, + SMA1307_10_SYSTEM_CTRL1, + SMA1307_SPK_MODE_MASK, + SMA1307_SPK_MONO); + } else { + regmap_update_bits(sma1307->regmap, + SMA1307_10_SYSTEM_CTRL1, + SMA1307_SPK_MODE_MASK, + SMA1307_SPK_STEREO); + } + + if (sma1307->check_fault_status) { + if (sma1307->check_fault_period > 0) + queue_delayed_work(system_freezable_wq, + &sma1307->check_fault_work, + sma1307->check_fault_period * HZ); + else + queue_delayed_work(system_freezable_wq, + &sma1307->check_fault_work, + CHECK_PERIOD_TIME * HZ); + } +} + +static void sma1307_shutdown(struct snd_soc_component *component) +{ + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + /* for SMA1307A */ + cancel_delayed_work_sync(&sma1307->check_fault_work); + + regmap_update_bits(sma1307->regmap, SMA1307_0E_MUTE_VOL_CTRL, + SMA1307_SPK_MUTE_MASK, SMA1307_SPK_MUTE); + /* Need to wait time for mute slope */ + msleep(55); + + regmap_update_bits(sma1307->regmap, SMA1307_10_SYSTEM_CTRL1, + SMA1307_SPK_MODE_MASK, SMA1307_SPK_OFF); + regmap_update_bits(sma1307->regmap, SMA1307_A2_TOP_MAN1, + SMA1307_PLL_MASK, SMA1307_PLL_OFF); + regmap_update_bits(sma1307->regmap, SMA1307_00_SYSTEM_CTRL, + SMA1307_POWER_MASK, SMA1307_POWER_OFF); +} + +static int sma1307_aif_in_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + unsigned int mux = sma1307->dapm_aif_in; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + switch (mux) { + case SMA1307_MONO_MODE: + regmap_update_bits(sma1307->regmap, + SMA1307_11_SYSTEM_CTRL2, + SMA1307_MONOMIX_MASK, + SMA1307_MONOMIX_ON); + break; + case SMA1307_LEFT_MODE: + regmap_update_bits(sma1307->regmap, + SMA1307_11_SYSTEM_CTRL2, + SMA1307_MONOMIX_MASK, + SMA1307_MONOMIX_OFF); + regmap_update_bits(sma1307->regmap, + SMA1307_11_SYSTEM_CTRL2, + SMA1307_LR_DATA_SW_MASK, + SMA1307_LR_DATA_SW_NORMAL); + break; + case SMA1307_RIGHT_MODE: + regmap_update_bits(sma1307->regmap, + SMA1307_11_SYSTEM_CTRL2, + SMA1307_MONOMIX_MASK, + SMA1307_MONOMIX_OFF); + regmap_update_bits(sma1307->regmap, + SMA1307_11_SYSTEM_CTRL2, + SMA1307_LR_DATA_SW_MASK, + SMA1307_LR_DATA_SW_SWAP); + break; + default: + + dev_err(sma1307->dev, "%s: Invalid value (%d)\n", + __func__, mux); + return -EINVAL; + } + sma1307->amp_mode = mux; + break; + } + return 0; +} + +static int sma1307_sdo_setting_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + unsigned int mux = sma1307->dapm_sdo_setting; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + switch (mux) { + case SMA1307_OUT_DATA_ONE_48K: + regmap_update_bits(sma1307->regmap, + SMA1307_A2_TOP_MAN1, + SMA1307_SDO_OUTPUT2_MASK, + SMA1307_ONE_SDO_PER_CH); + regmap_update_bits(sma1307->regmap, + SMA1307_A3_TOP_MAN2, + SMA1307_SDO_OUTPUT3_MASK + | + SMA1307_DATA_CLK_SEL_MASK, + SMA1307_SDO_OUTPUT3_DIS + | SMA1307_SDO_DATA); + break; + case SMA1307_OUT_DATA_TWO_48K: + regmap_update_bits(sma1307->regmap, + SMA1307_A2_TOP_MAN1, + SMA1307_SDO_OUTPUT2_MASK, + SMA1307_TWO_SDO_PER_CH); + regmap_update_bits(sma1307->regmap, + SMA1307_A3_TOP_MAN2, + SMA1307_SDO_OUTPUT3_MASK + | + SMA1307_DATA_CLK_SEL_MASK, + SMA1307_SDO_OUTPUT3_DIS + | SMA1307_SDO_DATA); + break; + case SMA1307_OUT_DATA_TWO_24K: + regmap_update_bits(sma1307->regmap, + SMA1307_A2_TOP_MAN1, + SMA1307_SDO_OUTPUT2_MASK, + SMA1307_TWO_SDO_PER_CH); + regmap_update_bits(sma1307->regmap, + SMA1307_A3_TOP_MAN2, + SMA1307_SDO_OUTPUT3_MASK + | + SMA1307_DATA_CLK_SEL_MASK, + SMA1307_TWO_SDO_PER_CH_24K + | SMA1307_SDO_DATA); + break; + case SMA1307_OUT_CLK_PLL: + regmap_update_bits(sma1307->regmap, + SMA1307_A3_TOP_MAN2, + SMA1307_DATA_CLK_SEL_MASK, + SMA1307_SDO_CLK_PLL); + + break; + case SMA1307_OUT_CLK_OSC: + regmap_update_bits(sma1307->regmap, + SMA1307_A3_TOP_MAN2, + SMA1307_DATA_CLK_SEL_MASK, + SMA1307_SDO_CLK_OSC); + + break; + default: + dev_err(sma1307->dev, "%s: Invalid value (%d)\n", + __func__, mux); + return -EINVAL; + } + break; + } + return 0; +} + +static int sma1307_aif_out_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + unsigned int mux = 0, val = 0, mask = 0; + + if (!strcmp(w->name, SMA1307_AIF_OUT0_NAME)) { + mux = sma1307->dapm_aif_out0; + val = mux; + mask = SMA1307_SDO_OUT0_SEL_MASK; + } else if (!strcmp(w->name, SMA1307_AIF_OUT1_NAME)) { + mux = sma1307->dapm_aif_out1; + val = mux << 3; + mask = SMA1307_SDO_OUT1_SEL_MASK; + } else { + dev_err(sma1307->dev, "%s: Invalid widget - %s\n", + __func__, w->name); + return -EINVAL; + } + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + regmap_update_bits(sma1307->regmap, SMA1307_09_OUTPUT_CTRL, + mask, val); + break; + } + return 0; +} + +static int sma1307_sdo_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + regmap_update_bits(sma1307->regmap, + SMA1307_09_OUTPUT_CTRL, + SMA1307_PORT_CONFIG_MASK, + SMA1307_OUTPUT_PORT_ENABLE); + regmap_update_bits(sma1307->regmap, + SMA1307_A3_TOP_MAN2, + SMA1307_SDO_OUTPUT_MASK, + SMA1307_LOGIC_OUTPUT); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(sma1307->regmap, + SMA1307_09_OUTPUT_CTRL, + SMA1307_PORT_CONFIG_MASK, + SMA1307_INPUT_PORT_ONLY); + regmap_update_bits(sma1307->regmap, + SMA1307_A3_TOP_MAN2, + SMA1307_SDO_OUTPUT_MASK, + SMA1307_HIGH_Z_OUTPUT); + break; + } + return 0; +} + +static int sma1307_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + sma1307_startup(component); + break; + case SND_SOC_DAPM_PRE_PMD: + sma1307_shutdown(component); + break; + } + return 0; +} + +static int sma1307_dapm_aif_in_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct sma1307_priv *sma1307 = + snd_soc_component_get_drvdata(dapm->component); + + ucontrol->value.enumerated.item[0] = (unsigned int)sma1307->dapm_aif_in; + snd_soc_dapm_put_enum_double(kcontrol, ucontrol); + + return 0; +} + +static int sma1307_dapm_aif_in_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct sma1307_priv *sma1307 = + snd_soc_component_get_drvdata(dapm->component); + int val = (int)ucontrol->value.enumerated.item[0]; + bool change; + + if ((val < 0) || (val >= ARRAY_SIZE(sma1307_aif_in_source_text))) { + dev_err(sma1307->dev, "%s: Out of range\n", __func__); + return -EINVAL; + } + + if (sma1307->dapm_aif_in != val) { + change = true; + sma1307->dapm_aif_in = val; + } else + change = false; + + snd_soc_dapm_put_enum_double(kcontrol, ucontrol); + + return change; +} + +static int sma1307_dapm_sdo_setting_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct sma1307_priv *sma1307 = + snd_soc_component_get_drvdata(dapm->component); + + ucontrol->value.enumerated.item[0] = + (unsigned int)sma1307->dapm_sdo_setting; + snd_soc_dapm_put_enum_double(kcontrol, ucontrol); + + return 0; +} + +static int sma1307_dapm_sdo_setting_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct sma1307_priv *sma1307 = + snd_soc_component_get_drvdata(dapm->component); + int val = (int)ucontrol->value.enumerated.item[0]; + bool change; + + if ((val < 0) || (val >= ARRAY_SIZE(sma1307_sdo_setting_text))) { + dev_err(sma1307->dev, "%s: Out of range\n", __func__); + return -EINVAL; + } + + if (sma1307->dapm_sdo_setting != val) { + change = true; + sma1307->dapm_sdo_setting = val; + } else + change = false; + + snd_soc_dapm_put_enum_double(kcontrol, ucontrol); + + return change; +} + +static int sma1307_dapm_aif_out_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct sma1307_priv *sma1307 = + snd_soc_component_get_drvdata(dapm->component); + unsigned int val = 0; + + if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT0_NAME)) { + val = (unsigned int)sma1307->dapm_aif_out0; + } else if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT1_NAME)) { + val = (unsigned int)sma1307->dapm_aif_out1; + } else { + dev_err(sma1307->dev, "%s: Invalid Control ID - %s\n", + __func__, kcontrol->id.name); + return -EINVAL; + } + ucontrol->value.enumerated.item[0] = val; + snd_soc_dapm_put_enum_double(kcontrol, ucontrol); + + return 0; +} + +static int sma1307_dapm_aif_out_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct sma1307_priv *sma1307 = + snd_soc_component_get_drvdata(dapm->component); + int val = (int)ucontrol->value.enumerated.item[0]; + bool change; + + if ((val < 0) || (val >= ARRAY_SIZE(sma1307_aif_out_source_text))) { + dev_err(sma1307->dev, "%s: Out of range\n", __func__); + return -EINVAL; + } + + if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT0_NAME)) { + if (sma1307->dapm_aif_out0 != val) { + change = true; + sma1307->dapm_aif_out0 = val; + } else + change = false; + } else if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT1_NAME)) { + if (sma1307->dapm_aif_out1 != val) { + change = true; + sma1307->dapm_aif_out1 = val; + } else + change = false; + } else { + dev_err(sma1307->dev, "%s: Invalid Control ID - %s\n", + __func__, kcontrol->id.name); + return -EINVAL; + } + + snd_soc_dapm_put_enum_double(kcontrol, ucontrol); + + return change; +} + +static int sma1307_dapm_sdo_enable_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct sma1307_priv *sma1307 = + snd_soc_component_get_drvdata(dapm->component); + + ucontrol->value.integer.value[0] = (long)sma1307->dapm_sdo_en; + snd_soc_dapm_put_volsw(kcontrol, ucontrol); + + return 0; +} + +static int sma1307_dapm_sdo_enable_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct sma1307_priv *sma1307 = + snd_soc_component_get_drvdata(dapm->component); + int val = (int)ucontrol->value.integer.value[0]; + bool change; + + if ((val < 0) || (val > 1)) { + dev_err(sma1307->dev, "%s: Out of range\n", __func__); + return -EINVAL; + } + + if (sma1307->dapm_sdo_en != val) { + change = true; + sma1307->dapm_sdo_en = val; + } else + change = false; + + snd_soc_dapm_put_volsw(kcontrol, ucontrol); + + return change; +} + +static const struct snd_kcontrol_new sma1307_aif_in_source_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SMA1307_AIF_IN_NAME, + .info = snd_soc_info_enum_double, + .get = sma1307_dapm_aif_in_get, + .put = sma1307_dapm_aif_in_put, + .private_value = (unsigned long)&sma1307_aif_in_source_enum +}; + +static const struct snd_kcontrol_new sma1307_sdo_setting_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "SDO Setting", + .info = snd_soc_info_enum_double, + .get = sma1307_dapm_sdo_setting_get, + .put = sma1307_dapm_sdo_setting_put, + .private_value = (unsigned long)&sma1307_sdo_setting_enum +}; + +static const struct snd_kcontrol_new sma1307_aif_out0_source_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SMA1307_AIF_OUT0_NAME, + .info = snd_soc_info_enum_double, + .get = sma1307_dapm_aif_out_get, + .put = sma1307_dapm_aif_out_put, + .private_value = (unsigned long)&sma1307_aif_out_source_enum +}; + +static const struct snd_kcontrol_new sma1307_aif_out1_source_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SMA1307_AIF_OUT1_NAME, + .info = snd_soc_info_enum_double, + .get = sma1307_dapm_aif_out_get, + .put = sma1307_dapm_aif_out_put, + .private_value = (unsigned long)&sma1307_aif_out_source_enum +}; + +static const struct snd_kcontrol_new sma1307_sdo_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Switch", + .info = snd_soc_info_volsw, + .get = sma1307_dapm_sdo_enable_get, + .put = sma1307_dapm_sdo_enable_put, + .private_value = SOC_SINGLE_VALUE(SND_SOC_NOPM, 0, 1, 0, 0) +}; + +static const struct snd_kcontrol_new sma1307_enable_control = + SOC_DAPM_SINGLE("Switch", SMA1307_00_SYSTEM_CTRL, 0, 1, 0); + +static const struct snd_kcontrol_new sma1307_binary_mode_control[] = { + SOC_ENUM_EXT("Binary Mode", sma1307_binary_mode_enum, + snd_soc_get_enum_double, sma1307_binary_mode_put), +}; + +static const struct snd_kcontrol_new sma1307_snd_controls[] = { + SOC_SINGLE_TLV(SMA1307_VOL_CTRL_NAME, SMA1307_0A_SPK_VOL, + 0, 167, 1, sma1307_spk_tlv), + SOC_ENUM_EXT(SMA1307_TDM_RX0_POS_NAME, sma1307_tdm_slot_enum, + sma1307_tdm_slot_get, sma1307_tdm_slot_put), + SOC_ENUM_EXT(SMA1307_TDM_RX1_POS_NAME, sma1307_tdm_slot_enum, + sma1307_tdm_slot_get, sma1307_tdm_slot_put), + SOC_ENUM_EXT(SMA1307_TDM_TX0_POS_NAME, sma1307_tdm_slot_enum, + sma1307_tdm_slot_get, sma1307_tdm_slot_put), + SOC_ENUM_EXT(SMA1307_TDM_TX1_POS_NAME, sma1307_tdm_slot_enum, + sma1307_tdm_slot_get, sma1307_tdm_slot_put), + SOC_ENUM_EXT(SMA1307_RESET_CTRL_NAME, sma1307_reset_enum, + snd_soc_get_enum_double, sma1307_reset_put), + SOC_SINGLE_BOOL_EXT(SMA1307_FORCE_MUTE_CTRL_NAME, 0, + sma1307_force_mute_get, sma1307_force_mute_put), + SOC_SINGLE_BOOL_EXT(SMA1307_OT1_SW_PROT_CTRL_NAME, 0, + sma1307_sw_ot1_prot_get, sma1307_sw_ot1_prot_put), + SOC_SINGLE_BOOL_EXT(SMA1307_CHECK_FAULT_STATUS_NAME, 0, + sma1307_check_fault_status_get, + sma1307_check_fault_status_put), + SOC_SINGLE_EXT(SMA1307_CHECK_FAULT_PERIOD_NAME, SND_SOC_NOPM, 0, 600, 0, + sma1307_check_fault_period_get, + sma1307_check_fault_period_put), +}; + +static const struct snd_soc_dapm_widget sma1307_dapm_widgets[] = { + /* platform domain */ + SND_SOC_DAPM_OUTPUT("SPK"), + SND_SOC_DAPM_INPUT("SDO"), + + /* path domain */ + SND_SOC_DAPM_MUX_E(SMA1307_AIF_IN_NAME, SND_SOC_NOPM, 0, 0, + &sma1307_aif_in_source_control, + sma1307_aif_in_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_MUX_E("SDO Setting", SND_SOC_NOPM, 0, 0, + &sma1307_sdo_setting_control, + sma1307_sdo_setting_event, + SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_MUX_E(SMA1307_AIF_OUT0_NAME, SND_SOC_NOPM, 0, 0, + &sma1307_aif_out0_source_control, + sma1307_aif_out_event, + SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_MUX_E(SMA1307_AIF_OUT1_NAME, SND_SOC_NOPM, 0, 0, + &sma1307_aif_out1_source_control, + sma1307_aif_out_event, + SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_SWITCH_E("SDO Enable", SND_SOC_NOPM, 0, 0, + &sma1307_sdo_control, + sma1307_sdo_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER("Entry", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV_E("AMP Power", SND_SOC_NOPM, 0, 0, NULL, 0, + sma1307_power_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD | + SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_SWITCH("AMP Enable", SND_SOC_NOPM, 0, 0, + &sma1307_enable_control), + + /* stream domain */ + SND_SOC_DAPM_AIF_IN("AIF IN", "Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIF OUT", "Capture", 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route sma1307_audio_map[] = { + /* Playback */ + { "AIF IN Source", "Mono", "AIF IN" }, + { "AIF IN Source", "Left", "AIF IN" }, + { "AIF IN Source", "Right", "AIF IN" }, + + { "SDO Enable", "Switch", "AIF IN" }, + + { "SDO Setting", "Data_One_48k", "SDO Enable" }, + { "SDO Setting", "Data_Two_48k", "SDO Enable" }, + { "SDO Setting", "Data_Two_24k", "SDO Enable" }, + { "SDO Setting", "Clk_PLL", "SDO Enable" }, + { "SDO Setting", "Clk_OSC", "SDO Enable" }, + + { "AIF OUT0 Source", "Disable", "SDO Setting" }, + { "AIF OUT0 Source", "After_FmtC", "SDO Setting" }, + { "AIF OUT0 Source", "After_Mixer", "SDO Setting" }, + { "AIF OUT0 Source", "After_DSP", "SDO Setting" }, + { "AIF OUT0 Source", "Vrms2_Avg", "SDO Setting" }, + { "AIF OUT0 Source", "Battery", "SDO Setting" }, + { "AIF OUT0 Source", "Temperature", "SDO Setting" }, + { "AIF OUT0 Source", "After_Delay", "SDO Setting" }, + + { "AIF OUT1 Source", "Disable", "SDO Setting" }, + { "AIF OUT1 Source", "After_FmtC", "SDO Setting" }, + { "AIF OUT1 Source", "After_Mixer", "SDO Setting" }, + { "AIF OUT1 Source", "After_DSP", "SDO Setting" }, + { "AIF OUT1 Source", "Vrms2_Avg", "SDO Setting" }, + { "AIF OUT1 Source", "Battery", "SDO Setting" }, + { "AIF OUT1 Source", "Temperature", "SDO Setting" }, + { "AIF OUT1 Source", "After_Delay", "SDO Setting" }, + + { "Entry", NULL, "AIF OUT0 Source" }, + { "Entry", NULL, "AIF OUT1 Source" }, + { "Entry", NULL, "AIF IN Source" }, + + { "AMP Power", NULL, "Entry" }, + + { "AMP Enable", "Switch", "AMP Power" }, + { "SPK", NULL, "AMP Enable" }, + + /* Capture */ + { "AIF OUT", NULL, "AMP Enable" }, +}; + +static void sma1307_setup_pll(struct snd_soc_component *component, + unsigned int bclk) +{ + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + int i = 0; + + dev_dbg(component->dev, "%s: BCLK = %dHz\n", __func__, bclk); + + if (sma1307->sys_clk_id == SMA1307_PLL_CLKIN_MCLK) { + dev_warn(component->dev, "%s: MCLK is not supported\n", + __func__); + } else if (sma1307->sys_clk_id == SMA1307_PLL_CLKIN_BCLK) { + for (i = 0; i < sma1307->num_of_pll_matches; i++) { + if (sma1307->pll_matches[i].input_clk == bclk) + break; + } + if (i == sma1307->num_of_pll_matches) { + dev_warn(component->dev, + "%s: No matching value between pll table and SCK\n", + __func__); + return; + } + + regmap_update_bits(sma1307->regmap, + SMA1307_A2_TOP_MAN1, + SMA1307_PLL_MASK, SMA1307_PLL_ON); + } + + regmap_write(sma1307->regmap, SMA1307_8B_PLL_POST_N, + sma1307->pll_matches[i].post_n); + regmap_write(sma1307->regmap, SMA1307_8C_PLL_N, + sma1307->pll_matches[i].n); + regmap_write(sma1307->regmap, SMA1307_8D_PLL_A_SETTING, + sma1307->pll_matches[i].vco); + regmap_write(sma1307->regmap, SMA1307_8E_PLL_P_CP, + sma1307->pll_matches[i].p_cp); +} + +static int sma1307_dai_hw_params_amp(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + unsigned int bclk = 0; + int ret = 0; + + if (sma1307->format == SND_SOC_DAIFMT_DSP_A) + bclk = params_rate(params) * sma1307->frame_size; + else + bclk = params_rate(params) * params_physical_width(params) + * params_channels(params); + + dev_dbg(component->dev, + "%s: rate = %d : bit size = %d : channel = %d\n", + __func__, params_rate(params), params_width(params), + params_channels(params)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (sma1307->sys_clk_id == SMA1307_PLL_CLKIN_BCLK) { + if (sma1307->last_bclk != bclk) { + sma1307_setup_pll(component, bclk); + sma1307->last_bclk = bclk; + } + } + + switch (params_rate(params)) { + case 8000: + case 12000: + case 16000: + case 24000: + case 32000: + case 44100: + case 48000: + break; + + case 96000: + dev_warn(component->dev, + "%s: %d rate not support SDO\n", __func__, + params_rate(params)); + break; + + default: + dev_err(component->dev, "%s: not support rate : %d\n", + __func__, params_rate(params)); + + return -EINVAL; + } + + /* substream->stream is SNDRV_PCM_STREAM_CAPTURE */ + } else { + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + regmap_update_bits(sma1307->regmap, + SMA1307_A4_TOP_MAN3, + SMA1307_SCK_RATE_MASK + | + SMA1307_DATA_WIDTH_MASK, + SMA1307_SCK_32FS | + SMA1307_DATA_16BIT); + break; + + case SNDRV_PCM_FORMAT_S24_LE: + regmap_update_bits(sma1307->regmap, + SMA1307_A4_TOP_MAN3, + SMA1307_SCK_RATE_MASK + | + SMA1307_DATA_WIDTH_MASK, + SMA1307_SCK_64FS | + SMA1307_DATA_24BIT); + break; + + case SNDRV_PCM_FORMAT_S32_LE: + regmap_update_bits(sma1307->regmap, + SMA1307_A4_TOP_MAN3, + SMA1307_SCK_RATE_MASK + | + SMA1307_DATA_WIDTH_MASK, + SMA1307_SCK_64FS | + SMA1307_DATA_24BIT); + break; + default: + dev_err(component->dev, + "%s: not support data bit : %d\n", __func__, + params_format(params)); + return -EINVAL; + } + } + + switch (sma1307->format) { + case SND_SOC_DAIFMT_I2S: + regmap_update_bits(sma1307->regmap, + SMA1307_01_INPUT_CTRL1, + SMA1307_I2S_MODE_MASK, + SMA1307_STANDARD_I2S); + regmap_update_bits(sma1307->regmap, + SMA1307_A4_TOP_MAN3, + SMA1307_INTERFACE_MASK, + SMA1307_I2S_FORMAT); + break; + case SND_SOC_DAIFMT_LEFT_J: + regmap_update_bits(sma1307->regmap, + SMA1307_01_INPUT_CTRL1, + SMA1307_I2S_MODE_MASK, SMA1307_LJ); + regmap_update_bits(sma1307->regmap, + SMA1307_A4_TOP_MAN3, + SMA1307_INTERFACE_MASK, + SMA1307_LJ_FORMAT); + break; + case SND_SOC_DAIFMT_RIGHT_J: + switch (params_width(params)) { + case 16: + regmap_update_bits(sma1307->regmap, + SMA1307_01_INPUT_CTRL1, + SMA1307_I2S_MODE_MASK, + SMA1307_RJ_16BIT); + break; + case 24: + case 32: + regmap_update_bits(sma1307->regmap, + SMA1307_01_INPUT_CTRL1, + SMA1307_I2S_MODE_MASK, + SMA1307_RJ_24BIT); + break; + } + break; + case SND_SOC_DAIFMT_DSP_A: + regmap_update_bits(sma1307->regmap, + SMA1307_01_INPUT_CTRL1, + SMA1307_I2S_MODE_MASK, + SMA1307_STANDARD_I2S); + regmap_update_bits(sma1307->regmap, + SMA1307_A4_TOP_MAN3, + SMA1307_INTERFACE_MASK, + SMA1307_TDM_FORMAT); + break; + } + + switch (params_width(params)) { + case 16: + case 24: + case 32: + break; + default: + dev_err(component->dev, + "%s: not support data bit : %d\n", __func__, + params_format(params)); + return -EINVAL; + } + if (ret < 0) + return -EINVAL; + + return 0; +} + +static int sma1307_dai_set_sysclk_amp(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_component *component = dai->component; + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + switch (clk_id) { + case SMA1307_EXTERNAL_CLOCK_19_2: + case SMA1307_EXTERNAL_CLOCK_24_576: + case SMA1307_PLL_CLKIN_MCLK: + case SMA1307_PLL_CLKIN_BCLK: + break; + default: + dev_err(component->dev, "%s: Invalid clk id: %d\n", + __func__, clk_id); + return -EINVAL; + } + sma1307->sys_clk_id = clk_id; + + return 0; +} + +static int sma1307_dai_set_fmt_amp(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + + case SND_SOC_DAIFMT_CBC_CFC: + dev_dbg(component->dev, + "%s: %s\n", __func__, "I2S/TDM Device mode"); + regmap_update_bits(sma1307->regmap, + SMA1307_01_INPUT_CTRL1, + SMA1307_CONTROLLER_DEVICE_MASK, + SMA1307_DEVICE_MODE); + break; + + case SND_SOC_DAIFMT_CBP_CFP: + dev_dbg(component->dev, + "%s: %s\n", __func__, "I2S/TDM Controller mode"); + regmap_update_bits(sma1307->regmap, + SMA1307_01_INPUT_CTRL1, + SMA1307_CONTROLLER_DEVICE_MASK, + SMA1307_CONTROLLER_MODE); + break; + + default: + dev_err(component->dev, + "%s: Unsupported Controller/Device : 0x%x\n", + __func__, fmt); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + sma1307->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + break; + default: + dev_err(component->dev, + "%s: Unsupported Audio Interface Format : 0x%x\n", + __func__, fmt); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + + case SND_SOC_DAIFMT_IB_NF: + dev_dbg(component->dev, "%s: %s\n", + __func__, "Invert BCLK + Normal Frame"); + regmap_update_bits(sma1307->regmap, + SMA1307_01_INPUT_CTRL1, + SMA1307_SCK_RISING_MASK, + SMA1307_SCK_RISING_EDGE); + break; + case SND_SOC_DAIFMT_IB_IF: + dev_dbg(component->dev, "%s: %s\n", + __func__, "Invert BCLK + Invert Frame"); + regmap_update_bits(sma1307->regmap, + SMA1307_01_INPUT_CTRL1, + SMA1307_LEFTPOL_MASK + | SMA1307_SCK_RISING_MASK, + SMA1307_HIGH_FIRST_CH + | SMA1307_SCK_RISING_EDGE); + break; + case SND_SOC_DAIFMT_NB_IF: + dev_dbg(component->dev, "%s: %s\n", + __func__, "Normal BCLK + Invert Frame"); + regmap_update_bits(sma1307->regmap, + SMA1307_01_INPUT_CTRL1, + SMA1307_LEFTPOL_MASK, + SMA1307_HIGH_FIRST_CH); + break; + case SND_SOC_DAIFMT_NB_NF: + dev_dbg(component->dev, "%s: %s\n", + __func__, "Normal BCLK + Normal Frame"); + break; + default: + dev_err(component->dev, + "%s: Unsupported Bit & Frameclock : 0x%x\n", + __func__, fmt); + return -EINVAL; + } + + return 0; +} + +static int sma1307_dai_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + dev_dbg(component->dev, "%s: slots = %d, slot_width - %d\n", + __func__, slots, slot_width); + + sma1307->frame_size = slot_width * slots; + + regmap_update_bits(sma1307->regmap, + SMA1307_A4_TOP_MAN3, + SMA1307_INTERFACE_MASK, SMA1307_TDM_FORMAT); + + regmap_update_bits(sma1307->regmap, + SMA1307_A5_TDM1, + SMA1307_TDM_TX_MODE_MASK, + SMA1307_TDM_TX_MONO); + + switch (slot_width) { + case 16: + regmap_update_bits(sma1307->regmap, + SMA1307_A6_TDM2, + SMA1307_TDM_DL_MASK, + SMA1307_TDM_DL_16); + break; + case 32: + regmap_update_bits(sma1307->regmap, + SMA1307_A6_TDM2, + SMA1307_TDM_DL_MASK, + SMA1307_TDM_DL_32); + break; + default: + dev_err(component->dev, "%s: not support TDM %d slot_width\n", + __func__, slot_width); + return -EINVAL; + } + + switch (slots) { + case 4: + regmap_update_bits(sma1307->regmap, + SMA1307_A6_TDM2, + SMA1307_TDM_N_SLOT_MASK, + SMA1307_TDM_N_SLOT_4); + break; + case 8: + regmap_update_bits(sma1307->regmap, + SMA1307_A6_TDM2, + SMA1307_TDM_N_SLOT_MASK, + SMA1307_TDM_N_SLOT_8); + break; + default: + dev_err(component->dev, "%s: not support TDM %d slots\n", + __func__, slots); + return -EINVAL; + } + + if (sma1307->tdm_slot0_rx < slots) + regmap_update_bits(sma1307->regmap, + SMA1307_A5_TDM1, + SMA1307_TDM_SLOT0_RX_POS_MASK, + sma1307->tdm_slot0_rx << 3); + else + dev_err(component->dev, "%s: Incorrect tdm-slot0-rx %d set\n", + __func__, sma1307->tdm_slot0_rx); + + if (sma1307->tdm_slot1_rx < slots) + regmap_update_bits(sma1307->regmap, + SMA1307_A5_TDM1, + SMA1307_TDM_SLOT1_RX_POS_MASK, + sma1307->tdm_slot1_rx); + else + dev_err(component->dev, "%s: Incorrect tdm-slot1-rx %d set\n", + __func__, sma1307->tdm_slot1_rx); + + if (sma1307->tdm_slot0_tx < slots) + regmap_update_bits(sma1307->regmap, + SMA1307_A6_TDM2, + SMA1307_TDM_SLOT0_TX_POS_MASK, + sma1307->tdm_slot0_tx << 3); + else + dev_err(component->dev, "%s: Incorrect tdm-slot0-tx %d set\n", + __func__, sma1307->tdm_slot0_tx); + + if (sma1307->tdm_slot1_tx < slots) + regmap_update_bits(sma1307->regmap, + SMA1307_A6_TDM2, + SMA1307_TDM_SLOT1_TX_POS_MASK, + sma1307->tdm_slot1_tx); + else + dev_err(component->dev, "%s: Incorrect tdm-slot1-tx %d set\n", + __func__, sma1307->tdm_slot1_tx); + + return 0; +} + +static int sma1307_dai_mute_stream(struct snd_soc_dai *dai, int mute, + int stream) +{ + struct snd_soc_component *component = dai->component; + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + + if (stream == SNDRV_PCM_STREAM_CAPTURE) + return 0; + if (mute) { + dev_dbg(component->dev, "%s: %s\n", __func__, "MUTE"); + regmap_update_bits(sma1307->regmap, + SMA1307_0E_MUTE_VOL_CTRL, + SMA1307_SPK_MUTE_MASK, + SMA1307_SPK_MUTE); + } else { + if (!sma1307->force_mute_status) { + dev_dbg(component->dev, "%s: %s\n", __func__, + "UNMUTE"); + regmap_update_bits(sma1307->regmap, + SMA1307_0E_MUTE_VOL_CTRL, + SMA1307_SPK_MUTE_MASK, + SMA1307_SPK_UNMUTE); + } else { + dev_dbg(sma1307->dev, "%s: FORCE MUTE!!!\n", __func__); + } + } + + return 0; +} + +static const struct snd_soc_dai_ops sma1307_dai_ops_amp = { + .hw_params = sma1307_dai_hw_params_amp, + .set_fmt = sma1307_dai_set_fmt_amp, + .set_sysclk = sma1307_dai_set_sysclk_amp, + .set_tdm_slot = sma1307_dai_set_tdm_slot, + .mute_stream = sma1307_dai_mute_stream, +}; + +#define SMA1307_RATES_PLAYBACK SNDRV_PCM_RATE_8000_96000 +#define SMA1307_RATES_CAPTURE SNDRV_PCM_RATE_8000_48000 +#define SMA1307_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver sma1307_dai[] = { + { + .name = "sma1307-amplifier", + .id = 0, + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SMA1307_RATES_PLAYBACK, + .formats = SMA1307_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SMA1307_RATES_CAPTURE, + .formats = SMA1307_FORMATS, + }, + .ops = &sma1307_dai_ops_amp, + }, +}; + +static void sma1307_check_fault_worker(struct work_struct *work) +{ + struct sma1307_priv *sma1307 = + container_of(work, struct sma1307_priv, check_fault_work.work); + unsigned int status1_val, status2_val; + char *envp[3] = { NULL, NULL, NULL }; + + if (sma1307->tsdw_cnt) + regmap_read(sma1307->regmap, + SMA1307_0A_SPK_VOL, &sma1307->cur_vol); + else + regmap_read(sma1307->regmap, + SMA1307_0A_SPK_VOL, &sma1307->init_vol); + + regmap_read(sma1307->regmap, SMA1307_FA_STATUS1, &status1_val); + regmap_read(sma1307->regmap, SMA1307_FB_STATUS2, &status2_val); + + if (~status1_val & SMA1307_OT1_OK_STATUS) { + dev_crit(sma1307->dev, + "%s: OT1(Over Temperature Level 1)\n", __func__); + envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1"); + if (sma1307->sw_ot1_prot) { + /* Volume control (Current Volume -3dB) */ + if ((sma1307->cur_vol + 6) <= 0xFA) { + sma1307->cur_vol += 6; + regmap_write(sma1307->regmap, + SMA1307_0A_SPK_VOL, + sma1307->cur_vol); + envp[1] = kasprintf(GFP_KERNEL, + "VOLUME=0x%02X", sma1307->cur_vol); + } + } + sma1307->tsdw_cnt++; + } else if (sma1307->tsdw_cnt) { + regmap_write(sma1307->regmap, + SMA1307_0A_SPK_VOL, sma1307->init_vol); + sma1307->tsdw_cnt = 0; + sma1307->cur_vol = sma1307->init_vol; + envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1_CLEAR"); + envp[1] = kasprintf(GFP_KERNEL, + "VOLUME=0x%02X", sma1307->cur_vol); + } + + if (~status1_val & SMA1307_OT2_OK_STATUS) { + dev_crit(sma1307->dev, + "%s: OT2(Over Temperature Level 2)\n", __func__); + envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT2"); + } + if (status1_val & SMA1307_UVLO_STATUS) { + dev_crit(sma1307->dev, + "%s: UVLO(Under Voltage Lock Out)\n", __func__); + envp[0] = kasprintf(GFP_KERNEL, "STATUS=UVLO"); + } + if (status1_val & SMA1307_OVP_BST_STATUS) { + dev_crit(sma1307->dev, + "%s: OVP_BST(Over Voltage Protection)\n", __func__); + envp[0] = kasprintf(GFP_KERNEL, "STATUS=OVP_BST"); + } + if (status2_val & SMA1307_OCP_SPK_STATUS) { + dev_crit(sma1307->dev, + "%s: OCP_SPK(Over Current Protect SPK)\n", __func__); + envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_SPK"); + } + if (status2_val & SMA1307_OCP_BST_STATUS) { + dev_crit(sma1307->dev, + "%s: OCP_BST(Over Current Protect Boost)\n", __func__); + envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_BST"); + } + if (status2_val & SMA1307_CLK_MON_STATUS) { + dev_crit(sma1307->dev, + "%s: CLK_FAULT(No clock input)\n", __func__); + envp[0] = kasprintf(GFP_KERNEL, "STATUS=CLK_FAULT"); + } + + if (envp[0] != NULL) { + if (kobject_uevent_env(sma1307->kobj, KOBJ_CHANGE, envp)) + dev_err(sma1307->dev, + "%s: Error sending uevent\n", __func__); + kfree(envp[0]); + kfree(envp[1]); + } + + if (sma1307->check_fault_status) { + if (sma1307->check_fault_period > 0) + queue_delayed_work(system_freezable_wq, + &sma1307->check_fault_work, + sma1307->check_fault_period * HZ); + else + queue_delayed_work(system_freezable_wq, + &sma1307->check_fault_work, + CHECK_PERIOD_TIME * HZ); + } +} + +static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *file) +{ + const struct firmware *fw; + int *data, size, offset, num_mode; + + request_firmware(&fw, file, sma1307->dev); + + if (!fw) { + dev_err(sma1307->dev, "%s: failed to read \"%s\"\n", + __func__, setting_file); + release_firmware(fw); + sma1307->set.status = false; + return; + } else if ((fw->size) < SMA1307_SETTING_HEADER_SIZE) { + dev_err(sma1307->dev, "%s: Invalid file\n", __func__); + release_firmware(fw); + sma1307->set.status = false; + return; + } + + data = kzalloc(fw->size, GFP_KERNEL); + size = fw->size >> 2; + memcpy(data, fw->data, fw->size); + + release_firmware(fw); + + /* HEADER */ + sma1307->set.header_size = SMA1307_SETTING_HEADER_SIZE; + sma1307->set.checksum = data[sma1307->set.header_size - 2]; + sma1307->set.num_mode = data[sma1307->set.header_size - 1]; + num_mode = sma1307->set.num_mode; + sma1307->set.header = devm_kzalloc(sma1307->dev, + sma1307->set.header_size, + GFP_KERNEL); + memcpy(sma1307->set.header, data, + sma1307->set.header_size * sizeof(int)); + + if ((sma1307->set.checksum >> 8) != SMA1307_SETTING_CHECKSUM) { + dev_err(sma1307->dev, "%s: failed by dismatch \"%s\"\n", + __func__, setting_file); + sma1307->set.status = false; + return; + } + + /* DEFAULT */ + sma1307->set.def_size = SMA1307_SETTING_DEFAULT_SIZE; + sma1307->set.def + = devm_kzalloc(sma1307->dev, + sma1307->set.def_size * sizeof(int), GFP_KERNEL); + memcpy(sma1307->set.def, + &data[sma1307->set.header_size], + sma1307->set.def_size * sizeof(int)); + + /* MODE */ + offset = sma1307->set.header_size + sma1307->set.def_size; + sma1307->set.mode_size = DIV_ROUND_CLOSEST(size - offset, num_mode + 1); + for (int i = 0; i < num_mode; i++) { + sma1307->set.mode_set[i] + = devm_kzalloc(sma1307->dev, + sma1307->set.mode_size * 2 * sizeof(int), + GFP_KERNEL); + for (int j = 0; j < sma1307->set.mode_size; j++) { + sma1307->set.mode_set[i][2 * j] + = data[offset + ((num_mode + 1) * j)]; + sma1307->set.mode_set[i][2 * j + 1] + = data[offset + ((num_mode + 1) * j + i + 1)]; + } + } + + kfree(data); + sma1307->set.status = true; + +} + +static void sma1307_reset(struct snd_soc_component *component) +{ + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + unsigned int status = 0; + + regmap_read(sma1307->regmap, SMA1307_FF_DEVICE_INDEX, &status); + + sma1307->rev_num = status & SMA1307_REV_NUM_STATUS; + dev_dbg(component->dev, "%s: SMA1307 Revision %d\n", + __func__, sma1307->rev_num); + regmap_read(sma1307->regmap, SMA1307_99_OTP_TRM2, &sma1307->otp_trm2); + regmap_read(sma1307->regmap, SMA1307_9A_OTP_TRM3, &sma1307->otp_trm3); + + if ((sma1307->otp_trm2 & SMA1307_OTP_STAT_MASK) != SMA1307_OTP_STAT_1) + dev_warn(component->dev, "%s: SMA1307 OTP Status Fail\n", + __func__); + + /* Register Initial Value Setting */ + sma1307_setting_loaded(sma1307, setting_file); + if (sma1307->set.status) + sma1307_set_binary(component); + else + sma1307_set_default(component); + + regmap_update_bits(sma1307->regmap, + SMA1307_93_INT_CTRL, + SMA1307_DIS_INT_MASK, SMA1307_HIGH_Z_INT); + regmap_write(sma1307->regmap, SMA1307_0A_SPK_VOL, sma1307->init_vol); +} + +static void sma1307_set_binary(struct snd_soc_component *component) +{ + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + int i = 0, mode = 0; + + for (i = 0; i < (sma1307->set.def_size); i++) { + if (sma1307_writeable_register(sma1307->dev, i) + && ((i < SMA1307_97_OTP_TRM0) + || (i > SMA1307_9A_OTP_TRM3))) { + regmap_write(sma1307->regmap, i, sma1307->set.def[i]); + + } + } + for (i = 0; i < (sma1307->set.mode_size); i++) { + if (sma1307_writeable_register(sma1307->dev, i) + && ((i < SMA1307_97_OTP_TRM0) + || (i > SMA1307_9A_OTP_TRM3))) { + mode = sma1307->binary_mode; + regmap_write(sma1307->regmap, + sma1307->set.mode_set[mode][2 * i], + sma1307->set.mode_set[mode][2 * i + + 1]); + } + } +} + +static void sma1307_set_default(struct snd_soc_component *component) +{ + struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); + int i = 0; + + for (i = 0; i < (unsigned int)ARRAY_SIZE(sma1307_reg_def); i++) + regmap_write(sma1307->regmap, + sma1307_reg_def[i].reg, + sma1307_reg_def[i].def); + + if (!strcmp(sma1307->name, DEVICE_NAME_SMA1307AQ)) + sma1307->data->init(sma1307->regmap); +} + +static int sma1307_probe(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + + snd_soc_dapm_sync(dapm); + + sma1307_amp_component = component; + + snd_soc_add_component_controls(component, sma1307_binary_mode_control, + ARRAY_SIZE(sma1307_binary_mode_control)); + sma1307_reset(component); + + return 0; +} + +static const struct snd_soc_component_driver sma1307_component = { + .probe = sma1307_probe, + .controls = sma1307_snd_controls, + .num_controls = ARRAY_SIZE(sma1307_snd_controls), + .dapm_widgets = sma1307_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sma1307_dapm_widgets), + .dapm_routes = sma1307_audio_map, + .num_dapm_routes = ARRAY_SIZE(sma1307_audio_map), +}; + +static const struct regmap_config sma_i2c_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = SMA1307_FF_DEVICE_INDEX, + .readable_reg = sma1307_readable_register, + .writeable_reg = sma1307_writeable_register, + .volatile_reg = sma1307_volatile_register, + + .reg_defaults = sma1307_reg_def, + .num_reg_defaults = ARRAY_SIZE(sma1307_reg_def), +}; + +static void sma1307aq_init(struct regmap *regmap) +{ + /* Guidelines for driving 4ohm load */ + /* Brown Out Protection */ + regmap_write(regmap, SMA1307_02_BROWN_OUT_PROT1, 0x62); + regmap_write(regmap, SMA1307_03_BROWN_OUT_PROT2, 0x5D); + regmap_write(regmap, SMA1307_04_BROWN_OUT_PROT3, 0x57); + regmap_write(regmap, SMA1307_05_BROWN_OUT_PROT8, 0x54); + regmap_write(regmap, SMA1307_06_BROWN_OUT_PROT9, 0x51); + regmap_write(regmap, + SMA1307_07_BROWN_OUT_PROT10, 0x4D); + regmap_write(regmap, + SMA1307_08_BROWN_OUT_PROT11, 0x4B); + regmap_write(regmap, SMA1307_27_BROWN_OUT_PROT4, 0x3C); + regmap_write(regmap, SMA1307_28_BROWN_OUT_PROT5, 0x5B); + regmap_write(regmap, + SMA1307_29_BROWN_OUT_PROT12, 0x78); + regmap_write(regmap, + SMA1307_2A_BROWN_OUT_PROT13, 0x96); + regmap_write(regmap, + SMA1307_2B_BROWN_OUT_PROT14, 0xB4); + regmap_write(regmap, + SMA1307_2C_BROWN_OUT_PROT15, 0xD3); + /* FDPEC Gain */ + regmap_write(regmap, SMA1307_35_FDPEC_CTRL0, 0x16); + /* FLT Vdd */ + regmap_write(regmap, SMA1307_92_FDPEC_CTRL1, 0xA0); + /* Boost Max */ + regmap_write(regmap, SMA1307_AB_BOOST_CTRL4, 0x0F); +} + +static const struct sma1307_data sma1307aq_data = { + .name = DEVICE_NAME_SMA1307AQ, + .init = sma1307aq_init, +}; + +static int sma1307_i2c_probe(struct i2c_client *client) +{ + struct sma1307_priv *sma1307; + const struct sma1307_data *data; + int ret = 0; + unsigned int device_info; + + sma1307 = devm_kzalloc(&client->dev, + sizeof(*sma1307), GFP_KERNEL); + if (!sma1307) + return -ENOMEM; + + sma1307->regmap = devm_regmap_init_i2c(client, &sma_i2c_regmap); + if (IS_ERR(sma1307->regmap)) { + return dev_err_probe(&client->dev, PTR_ERR(sma1307->regmap), + "%s: failed to allocate register map\n", __func__); + } + + data = device_get_match_data(&client->dev); + if (!data) + return -ENODEV; + + sma1307->data = data; + + /* set initial value as normal AMP IC status */ + sma1307->name = client->name; + sma1307->format = SND_SOC_DAIFMT_I2S; + sma1307->sys_clk_id = SMA1307_PLL_CLKIN_BCLK; + sma1307->num_of_pll_matches = ARRAY_SIZE(sma1307_pll_matches); + + sma1307->check_fault_period = CHECK_PERIOD_TIME; + sma1307->check_fault_status = true; + sma1307->init_vol = 0x32; + sma1307->cur_vol = sma1307->init_vol; + sma1307->sw_ot1_prot = true; + + mutex_init(&sma1307->default_lock); + + INIT_DELAYED_WORK(&sma1307->check_fault_work, + sma1307_check_fault_worker); + + sma1307->dev = &client->dev; + sma1307->kobj = &client->dev.kobj; + + i2c_set_clientdata(client, sma1307); + + sma1307->pll_matches = sma1307_pll_matches; + + regmap_read(sma1307->regmap, + SMA1307_FF_DEVICE_INDEX, &device_info); + + if ((device_info & 0xF8) != SMA1307_DEVICE_ID) { + dev_err(&client->dev, + "%s: device initialization error (0x%02X)", + __func__, device_info); + return -ENODEV; + } + dev_dbg(&client->dev, "%s: chip version 0x%02X\n", + __func__, device_info); + + i2c_set_clientdata(client, sma1307); + + ret = devm_snd_soc_register_component(&client->dev, + &sma1307_component, sma1307_dai, + 1); + + if (ret) { + dev_err(&client->dev, "%s: failed to register component\n", + __func__); + + return ret; + } + + return ret; +} + +static void sma1307_i2c_remove(struct i2c_client *client) +{ + struct sma1307_priv *sma1307 = + (struct sma1307_priv *)i2c_get_clientdata(client); + + cancel_delayed_work_sync(&sma1307->check_fault_work); +} + +static const struct i2c_device_id sma1307_i2c_id[] = { + { "sma1307a", 0 }, + { "sma1307aq", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, sma1307_i2c_id); + +static const struct of_device_id sma1307_of_match[] = { + { + .compatible = "irondevice,sma1307a", + }, + { + .compatible = "irondevice,sma1307aq", + .data = &sma1307aq_data //AEC-Q100 Qualificated + }, + { } +}; + +MODULE_DEVICE_TABLE(of, sma1307_of_match); + +static struct i2c_driver sma1307_i2c_driver = { + .driver = { + .name = "sma1307", + .of_match_table = sma1307_of_match, + }, + .probe = sma1307_i2c_probe, + .remove = sma1307_i2c_remove, + .id_table = sma1307_i2c_id, +}; + +module_i2c_driver(sma1307_i2c_driver); + +MODULE_DESCRIPTION("ALSA SoC SMA1307 driver"); +MODULE_AUTHOR("Gyuhwa Park, "); +MODULE_AUTHOR("KS Jo, "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/sma1307.h b/sound/soc/codecs/sma1307.h new file mode 100644 index 000000000000..44aab52a32f9 --- /dev/null +++ b/sound/soc/codecs/sma1307.h @@ -0,0 +1,444 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * sma1307.h -- sma1307 ALSA SoC Audio driver + * + * Copyright 2024 Iron Device Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _SMA1307_H +#define _SMA1307_H + +#include + +enum sma1307_fault { + SMA1307_FAULT_OT1, + SMA1307_FAULT_OT2, + SMA1307_FAULT_UVLO, + SMA1307_FAULT_OVP_BST, + SMA1307_FAULT_OCP_SPK, + SMA1307_FAULT_OCP_BST, + SMA1307_FAULT_CLK +}; + +enum sma1307_mode { + SMA1307_MONO_MODE, + SMA1307_LEFT_MODE, + SMA1307_RIGHT_MODE, +}; + +enum sma1307_sdo_mode { + SMA1307_OUT_DATA_ONE_48K, + SMA1307_OUT_DATA_TWO_48K, + SMA1307_OUT_DATA_TWO_24K, + SMA1307_OUT_CLK_PLL, + SMA1307_OUT_CLK_OSC +}; + +enum sma1307_sdo_source { + SMA1307_OUT_DISABLE, + SMA1307_OUT_FORMAT_C, + SMA1307_OUT_MIXER_OUT, + SMA1307_OUT_AFTER_DSP, + SMA1307_OUT_VRMS2_AVG, + SMA1307_OUT_BATTERY, + SMA1307_OUT_TEMP, + SMA1307_OUT_AFTER_DELAY +}; + +struct sma1307_setting_file { + bool status; + char *header; + int *def; + int *mode_set[5]; + int checksum; + int num_mode; + size_t header_size; + size_t def_size; + size_t mode_size; +}; + +#define SMA1307_I2C_ADDR_00 0x1e +#define SMA1307_I2C_ADDR_01 0x3e +#define SMA1307_I2C_ADDR_10 0x5e +#define SMA1307_I2C_ADDR_11 0x7e + +#define DEVICE_NAME_SMA1307A "sma1307a" +#define DEVICE_NAME_SMA1307AQ "sma1307aq" + +#define SMA1307_EXTERNAL_CLOCK_19_2 0x00 +#define SMA1307_EXTERNAL_CLOCK_24_576 0x01 +#define SMA1307_PLL_CLKIN_MCLK 0x02 +#define SMA1307_PLL_CLKIN_BCLK 0x03 + +#define SMA1307_OFFSET_DEFAULT_MODE 0x00 +#define SMA1307_OFFSET_BURNING_MODE 0x01 + +#define SMA1307_SETTING_HEADER_SIZE 0x08 +#define SMA1307_SETTING_DEFAULT_SIZE 0xC0 + +#define SMA1307_DEFAULT_SET 0x00 +#define SMA1307_BINARY_FILE_SET 0x01 + +/* Controls Name */ +#define SMA1307_REG_CTRL_NAME "Register Byte Control" +#define SMA1307_VOL_CTRL_NAME "Speaker Volume" +#define SMA1307_FORCE_MUTE_CTRL_NAME "Force Mute Switch" +#define SMA1307_TDM_RX0_POS_NAME "TDM RX Slot0 Position" +#define SMA1307_TDM_RX1_POS_NAME "TDM RX Slot1 Position" +#define SMA1307_TDM_TX0_POS_NAME "TDM TX Slot0 Position" +#define SMA1307_TDM_TX1_POS_NAME "TDM TX Slot1 Position" +#define SMA1307_OT1_SW_PROT_CTRL_NAME "OT1 SW Protection Switch" +#define SMA1307_RESET_CTRL_NAME "Reset Switch" +#define SMA1307_CHECK_FAULT_STATUS_NAME "Check Fault Status" +#define SMA1307_CHECK_FAULT_PERIOD_NAME "Check Fault Period" + +/* DAPM Name */ +#define SMA1307_AIF_IN_NAME "AIF IN Source" +#define SMA1307_AIF_OUT0_NAME "AIF OUT0 Source" +#define SMA1307_AIF_OUT1_NAME "AIF OUT1 Source" + +/* + * SMA1307 Register Definition + */ + +/* SMA1307 Register Addresses */ +#define SMA1307_00_SYSTEM_CTRL 0x00 +#define SMA1307_01_INPUT_CTRL1 0x01 +#define SMA1307_02_BROWN_OUT_PROT1 0x02 +#define SMA1307_03_BROWN_OUT_PROT2 0x03 +#define SMA1307_04_BROWN_OUT_PROT3 0x04 +#define SMA1307_05_BROWN_OUT_PROT8 0x05 +#define SMA1307_06_BROWN_OUT_PROT9 0x06 +#define SMA1307_07_BROWN_OUT_PROT10 0x07 +#define SMA1307_08_BROWN_OUT_PROT11 0x08 +#define SMA1307_09_OUTPUT_CTRL 0x09 +#define SMA1307_0A_SPK_VOL 0x0A +#define SMA1307_0B_BST_TEST 0x0B +#define SMA1307_0C_BOOST_CTRL8 0x0C +#define SMA1307_0D_SPK_TEST 0x0D +#define SMA1307_0E_MUTE_VOL_CTRL 0x0E +#define SMA1307_0F_VBAT_TEMP_SENSING 0x0F + +#define SMA1307_10_SYSTEM_CTRL1 0x10 +#define SMA1307_11_SYSTEM_CTRL2 0x11 +#define SMA1307_12_SYSTEM_CTRL3 0x12 +#define SMA1307_13_DELAY 0x13 +#define SMA1307_14_MODULATOR 0x14 +#define SMA1307_15_BASS_SPK1 0x15 +#define SMA1307_16_BASS_SPK2 0x16 +#define SMA1307_17_BASS_SPK3 0x17 +#define SMA1307_18_BASS_SPK4 0x18 +#define SMA1307_19_BASS_SPK5 0x19 +#define SMA1307_1A_BASS_SPK6 0x1A +#define SMA1307_1B_BASS_SPK7 0x1B +#define SMA1307_1C_BROWN_OUT_PROT20 0x1C +#define SMA1307_1D_BROWN_OUT_PROT0 0x1D +#define SMA1307_1E_TONE_GENERATOR 0x1E +#define SMA1307_1F_TONE_FINE_VOLUME 0x1F + +#define SMA1307_22_COMP_HYS_SEL 0x22 +#define SMA1307_23_COMPLIM1 0x23 +#define SMA1307_24_COMPLIM2 0x24 +#define SMA1307_25_COMPLIM3 0x25 +#define SMA1307_26_COMPLIM4 0x26 +#define SMA1307_27_BROWN_OUT_PROT4 0x27 +#define SMA1307_28_BROWN_OUT_PROT5 0x28 +#define SMA1307_29_BROWN_OUT_PROT12 0x29 +#define SMA1307_2A_BROWN_OUT_PROT13 0x2A +#define SMA1307_2B_BROWN_OUT_PROT14 0x2B +#define SMA1307_2C_BROWN_OUT_PROT15 0x2C +#define SMA1307_2D_BROWN_OUT_PROT6 0x2D +#define SMA1307_2E_BROWN_OUT_PROT7 0x2E +#define SMA1307_2F_BROWN_OUT_PROT16 0x2F + +#define SMA1307_30_BROWN_OUT_PROT17 0x30 +#define SMA1307_31_BROWN_OUT_PROT18 0x31 +#define SMA1307_32_BROWN_OUT_PROT19 0x32 +#define SMA1307_34_OCP_SPK 0x34 +#define SMA1307_35_FDPEC_CTRL0 0x35 +#define SMA1307_36_PROTECTION 0x36 +#define SMA1307_37_SLOPECTRL 0x37 +#define SMA1307_38_POWER_METER 0x38 +#define SMA1307_39_PMT_NZ_VAL 0x39 +#define SMA1307_3B_TEST1 0x3B +#define SMA1307_3C_TEST2 0x3C +#define SMA1307_3D_TEST3 0x3D +#define SMA1307_3E_IDLE_MODE_CTRL 0x3E +#define SMA1307_3F_ATEST2 0x3F +#define SMA1307_8B_PLL_POST_N 0x8B +#define SMA1307_8C_PLL_N 0x8C +#define SMA1307_8D_PLL_A_SETTING 0x8D +#define SMA1307_8E_PLL_P_CP 0x8E +#define SMA1307_8F_ANALOG_TEST 0x8F + +#define SMA1307_90_CRESTLIM1 0x90 +#define SMA1307_91_CRESTLIM2 0x91 +#define SMA1307_92_FDPEC_CTRL1 0x92 +#define SMA1307_93_INT_CTRL 0x93 +#define SMA1307_94_BOOST_CTRL9 0x94 +#define SMA1307_95_BOOST_CTRL10 0x95 +#define SMA1307_96_BOOST_CTRL11 0x96 +#define SMA1307_97_OTP_TRM0 0x97 +#define SMA1307_98_OTP_TRM1 0x98 +#define SMA1307_99_OTP_TRM2 0x99 +#define SMA1307_9A_OTP_TRM3 0x9A + +#define SMA1307_A0_PAD_CTRL0 0xA0 +#define SMA1307_A1_PAD_CTRL1 0xA1 +#define SMA1307_A2_TOP_MAN1 0xA2 +#define SMA1307_A3_TOP_MAN2 0xA3 +#define SMA1307_A4_TOP_MAN3 0xA4 +#define SMA1307_A5_TDM1 0xA5 +#define SMA1307_A6_TDM2 0xA6 +#define SMA1307_A7_CLK_MON 0xA7 +#define SMA1307_A8_BOOST_CTRL1 0xA8 +#define SMA1307_A9_BOOST_CTRL2 0xA9 +#define SMA1307_AA_BOOST_CTRL3 0xAA +#define SMA1307_AB_BOOST_CTRL4 0xAB +#define SMA1307_AC_BOOST_CTRL5 0xAC +#define SMA1307_AD_BOOST_CTRL6 0xAD +#define SMA1307_AE_BOOST_CTRL7 0xAE +#define SMA1307_AF_LPF 0xAF + +#define SMA1307_B0_RMS_TC1 0xB0 +#define SMA1307_B1_RMS_TC2 0xB1 +#define SMA1307_B2_AVG_TC1 0xB2 +#define SMA1307_B3_AVG_TC2 0xB3 +#define SMA1307_B4_PRVALUE1 0xB4 +#define SMA1307_B5_PRVALUE2 0xB5 +#define SMA1307_B8_SPK_NG_CTRL1 0xB8 +#define SMA1307_B9_SPK_NG_CTRL2 0xB9 +#define SMA1307_BA_DGC1 0xBA +#define SMA1307_BB_DGC2 0xBB +#define SMA1307_BC_DGC3 0xBC +#define SMA1307_BD_MCBS_CTRL1 0xBD +#define SMA1307_BE_MCBS_CTRL2 0xBE + +/* Status Register Read Only */ +#define SMA1307_F5_READY_FOR_V_SAR 0xF5 +#define SMA1307_F7_READY_FOR_T_SAR 0xF7 +#define SMA1307_F8_STATUS_T1 0xF8 +#define SMA1307_F9_STATUS_T2 0xF9 +#define SMA1307_FA_STATUS1 0xFA +#define SMA1307_FB_STATUS2 0xFB +#define SMA1307_FC_STATUS3 0xFC +#define SMA1307_FD_STATUS4 0xFD +#define SMA1307_FE_STATUS5 0xFE +#define SMA1307_FF_DEVICE_INDEX 0xFF + +/* SMA1307 Registers Bit Fields */ +/* Power On/Off */ +#define SMA1307_POWER_MASK BIT(0) +#define SMA1307_POWER_OFF 0 +#define SMA1307_POWER_ON BIT(0) + +/* Reset */ +#define SMA1307_RESET_MASK BIT(1) +#define SMA1307_RESET_ON BIT(1) + +/* Left Polarity */ +#define SMA1307_LEFTPOL_MASK BIT(3) +#define SMA1307_LOW_FIRST_CH 0 +#define SMA1307_HIGH_FIRST_CH BIT(3) + +/* SCK Falling/Rising */ +#define SMA1307_SCK_RISING_MASK BIT(2) +#define SMA1307_SCK_FALLING_EDGE 0 +#define SMA1307_SCK_RISING_EDGE BIT(2) + +/* SPK Mute */ +#define SMA1307_SPK_MUTE_MASK BIT(0) +#define SMA1307_SPK_UNMUTE 0 +#define SMA1307_SPK_MUTE BIT(0) + +/* SPK Mode */ +#define SMA1307_SPK_MODE_MASK (BIT(2)|BIT(3)|BIT(4)) +#define SMA1307_SPK_OFF 0 +#define SMA1307_SPK_MONO BIT(2) +#define SMA1307_SPK_STEREO BIT(4) + +/* Mono Mix */ +#define SMA1307_MONOMIX_MASK BIT(0) +#define SMA1307_MONOMIX_OFF 0 +#define SMA1307_MONOMIX_ON BIT(0) + +/* LR Data Swap */ +#define SMA1307_LR_DATA_SW_MASK BIT(4) +#define SMA1307_LR_DATA_SW_NORMAL 0 +#define SMA1307_LR_DATA_SW_SWAP BIT(4) + +/* PLL On/Off */ +#define SMA1307_PLL_MASK BIT(6) +#define SMA1307_PLL_ON 0 +#define SMA1307_PLL_OFF BIT(6) + +/* Input Format */ +#define SMA1307_I2S_MODE_MASK (BIT(4)|BIT(5)|BIT(6)) +#define SMA1307_STANDARD_I2S 0 +#define SMA1307_LJ BIT(4) +#define SMA1307_RJ_16BIT BIT(6) +#define SMA1307_RJ_18BIT (BIT(4)|BIT(6)) +#define SMA1307_RJ_20BIT (BIT(5)|BIT(6)) +#define SMA1307_RJ_24BIT (BIT(4)|BIT(5)|BIT(6)) + +/* Controller / Device Setting */ +#define SMA1307_CONTROLLER_DEVICE_MASK BIT(7) +#define SMA1307_DEVICE_MODE 0 +#define SMA1307_CONTROLLER_MODE BIT(7) + +/* Port Config */ +#define SMA1307_PORT_CONFIG_MASK (BIT(6)|BIT(7)) +#define SMA1307_INPUT_PORT_ONLY 0 +#define SMA1307_OUTPUT_PORT_ENABLE BIT(7) + +/* SDO Output */ +#define SMA1307_SDO_OUTPUT_MASK BIT(3) +#define SMA1307_LOGIC_OUTPUT 0 +#define SMA1307_HIGH_Z_OUTPUT BIT(3) + +#define SMA1307_DATA_CLK_SEL_MASK (BIT(6)|BIT(7)) +#define SMA1307_SDO_DATA 0 +#define SMA1307_SDO_CLK_PLL BIT(6) +#define SMA1307_SDO_CLK_OSC (BIT(6)|BIT(7)) + +/* SDO Output2 */ +#define SMA1307_SDO_OUTPUT2_MASK BIT(0) +#define SMA1307_ONE_SDO_PER_CH 0 +#define SMA1307_TWO_SDO_PER_CH BIT(0) + +/* SDO Output3 */ +#define SMA1307_SDO_OUTPUT3_MASK BIT(2) +#define SMA1307_SDO_OUTPUT3_DIS 0 +#define SMA1307_TWO_SDO_PER_CH_24K BIT(2) + +/* SDO OUT1 Select*/ +#define SMA1307_SDO_OUT1_SEL_MASK (BIT(3)|BIT(4)|BIT(5)) +#define SMA1307_SDO1_DISABLE 0 +#define SMA1307_SDO1_FORMAT_C BIT(3) +#define SMA1307_SDO1_MONO_MIX BIT(4) +#define SMA1307_SDO1_AFTER_DSP (BIT(3)|BIT(4)) +#define SMA1307_SDO1_VRMS2_AVG BIT(5) +#define SMA1307_SDO1_VBAT_MON (BIT(3)|BIT(5)) +#define SMA1307_SDO1_TEMP_MON (BIT(4)|BIT(5)) +#define SMA1307_SDO1_AFTER_DELAY (BIT(3)|BIT(4)|BIT(5)) + +/* SDO OUT0 Select*/ +#define SMA1307_SDO_OUT0_SEL_MASK (BIT(0)|BIT(1)|BIT(2)) +#define SMA1307_SDO0_DISABLE 0 +#define SMA1307_SDO0_FORMAT_C BIT(0) +#define SMA1307_SDO0_MONO_MIX BIT(1) +#define SMA1307_SDO0_AFTER_DSP (BIT(0)|BIT(1)) +#define SMA1307_SDO0_VRMS2_AVG BIT(2) +#define SMA1307_SDO0_VBAT_MON (BIT(0)|BIT(2)) +#define SMA1307_SDO0_TEMP_MON (BIT(1)|BIT(2)) +#define SMA1307_SDO0_AFTER_DELAY (BIT(0)|BIT(1)|BIT(2)) + +/* INTERRUPT Operation */ +#define SMA1307_SEL_INT_MASK BIT(2) +#define SMA1307_INT_CLEAR_AUTO 0 +#define SMA1307_INT_CLEAR_MANUAL BIT(2) + +/* INTERRUPT CLEAR */ +#define SMA1307_CLR_INT_MASK BIT(1) +#define SMA1307_INT_READY 0 +#define SMA1307_INT_CLEAR BIT(1) + +/* INTERRUPT Disable */ +#define SMA1307_DIS_INT_MASK BIT(0) +#define SMA1307_NORMAL_INT 0 +#define SMA1307_HIGH_Z_INT BIT(0) + +/* Interface Control */ +#define SMA1307_INTERFACE_MASK (BIT(5)|BIT(6)|BIT(7)) +#define SMA1307_LJ_FORMAT BIT(5) +#define SMA1307_I2S_FORMAT (BIT(5)|BIT(6)) +#define SMA1307_TDM_FORMAT BIT(7) + +#define SMA1307_SCK_RATE_MASK (BIT(3)|BIT(4)) +#define SMA1307_SCK_64FS 0 +#define SMA1307_SCK_32FS BIT(4) + +#define SMA1307_DATA_WIDTH_MASK (BIT(1)|BIT(2)) +#define SMA1307_DATA_24BIT 0 +#define SMA1307_DATA_16BIT (BIT(1)|BIT(2)) + +#define SMA1307_TDM_TX_MODE_MASK BIT(6) +#define SMA1307_TDM_TX_MONO 0 +#define SMA1307_TDM_TX_STEREO BIT(6) + +#define SMA1307_TDM_SLOT0_RX_POS_MASK (BIT(3)|BIT(4)|BIT(5)) +#define SMA1307_TDM_SLOT0_RX_POS_0 0 +#define SMA1307_TDM_SLOT0_RX_POS_1 BIT(3) +#define SMA1307_TDM_SLOT0_RX_POS_2 BIT(4) +#define SMA1307_TDM_SLOT0_RX_POS_3 (BIT(3)|BIT(4)) +#define SMA1307_TDM_SLOT0_RX_POS_4 BIT(5) +#define SMA1307_TDM_SLOT0_RX_POS_5 (BIT(3)|BIT(5)) +#define SMA1307_TDM_SLOT0_RX_POS_6 (BIT(4)|BIT(5)) +#define SMA1307_TDM_SLOT0_RX_POS_7 (BIT(3)|BIT(4)|BIT(5)) + +#define SMA1307_TDM_SLOT1_RX_POS_MASK (BIT(0)|BIT(1)|BIT(2)) +#define SMA1307_TDM_SLOT1_RX_POS_0 0 +#define SMA1307_TDM_SLOT1_RX_POS_1 BIT(0) +#define SMA1307_TDM_SLOT1_RX_POS_2 BIT(1) +#define SMA1307_TDM_SLOT1_RX_POS_3 (BIT(0)|BIT(1)) +#define SMA1307_TDM_SLOT1_RX_POS_4 BIT(2) +#define SMA1307_TDM_SLOT1_RX_POS_5 (BIT(0)|BIT(2)) +#define SMA1307_TDM_SLOT1_RX_POS_6 (BIT(1)|BIT(2)) +#define SMA1307_TDM_SLOT1_RX_POS_7 (BIT(0)|BIT(1)|BIT(2)) + +/* TDM2 FORMAT : 0xA6 */ +#define SMA1307_TDM_DL_MASK BIT(7) +#define SMA1307_TDM_DL_16 0 +#define SMA1307_TDM_DL_32 BIT(7) + +#define SMA1307_TDM_N_SLOT_MASK BIT(6) +#define SMA1307_TDM_N_SLOT_4 0 +#define SMA1307_TDM_N_SLOT_8 BIT(6) + +#define SMA1307_TDM_SLOT0_TX_POS_MASK (BIT(3)|BIT(4)|BIT(5)) +#define SMA1307_TDM_SLOT0_TX_POS_0 0 +#define SMA1307_TDM_SLOT0_TX_POS_1 BIT(3) +#define SMA1307_TDM_SLOT0_TX_POS_2 BIT(4) +#define SMA1307_TDM_SLOT0_TX_POS_3 (BIT(3)|BIT(4)) +#define SMA1307_TDM_SLOT0_TX_POS_4 BIT(5) +#define SMA1307_TDM_SLOT0_TX_POS_5 (BIT(3)|BIT(5)) +#define SMA1307_TDM_SLOT0_TX_POS_6 (BIT(4)|BIT(5)) +#define SMA1307_TDM_SLOT0_TX_POS_7 (BIT(3)|BIT(4)|BIT(5)) + +#define SMA1307_TDM_SLOT1_TX_POS_MASK (BIT(0)|BIT(1)|BIT(2)) +#define SMA1307_TDM_SLOT1_TX_POS_0 0 +#define SMA1307_TDM_SLOT1_TX_POS_1 BIT(0) +#define SMA1307_TDM_SLOT1_TX_POS_2 BIT(1) +#define SMA1307_TDM_SLOT1_TX_POS_3 (BIT(0)|BIT(1)) +#define SMA1307_TDM_SLOT1_TX_POS_4 BIT(2) +#define SMA1307_TDM_SLOT1_TX_POS_5 (BIT(0)|BIT(2)) +#define SMA1307_TDM_SLOT1_TX_POS_6 (BIT(1)|BIT(2)) +#define SMA1307_TDM_SLOT1_TX_POS_7 (BIT(0)|BIT(1)|BIT(2)) + +/* OTP STATUS */ +#define SMA1307_OTP_STAT_MASK BIT(6) +#define SMA1307_OTP_STAT_0 0 +#define SMA1307_OTP_STAT_1 BIT(6) + +/* STATUS */ +#define SMA1307_OT1_OK_STATUS BIT(7) +#define SMA1307_OT2_OK_STATUS BIT(6) +#define SMA1307_UVLO_STATUS BIT(5) +#define SMA1307_OVP_BST_STATUS BIT(4) +#define SMA1307_POWER_FLAG BIT(3) + +#define SMA1307_SCAN_CHK BIT(7) +#define SMA1307_OCP_SPK_STATUS BIT(5) +#define SMA1307_OCP_BST_STATUS BIT(4) +#define SMA1307_BOP_STATE (BIT(1)|BIT(2)|BIT(3)) +#define SMA1307_CLK_MON_STATUS BIT(0) + +#define SMA1307_DEVICE_ID (BIT(3)|BIT(4)) +#define SMA1307_REV_NUM_STATUS (BIT(0)|BIT(1)) +#define SMA1307_REV_NUM_REV0 0 +#define SMA1307_REV_NUM_REV1 BIT(0) + +#endif From ae6e9e8be2be162da75b0f637cd030b76ed30716 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:07 +0100 Subject: [PATCH 183/256] ASoC: da7213: Avoid setting PLL when closing audio stream JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1e1a2ef95b571825ca9c0113f6bef51e9cec98b0 Author: Hao Bui Date: Wed Nov 6 10:18:20 2024 +0200 ASoC: da7213: Avoid setting PLL when closing audio stream When audio stream is closing, audio frequency is set to 0 by ALSA but codec driver DA7213 does not handle properly in this case. This patch adds checking of 0Hz frequency to da7213_set_component_sysclk() and avoid unnecessary PLL settings. Signed-off-by: Hao Bui Signed-off-by: Claudiu Beznea Link: https://patch.msgid.link/20241106081826.1211088-26-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/da7213.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 1deb0ecb4c0e..ccff689cffdd 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1555,6 +1555,10 @@ static int da7213_set_component_sysclk(struct snd_soc_component *component, if ((da7213->clk_src == clk_id) && (da7213->mclk_rate == freq)) return 0; + /* Maybe audio stream is closing. */ + if (freq == 0) + return 0; + if (((freq < 5000000) && (freq != 32768)) || (freq > 54000000)) { dev_err(component->dev, "Unsupported MCLK value %d\n", freq); From 103b4047826b6b0a80260b0fdd6cdf8dff2509de Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:07 +0100 Subject: [PATCH 184/256] ASoC: da7213: Extend support for the MCK in range [2, 50] MHz JIRA: https://issues.redhat.com/browse/RHEL-80681 commit b3296f9095d6ad24723e5ad89c28acc317d0c3cf Author: Hao Bui Date: Wed Nov 6 10:18:21 2024 +0200 ASoC: da7213: Extend support for the MCK in range [2, 50] MHz According to DA7212 HW manual, the codec's PLL input divider can operate with MCLK range from 2MHz to 50MHz but current driver only set the minimum supported MCLK frequency to 5MHz. That cause 11.025kHz audio which is corresponding to MCLK of 2.8224MHz (11.025kHz * 256) unable to play in case audio-simple-card is used. Signed-off-by: Hao Bui Co-developed-by: Claudiu Beznea Signed-off-by: Claudiu Beznea Link: https://patch.msgid.link/20241106081826.1211088-27-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/da7213.c | 18 +++++++++++++----- sound/soc/codecs/da7213.h | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index ccff689cffdd..5d61ec0f862c 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1559,7 +1560,7 @@ static int da7213_set_component_sysclk(struct snd_soc_component *component, if (freq == 0) return 0; - if (((freq < 5000000) && (freq != 32768)) || (freq > 54000000)) { + if (((freq < da7213->fin_min_rate) && (freq != 32768)) || (freq > 54000000)) { dev_err(component->dev, "Unsupported MCLK value %d\n", freq); return -EINVAL; @@ -1858,11 +1859,14 @@ static int da7213_set_bias_level(struct snd_soc_component *component, return 0; } +#define DA7213_FIN_MIN_RATE (5 * MEGA) +#define DA7212_FIN_MIN_RATE (2 * MEGA) + #if defined(CONFIG_OF) /* DT */ static const struct of_device_id da7213_of_match[] = { - { .compatible = "dlg,da7212", }, - { .compatible = "dlg,da7213", }, + { .compatible = "dlg,da7212", .data = (void *)DA7212_FIN_MIN_RATE }, + { .compatible = "dlg,da7213", .data = (void *)DA7213_FIN_MIN_RATE }, { } }; MODULE_DEVICE_TABLE(of, da7213_of_match); @@ -1870,8 +1874,8 @@ MODULE_DEVICE_TABLE(of, da7213_of_match); #ifdef CONFIG_ACPI static const struct acpi_device_id da7213_acpi_match[] = { - { "DLGS7212", 0}, - { "DLGS7213", 0}, + { "DLGS7212", DA7212_FIN_MIN_RATE }, + { "DLGS7213", DA7213_FIN_MIN_RATE }, { }, }; MODULE_DEVICE_TABLE(acpi, da7213_acpi_match); @@ -2167,6 +2171,10 @@ static int da7213_i2c_probe(struct i2c_client *i2c) if (!da7213) return -ENOMEM; + da7213->fin_min_rate = (uintptr_t)i2c_get_match_data(i2c); + if (!da7213->fin_min_rate) + return -EINVAL; + i2c_set_clientdata(i2c, da7213); /* Get required supplies */ diff --git a/sound/soc/codecs/da7213.h b/sound/soc/codecs/da7213.h index 505b731c0adb..b9ab791d6b88 100644 --- a/sound/soc/codecs/da7213.h +++ b/sound/soc/codecs/da7213.h @@ -600,6 +600,7 @@ struct da7213_priv { struct clk *mclk; unsigned int mclk_rate; unsigned int out_rate; + unsigned int fin_min_rate; int clk_src; bool master; bool alc_calib_auto; From 370e486e69ae501a15e5a8cb488b9c4364f69bb7 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:07 +0100 Subject: [PATCH 185/256] ASoC: SOF: ext_manifest: Add missing ext_manifest type for PROBE_INFO JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7f4eb7672b1785119b29a4dff50aeef13368e813 Author: Peter Ujfalusi Date: Thu Nov 7 14:03:05 2024 +0200 ASoC: SOF: ext_manifest: Add missing ext_manifest type for PROBE_INFO Elem type 3 is PROBE_INFO in ext_manifest, add it to the list. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Liam Girdwood Link: https://patch.msgid.link/20241107120306.30680-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/sof/ext_manifest.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h index fc0231d04a94..7dfe3ccf1fe4 100644 --- a/include/sound/sof/ext_manifest.h +++ b/include/sound/sof/ext_manifest.h @@ -60,6 +60,7 @@ enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, SOF_EXT_MAN_ELEM_WINDOW = 1, SOF_EXT_MAN_ELEM_CC_VERSION = 2, + SOF_EXT_MAN_ELEM_PROBE_INFO = 3, SOF_EXT_MAN_ELEM_DBG_ABI = 4, SOF_EXT_MAN_ELEM_CONFIG_DATA = 5, /**< ABI3.17 */ SOF_EXT_MAN_ELEM_PLATFORM_CONFIG_DATA = 6, From ce2941fffd878f81410d57941bdce73bf5ac6b62 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:08 +0100 Subject: [PATCH 186/256] ASoC: SOF: ipc3-loader: 'Handle' PROBE_INFO ext_manifest type when parsing JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 83e367c1a178045bf3675646aa9582a0c5a4e566 Author: Peter Ujfalusi Date: Thu Nov 7 14:03:06 2024 +0200 ASoC: SOF: ipc3-loader: 'Handle' PROBE_INFO ext_manifest type when parsing Every time when the firmware is loaded we see the following printed in info level: unknown sof_ext_man header type 3 size 0x30 This is the PROBE_INFO element, which is not parsed, but it is not something that we should treat as surprise, aka unknown type. Add an empty case with a debug print to 'handle' this ext_manifest type and silence the confusing print in kernel log. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Liam Girdwood Link: https://patch.msgid.link/20241107120306.30680-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc3-loader.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sof/ipc3-loader.c b/sound/soc/sof/ipc3-loader.c index 35b89c2b9d4c..7e9c76d5b2c9 100644 --- a/sound/soc/sof/ipc3-loader.c +++ b/sound/soc/sof/ipc3-loader.c @@ -193,6 +193,9 @@ static size_t sof_ipc3_fw_parse_ext_man(struct snd_sof_dev *sdev) case SOF_EXT_MAN_ELEM_CC_VERSION: ret = ipc3_fw_ext_man_get_cc_info(sdev, elem_hdr); break; + case SOF_EXT_MAN_ELEM_PROBE_INFO: + dev_dbg(sdev->dev, "Probe info (not parsed)\n"); + break; case SOF_EXT_MAN_ELEM_DBG_ABI: ret = ipc3_fw_ext_man_get_dbg_abi_info(sdev, elem_hdr); break; From 317ea3af5e9f367c86c9495cb37d9d7650ff8796 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:08 +0100 Subject: [PATCH 187/256] ASoC: SOF: Intel: hda-stream: Always use at least two BDLE for transfers JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1b1f491dac4f6ee88ec7c36c4fd27880b0a89f41 Author: Peter Ujfalusi Date: Thu Nov 7 14:15:32 2024 +0200 ASoC: SOF: Intel: hda-stream: Always use at least two BDLE for transfers The HDA specification states that the SDnLVI (Last Valid Index) must be at least 1 (two BDLE entry). Update the debug prints as well to provide better information. While the LVI=0 worked so far without issues, it is better to align with the specification to avoid unforeseen issues with FW loading. Notes: - The LVI > 0 rules is valid and honored for audio use cases - LVI == 0 is used with software controlled (SPIB) transfers only for firmware and library loading, which is permitted by the hardware - This is not spelled out in the specification and it is better to avoid cases Signed-off-by: Peter Ujfalusi Reviewed-by: Liam Girdwood Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Link: https://patch.msgid.link/20241107121532.3241-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/intel/hda-stream.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 3ac63ce67ab1..519bafd3b947 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -119,13 +119,39 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev, int remain, ioc; period_bytes = hstream->period_bytes; - dev_dbg(sdev->dev, "period_bytes:0x%x\n", period_bytes); - if (!period_bytes) + dev_dbg(sdev->dev, "period_bytes: %#x, bufsize: %#x\n", period_bytes, + hstream->bufsize); + + if (!period_bytes) { + unsigned int chunk_size; + + chunk_size = snd_sgbuf_get_chunk_size(dmab, 0, hstream->bufsize); + period_bytes = hstream->bufsize; + /* + * HDA spec demands that the LVI value must be at least one + * before the DMA operation can begin. This means that there + * must be at least two BDLE present for the transfer. + * + * If the buffer is not a single continuous area then the + * hda_setup_bdle() will create multiple BDLEs for each segment. + * If the memory is a single continuous area, force it to be + * split into two 'periods', otherwise the transfer will be + * split to multiple BDLE for each chunk in hda_setup_bdle() + * + * Note: period_bytes == 0 can only happen for firmware or + * library loading. The data size is 4K aligned, which ensures + * that the second chunk's start address will be 128-byte + * aligned. + */ + if (chunk_size == hstream->bufsize) + period_bytes /= 2; + } + periods = hstream->bufsize / period_bytes; - dev_dbg(sdev->dev, "periods:%d\n", periods); + dev_dbg(sdev->dev, "periods: %d\n", periods); remain = hstream->bufsize % period_bytes; if (remain) From a8a7a2ff5fe6d4f2c5899ca9a1b01f81fa52170d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:08 +0100 Subject: [PATCH 188/256] ASoC: SOF: Intel: hda: Add support for persistent Code Loader DMA buffers JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1862e847bf115a3ccbf38dd035ea0118be57f2e2 Author: Peter Ujfalusi Date: Thu Nov 7 14:14:40 2024 +0200 ASoC: SOF: Intel: hda: Add support for persistent Code Loader DMA buffers It has been reported that the DMA memory allocation for firmware download can fail after extended period of uptime on systems with relatively small amount of RAM when the system memory becomes fragmented. The issue primarily happens when the system is waking up from system suspend, swap might not be available and the MM system cannot move things around to allow for successful allocation. If the IMR boot is not supported then for each DSP boot we would need to allocate the DMA buffer for firmware transfer, which can increase the chances of the issue to be hit. This patch adds support for allocating the DMA buffers once at first boot time and keep it until the system is shut down, rebooted or the drivers re-loaded and makes this as the default operation. With persistent_cl_buffer module parameter the persistent Code Loader DMA buffer can be disabled to fall back to on demand allocation. Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Liam Girdwood Reviewed-by: Kai Vehmanen Link: https://patch.msgid.link/20241107121440.1472-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/intel/hda-loader.c | 100 ++++++++++++++++++++++--------- sound/soc/sof/intel/hda.c | 6 ++ sound/soc/sof/intel/hda.h | 14 ++++- 3 files changed, 90 insertions(+), 30 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 9d8ebb7c6a10..76a03b6b2728 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -26,6 +26,11 @@ #include "../sof-priv.h" #include "hda.h" +static bool persistent_cl_buffer = true; +module_param(persistent_cl_buffer, bool, 0444); +MODULE_PARM_DESC(persistent_cl_buffer, "Persistent Code Loader DMA buffer " + "(default = Y, use N to force buffer re-allocation)"); + static void hda_ssp_set_cbp_cfp(struct snd_sof_dev *sdev) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; @@ -43,9 +48,10 @@ static void hda_ssp_set_cbp_cfp(struct snd_sof_dev *sdev) } } -struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format, - unsigned int size, struct snd_dma_buffer *dmab, - int direction, bool is_iccmax) +struct hdac_ext_stream* +hda_cl_prepare(struct device *dev, unsigned int format, unsigned int size, + struct snd_dma_buffer *dmab, bool persistent_buffer, int direction, + bool is_iccmax) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct hdac_ext_stream *hext_stream; @@ -61,11 +67,19 @@ struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format, hstream = &hext_stream->hstream; hstream->substream = NULL; - /* allocate DMA buffer */ - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev, size, dmab); - if (ret < 0) { - dev_err(sdev->dev, "error: memory alloc failed: %d\n", ret); - goto out_put; + /* + * Allocate DMA buffer if it is temporary or if the buffer is intended + * to be persistent but not yet allocated. + * We cannot rely solely on !dmab->area as caller might use a struct on + * stack (when it is temporary) without clearing it to 0. + */ + if (!persistent_buffer || !dmab->area) { + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev, size, dmab); + if (ret < 0) { + dev_err(sdev->dev, "%s: memory alloc failed: %d\n", + __func__, ret); + goto out_put; + } } hstream->period_bytes = 0;/* initialize period_bytes */ @@ -91,6 +105,10 @@ struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format, out_free: snd_dma_free_pages(dmab); + dmab->area = NULL; + dmab->bytes = 0; + hstream->bufsize = 0; + hstream->format_val = 0; out_put: hda_dsp_stream_put(sdev, direction, hstream->stream_tag); return ERR_PTR(ret); @@ -255,7 +273,7 @@ int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int EXPORT_SYMBOL_NS(hda_cl_trigger, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab, - struct hdac_ext_stream *hext_stream) + bool persistent_buffer, struct hdac_ext_stream *hext_stream) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct hdac_stream *hstream = &hext_stream->hstream; @@ -279,10 +297,14 @@ int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab, sd_offset + SOF_HDA_ADSP_REG_SD_BDLPU, 0); snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset, 0); - snd_dma_free_pages(dmab); - dmab->area = NULL; - hstream->bufsize = 0; - hstream->format_val = 0; + + if (!persistent_buffer) { + snd_dma_free_pages(dmab); + dmab->area = NULL; + dmab->bytes = 0; + hstream->bufsize = 0; + hstream->format_val = 0; + } return ret; } @@ -340,8 +362,8 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_ext_stream *iccmax_stream; - struct snd_dma_buffer dmab_bdl; int ret, ret1; u8 original_gb; @@ -354,7 +376,8 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) * the data, so use a buffer of PAGE_SIZE for receiving. */ iccmax_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, PAGE_SIZE, - &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE, true); + &hda->iccmax_dmab, persistent_cl_buffer, + SNDRV_PCM_STREAM_CAPTURE, true); if (IS_ERR(iccmax_stream)) { dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n"); return PTR_ERR(iccmax_stream); @@ -366,7 +389,8 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) * Perform iccmax stream cleanup. This should be done even if firmware loading fails. * If the cleanup also fails, we return the initial error */ - ret1 = hda_cl_cleanup(sdev->dev, &dmab_bdl, iccmax_stream); + ret1 = hda_cl_cleanup(sdev->dev, &hda->iccmax_dmab, + persistent_cl_buffer, iccmax_stream); if (ret1 < 0) { dev_err(sdev->dev, "error: ICCMAX stream cleanup failed\n"); @@ -408,7 +432,6 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) const struct sof_intel_dsp_desc *chip_info; struct hdac_ext_stream *hext_stream; struct firmware stripped_firmware; - struct snd_dma_buffer dmab; int ret, ret1, i; if (hda->imrboot_supported && !sdev->first_boot && !hda->skip_imr_boot) { @@ -432,23 +455,31 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) return -EINVAL; } - stripped_firmware.data = sdev->basefw.fw->data + sdev->basefw.payload_offset; - stripped_firmware.size = sdev->basefw.fw->size - sdev->basefw.payload_offset; - /* init for booting wait */ init_waitqueue_head(&sdev->boot_wait); /* prepare DMA for code loader stream */ + stripped_firmware.size = sdev->basefw.fw->size - sdev->basefw.payload_offset; hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, stripped_firmware.size, - &dmab, SNDRV_PCM_STREAM_PLAYBACK, false); + &hda->cl_dmab, persistent_cl_buffer, + SNDRV_PCM_STREAM_PLAYBACK, false); if (IS_ERR(hext_stream)) { dev_err(sdev->dev, "error: dma prepare for fw loading failed\n"); return PTR_ERR(hext_stream); } - memcpy(dmab.area, stripped_firmware.data, - stripped_firmware.size); + /* + * Copy the payload to the DMA buffer if it is temporary or if the + * buffer is persistent but it does not have the basefw payload either + * because this is the first boot and the buffer needs to be initialized, + * or a library got loaded and it replaced the basefw. + */ + if (!persistent_cl_buffer || !hda->cl_dmab_contains_basefw) { + stripped_firmware.data = sdev->basefw.fw->data + sdev->basefw.payload_offset; + memcpy(hda->cl_dmab.area, stripped_firmware.data, stripped_firmware.size); + hda->cl_dmab_contains_basefw = true; + } /* try ROM init a few times before giving up */ for (i = 0; i < HDA_FW_BOOT_ATTEMPTS; i++) { @@ -514,7 +545,8 @@ cleanup: * This should be done even if firmware loading fails. * If the cleanup also fails, we return the initial error */ - ret1 = hda_cl_cleanup(sdev->dev, &dmab, hext_stream); + ret1 = hda_cl_cleanup(sdev->dev, &hda->cl_dmab, + persistent_cl_buffer, hext_stream); if (ret1 < 0) { dev_err(sdev->dev, "error: Code loader DSP cleanup failed\n"); @@ -545,7 +577,6 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream; struct firmware stripped_firmware; struct sof_ipc4_msg msg = {}; - struct snd_dma_buffer dmab; int ret, ret1; /* if IMR booting is enabled and fw context is saved for D3 state, skip the loading */ @@ -556,16 +587,28 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, stripped_firmware.data = fw_lib->sof_fw.fw->data + fw_lib->sof_fw.payload_offset; stripped_firmware.size = fw_lib->sof_fw.fw->size - fw_lib->sof_fw.payload_offset; + /* + * force re-allocation of the cl_dmab if the preserved DMA buffer is + * smaller than what is needed for the library + */ + if (persistent_cl_buffer && stripped_firmware.size > hda->cl_dmab.bytes) { + snd_dma_free_pages(&hda->cl_dmab); + hda->cl_dmab.area = NULL; + hda->cl_dmab.bytes = 0; + } + /* prepare DMA for code loader stream */ hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, stripped_firmware.size, - &dmab, SNDRV_PCM_STREAM_PLAYBACK, false); + &hda->cl_dmab, persistent_cl_buffer, + SNDRV_PCM_STREAM_PLAYBACK, false); if (IS_ERR(hext_stream)) { dev_err(sdev->dev, "%s: DMA prepare failed\n", __func__); return PTR_ERR(hext_stream); } - memcpy(dmab.area, stripped_firmware.data, stripped_firmware.size); + memcpy(hda->cl_dmab.area, stripped_firmware.data, stripped_firmware.size); + hda->cl_dmab_contains_basefw = false; /* * 1st stage: SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE @@ -628,7 +671,8 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, cleanup: /* clean up even in case of error and return the first error */ - ret1 = hda_cl_cleanup(sdev->dev, &dmab, hext_stream); + ret1 = hda_cl_cleanup(sdev->dev, &hda->cl_dmab, persistent_cl_buffer, + hext_stream); if (ret1 < 0) { dev_err(sdev->dev, "%s: Code loader DSP cleanup failed\n", __func__); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 2d021d7bff3f..b916788a72dd 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -936,6 +936,12 @@ void hda_dsp_remove(struct snd_sof_dev *sdev) /* disable DSP */ hda_dsp_ctrl_ppcap_enable(sdev, false); + /* Free the persistent DMA buffers used for base firmware download */ + if (hda->cl_dmab.area) + snd_dma_free_pages(&hda->cl_dmab); + if (hda->iccmax_dmab.area) + snd_dma_free_pages(&hda->iccmax_dmab); + skip_disable_dsp: free_irq(sdev->ipc_irq, sdev); if (sdev->msi_enabled) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 4a4a0b55f0bc..ee4ccc1a5490 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -495,6 +495,15 @@ struct sof_intel_hda_dev { int boot_iteration; + /* + * DMA buffers for base firmware download. By default the buffers are + * allocated once and kept through the lifetime of the driver. + * See module parameter: persistent_cl_buffer + */ + struct snd_dma_buffer cl_dmab; + bool cl_dmab_contains_basefw; + struct snd_dma_buffer iccmax_dmab; + struct hda_bus hbus; /* hw config */ @@ -714,11 +723,12 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format, unsigned int size, struct snd_dma_buffer *dmab, - int direction, bool is_iccmax); + bool persistent_buffer, int direction, + bool is_iccmax); int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int cmd); int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab, - struct hdac_ext_stream *hext_stream); + bool persistent_buffer, struct hdac_ext_stream *hext_stream); int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot); #define HDA_CL_STREAM_FORMAT 0x40 From 459a5cfb35fb81353ba10fb4e5bfa8c5878edc69 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:08 +0100 Subject: [PATCH 189/256] ASoC: SOF: Intel: hda: handle only paused streams in hda_dai_suspend() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7a117225b15b2d1dc021ab9fc36687c1e61ad2b1 Author: Ranjani Sridharan Date: Thu Nov 7 15:49:57 2024 +0200 ASoC: SOF: Intel: hda: handle only paused streams in hda_dai_suspend() hda_dai_suspend() was added to handle paused stream during system suspend. But as a side effect, it also ends up cleaning up the DMA data for those streams that were prepared but not triggered before a system suspend. Since these streams will not receive the prepare callback after resuming, we need to preserve the DMA data during suspend. So, add the check to handle only those streams that are in the paused state to avoid losing the DMA data for all other streams. Link: https://github.com/thesofproject/linux/issues/5080 Signed-off-by: Ranjani Sridharan Reviewed-by: Fred Oh Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://patch.msgid.link/20241107134957.25160-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/intel/hda-dai.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 82f46ecd9430..09e23163240f 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -660,6 +660,10 @@ static int hda_dai_suspend(struct hdac_bus *bus) sdai = swidget->private; ops = sdai->platform_private; + if (rtd->dpcm[hext_stream->link_substream->stream].state != + SND_SOC_DPCM_STATE_PAUSED) + continue; + /* for consistency with TRIGGER_SUSPEND */ if (ops->post_trigger) { ret = ops->post_trigger(sdev, cpu_dai, From 6cff734a0924a1bb8e35505c323f6508bdbb4cf8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:08 +0100 Subject: [PATCH 190/256] ASoC: ux500: Remove redundant casts JIRA: https://issues.redhat.com/browse/RHEL-80681 commit fa24fdc8ae9e6f6fe7a4f7676a4d8c14433a86c0 Author: Tang Bin Date: Thu Nov 7 15:54:40 2024 +0800 ASoC: ux500: Remove redundant casts In the function ux500_msp_drv_probe, the 'int' type cast in front of the PTR_ERR() macro is redundant, thus remove it. Signed-off-by: Tang Bin Link: https://patch.msgid.link/20241107075440.2770-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/ux500/ux500_msp_dai.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 63c02d6d3e6c..d5bd25c34a81 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -761,7 +761,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape"); if (IS_ERR(drvdata->reg_vape)) { - ret = (int)PTR_ERR(drvdata->reg_vape); + ret = PTR_ERR(drvdata->reg_vape); dev_err(&pdev->dev, "%s: ERROR: Failed to get Vape supply (%d)!\n", __func__, ret); @@ -771,7 +771,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) drvdata->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); if (IS_ERR(drvdata->pclk)) { - ret = (int)PTR_ERR(drvdata->pclk); + ret = PTR_ERR(drvdata->pclk); dev_err(&pdev->dev, "%s: ERROR: devm_clk_get of pclk failed (%d)!\n", __func__, ret); @@ -780,7 +780,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) drvdata->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(drvdata->clk)) { - ret = (int)PTR_ERR(drvdata->clk); + ret = PTR_ERR(drvdata->clk); dev_err(&pdev->dev, "%s: ERROR: devm_clk_get failed (%d)!\n", __func__, ret); From d708606baf4e9a7d9e0ecb4b29d018987d5d5465 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:33 +0100 Subject: [PATCH 191/256] ASoC: sma1307: Fix invalid logical judgement JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 08aa540a196a672b8597fb611e2dc25e42986bd9 Author: Tang Bin Date: Fri Nov 8 09:16:17 2024 +0800 ASoC: sma1307: Fix invalid logical judgement In the function sma1307_dai_hw_params_amp, the variable 'ret' has not been assigned a value, so the logical judgement is invalid, thus fix it. Signed-off-by: Tang Bin Link: https://patch.msgid.link/20241108011617.2284-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/sma1307.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c index 985a247b3310..81638768ac12 100644 --- a/sound/soc/codecs/sma1307.c +++ b/sound/soc/codecs/sma1307.c @@ -1191,7 +1191,6 @@ static int sma1307_dai_hw_params_amp(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); unsigned int bclk = 0; - int ret = 0; if (sma1307->format == SND_SOC_DAIFMT_DSP_A) bclk = params_rate(params) * sma1307->frame_size; @@ -1336,8 +1335,6 @@ static int sma1307_dai_hw_params_amp(struct snd_pcm_substream *substream, params_format(params)); return -EINVAL; } - if (ret < 0) - return -EINVAL; return 0; } From c0b964140553f96e48c7d37118c9c2821048f79d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:43 +0100 Subject: [PATCH 192/256] ASoC: Intel: Kconfig: Only select SND_SOC_SDCA if ACPI is enabled JIRA: https://issues.redhat.com/browse/RHEL-80681 commit c5bbc47f8e094f4489934a244ee1c14947a5075e Author: Peter Ujfalusi Date: Thu Nov 7 12:02:03 2024 +0200 ASoC: Intel: Kconfig: Only select SND_SOC_SDCA if ACPI is enabled The SDCA module have hard dependency to compile on ACPI, it can only be selected if ACPI is also enabled. The SDCA header provides inline prototypes for other modules to compile in case SND_SOC_SDCA is not enabled. Fixes: 845cb1ddf1fc ("ASoC: Intel: Kconfig: select SND_SOC_SDCA by SND_SOC_ACPI_INTEL_SDCA_QUIRKS") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202411070806.UhCRpZok-lkp@intel.com/ Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Link: https://patch.msgid.link/20241107100204.24952-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/intel/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 870f88e95718..7b08ad7d7946 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -201,7 +201,7 @@ config SND_SOC_ACPI_INTEL_MATCH config SND_SOC_ACPI_INTEL_SDCA_QUIRKS tristate - select SND_SOC_SDCA + select SND_SOC_SDCA if ACPI endif ## SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL From e5ddbb7fb7a8333f8c036296a490d8243867a5df Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:43 +0100 Subject: [PATCH 193/256] ASoC: Intel: Kconfig: Revert make SND_SOC_ACPI_INTEL_MATCH depend on ACPI JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 4f1636e7b0384c43856e1442755f48d7c690c2a9 Author: Peter Ujfalusi Date: Thu Nov 7 12:02:04 2024 +0200 ASoC: Intel: Kconfig: Revert make SND_SOC_ACPI_INTEL_MATCH depend on ACPI The acpi-intel-match should be compiled even if ACPI is not selected. The ACPI is not compile time requirement, but the exported symbols are needed for other modules. Fixes: b6bd3f3b6357 ("ASoC: Intel: Kconfig: make SND_SOC_ACPI_INTEL_MATCH depend on ACPI") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202411070806.UhCRpZok-lkp@intel.com/ Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Link: https://patch.msgid.link/20241107100204.24952-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/intel/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 7b08ad7d7946..b91774f0042e 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -193,8 +193,7 @@ if SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL config SND_SOC_ACPI_INTEL_MATCH tristate - depends on ACPI - select SND_SOC_ACPI + select SND_SOC_ACPI if ACPI select SND_SOC_ACPI_INTEL_SDCA_QUIRKS # this option controls the compilation of ACPI matching tables and # helpers and is not meant to be selected by the user. From f6bf3bdac04e6c94d25af1d1e58263759f2c261d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:43 +0100 Subject: [PATCH 194/256] ALSA: ump: remove unnecessary check on blk JIRA: https://issues.redhat.com/browse/RHEL-80681 commit eab936aa8500ea09fb3faad25af817221b8a5cb2 Author: Luo Yifan Date: Fri Nov 8 11:27:02 2024 +0800 ALSA: ump: remove unnecessary check on blk The unsigned expression 'blk' will never be negative, so remove the unnecessary check. Signed-off-by: Luo Yifan Link: https://patch.msgid.link/20241108032702.217168-1-luoyifan@cmss.chinamobile.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/core/ump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/ump.c b/sound/core/ump.c index abc537d54b73..ea6f0fe6d841 100644 --- a/sound/core/ump.c +++ b/sound/core/ump.c @@ -370,7 +370,7 @@ int snd_ump_block_new(struct snd_ump_endpoint *ump, unsigned int blk, { struct snd_ump_block *fb, *p; - if (blk < 0 || blk >= SNDRV_UMP_MAX_BLOCKS) + if (blk >= SNDRV_UMP_MAX_BLOCKS) return -EINVAL; if (snd_ump_get_block(ump, blk)) From 817e3f592471178af2f3ed0de15a144184e5b511 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:43 +0100 Subject: [PATCH 195/256] ASoC: qcom: sm8250: add handling of secondary MI2S clock JIRA: https://issues.redhat.com/browse/RHEL-80681 commit ed7bca5b2b891caedf2ed3ffc427eba23559da95 Author: Alexey Klimov Date: Fri Oct 18 03:54:47 2024 +0100 ASoC: qcom: sm8250: add handling of secondary MI2S clock Add handling of clock related to secondary MI2S_RX in sm8250_snd_startup(). Cc: Srinivas Kandagatla Reviewed-by: Dmitry Baryshkov Signed-off-by: Alexey Klimov Link: https://patch.msgid.link/20241018025452.1362293-2-alexey.klimov@linaro.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/qcom/sm8250.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c index a1ff8d770958..5c65324a3e5e 100644 --- a/sound/soc/qcom/sm8250.c +++ b/sound/soc/qcom/sm8250.c @@ -64,6 +64,14 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream) snd_soc_dai_set_fmt(cpu_dai, fmt); snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); break; + case SECONDARY_MI2S_RX: + codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; + snd_soc_dai_set_sysclk(cpu_dai, + Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT, + MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); + snd_soc_dai_set_fmt(cpu_dai, fmt); + snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); + break; case TERTIARY_MI2S_RX: codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; snd_soc_dai_set_sysclk(cpu_dai, From ab79024ffa581eda0c378b930046656d43f6f88f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:44 +0100 Subject: [PATCH 196/256] ASoC: machine: update documentation JIRA: https://issues.redhat.com/browse/RHEL-80681 commit e90dbd3839f554bef35786c4bec8276455691b20 Author: anish kumar Date: Sat Nov 9 11:22:31 2024 -0800 ASoC: machine: update documentation 1. Added clocking details. 2. Updated ways to register the dai's 3. Bit more detail about card registration details. Signed-off-by: anish kumar Reviewed-by: Bagas Sanjaya Link: https://patch.msgid.link/20241109192231.11623-1-yesanishhere@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- Documentation/sound/soc/machine.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Documentation/sound/soc/machine.rst b/Documentation/sound/soc/machine.rst index 515c9444deaf..9db132bc0070 100644 --- a/Documentation/sound/soc/machine.rst +++ b/Documentation/sound/soc/machine.rst @@ -71,6 +71,18 @@ struct snd_soc_dai_link is used to set up each DAI in your machine. e.g. .ops = &corgi_ops, }; +In the above struct, dai’s are registered using names but you can pass +either dai name or device tree node but not both. Also, names used here +for cpu/codec/platform dais should be globally unique. + +Additionaly below example macro can be used to register cpu, codec and +platform dai:: + + SND_SOC_DAILINK_DEFS(wm2200_cpu_dsp, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + struct snd_soc_card then sets up the machine with its DAIs. e.g. :: @@ -81,6 +93,10 @@ struct snd_soc_card then sets up the machine with its DAIs. e.g. .num_links = 1, }; +Following this, ``devm_snd_soc_register_card`` can be used to register +the sound card. During the registration, the individual components +such as the codec, CPU, and platform are probed. If all these components +are successfully probed, the sound card gets registered. Machine Power Map ----------------- @@ -95,3 +111,13 @@ Machine Controls ---------------- Machine specific audio mixer controls can be added in the DAI init function. + + +Clocking Controls +----------------- + +As previously noted, clock configuration is handled within the machine driver. +For details on the clock APIs that the machine driver can utilize for +setup, please refer to Documentation/sound/soc/clocking.rst. However, the +callback needs to be registered by the CPU/Codec/Platform drivers to configure +the clocks that is needed for the corresponding device operation. From b143990b656d5b374e8a3c77923a4b81b9cca427 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:43:44 +0100 Subject: [PATCH 197/256] ASoC: max98088: Remove duplicate DACs JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 725570f96321f3e0ae1c6a1f80482d2907538d07 Author: Marek Vasut Date: Sat Nov 9 00:53:47 2024 +0100 ASoC: max98088: Remove duplicate DACs This codec only has one set of left and right DACs, remove the duplicate DACs with duplicated bits controlling them as the userspace can set those controls to mismatched value. This most likely does break userspace ABI, but there seem to be no in-kernel users. Signed-off-by: Marek Vasut Link: https://patch.msgid.link/20241108235453.196289-1-marex@denx.de Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/max98088.c | 80 ++++++++++++------------------------- 1 file changed, 26 insertions(+), 54 deletions(-) diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 56773e3fd552..abc3b16c9a41 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -515,10 +515,8 @@ static const struct snd_kcontrol_new max98088_snd_controls[] = { /* Left speaker mixer switch */ static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0), @@ -529,10 +527,8 @@ static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { /* Right speaker mixer switch */ static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0), @@ -543,10 +539,8 @@ static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = { /* Left headphone mixer switch */ static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0), @@ -557,10 +551,8 @@ static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { /* Right headphone mixer switch */ static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0), @@ -571,10 +563,8 @@ static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = { /* Left earpiece/receiver mixer switch */ static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0), @@ -585,10 +575,8 @@ static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { /* Right earpiece/receiver mixer switch */ static const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0), @@ -717,13 +705,9 @@ static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 1, 0), SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 0, 0), - SND_SOC_DAPM_DAC("DACL1", "HiFi Playback", + SND_SOC_DAPM_DAC("DACL", "HiFi Playback", M98088_REG_4D_PWR_EN_OUT, 1, 0), - SND_SOC_DAPM_DAC("DACR1", "HiFi Playback", - M98088_REG_4D_PWR_EN_OUT, 0, 0), - SND_SOC_DAPM_DAC("DACL2", "Aux Playback", - M98088_REG_4D_PWR_EN_OUT, 1, 0), - SND_SOC_DAPM_DAC("DACR2", "Aux Playback", + SND_SOC_DAPM_DAC("DACR", "HiFi Playback", M98088_REG_4D_PWR_EN_OUT, 0, 0), SND_SOC_DAPM_PGA("HP Left Out", M98088_REG_4D_PWR_EN_OUT, @@ -819,10 +803,8 @@ static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { static const struct snd_soc_dapm_route max98088_audio_map[] = { /* Left headphone output mixer */ - {"Left HP Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left HP Mixer", "Left DAC2 Switch", "DACL2"}, - {"Left HP Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left HP Mixer", "Right DAC2 Switch", "DACR2"}, + {"Left HP Mixer", "Left DAC Switch", "DACL"}, + {"Left HP Mixer", "Right DAC Switch", "DACR"}, {"Left HP Mixer", "MIC1 Switch", "MIC1 Input"}, {"Left HP Mixer", "MIC2 Switch", "MIC2 Input"}, {"Left HP Mixer", "INA1 Switch", "INA1 Input"}, @@ -831,10 +813,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = { {"Left HP Mixer", "INB2 Switch", "INB2 Input"}, /* Right headphone output mixer */ - {"Right HP Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right HP Mixer", "Left DAC2 Switch", "DACL2" }, - {"Right HP Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right HP Mixer", "Right DAC2 Switch", "DACR2"}, + {"Right HP Mixer", "Left DAC Switch", "DACL"}, + {"Right HP Mixer", "Right DAC Switch", "DACR"}, {"Right HP Mixer", "MIC1 Switch", "MIC1 Input"}, {"Right HP Mixer", "MIC2 Switch", "MIC2 Input"}, {"Right HP Mixer", "INA1 Switch", "INA1 Input"}, @@ -843,10 +823,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = { {"Right HP Mixer", "INB2 Switch", "INB2 Input"}, /* Left speaker output mixer */ - {"Left SPK Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left SPK Mixer", "Left DAC2 Switch", "DACL2"}, - {"Left SPK Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left SPK Mixer", "Right DAC2 Switch", "DACR2"}, + {"Left SPK Mixer", "Left DAC Switch", "DACL"}, + {"Left SPK Mixer", "Right DAC Switch", "DACR"}, {"Left SPK Mixer", "MIC1 Switch", "MIC1 Input"}, {"Left SPK Mixer", "MIC2 Switch", "MIC2 Input"}, {"Left SPK Mixer", "INA1 Switch", "INA1 Input"}, @@ -855,10 +833,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = { {"Left SPK Mixer", "INB2 Switch", "INB2 Input"}, /* Right speaker output mixer */ - {"Right SPK Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right SPK Mixer", "Left DAC2 Switch", "DACL2"}, - {"Right SPK Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right SPK Mixer", "Right DAC2 Switch", "DACR2"}, + {"Right SPK Mixer", "Left DAC Switch", "DACL"}, + {"Right SPK Mixer", "Right DAC Switch", "DACR"}, {"Right SPK Mixer", "MIC1 Switch", "MIC1 Input"}, {"Right SPK Mixer", "MIC2 Switch", "MIC2 Input"}, {"Right SPK Mixer", "INA1 Switch", "INA1 Input"}, @@ -867,10 +843,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = { {"Right SPK Mixer", "INB2 Switch", "INB2 Input"}, /* Earpiece/Receiver output mixer */ - {"Left REC Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left REC Mixer", "Left DAC2 Switch", "DACL2"}, - {"Left REC Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left REC Mixer", "Right DAC2 Switch", "DACR2"}, + {"Left REC Mixer", "Left DAC Switch", "DACL"}, + {"Left REC Mixer", "Right DAC Switch", "DACR"}, {"Left REC Mixer", "MIC1 Switch", "MIC1 Input"}, {"Left REC Mixer", "MIC2 Switch", "MIC2 Input"}, {"Left REC Mixer", "INA1 Switch", "INA1 Input"}, @@ -879,10 +853,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = { {"Left REC Mixer", "INB2 Switch", "INB2 Input"}, /* Earpiece/Receiver output mixer */ - {"Right REC Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right REC Mixer", "Left DAC2 Switch", "DACL2"}, - {"Right REC Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right REC Mixer", "Right DAC2 Switch", "DACR2"}, + {"Right REC Mixer", "Left DAC Switch", "DACL"}, + {"Right REC Mixer", "Right DAC Switch", "DACR"}, {"Right REC Mixer", "MIC1 Switch", "MIC1 Input"}, {"Right REC Mixer", "MIC2 Switch", "MIC2 Input"}, {"Right REC Mixer", "INA1 Switch", "INA1 Input"}, From 4874dcb0ad6ba58b6c4c6a1953e83990ed7eba1a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:00 +0100 Subject: [PATCH 198/256] ASoc: SOF: ipc4-pcm: fix uninit-value in sof_ipc4_pcm_dai_link_fixup_rate JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9a59718a5340aa0240a442115eb499de2ed18ee4 Author: Suraj Sonawane Date: Thu Nov 7 12:06:09 2024 +0530 ASoc: SOF: ipc4-pcm: fix uninit-value in sof_ipc4_pcm_dai_link_fixup_rate Fix an issue detected by the Smatch tool: sound/soc/sof/ipc4-pcm.c: sof_ipc4_pcm_dai_link_fixup_rate() error: uninitialized symbol 'be_rate'. The warning highlights a case where `be_rate` could remain uninitialized if `num_input_formats` is zero, which would cause undefined behavior when setting `rate->min` and `rate->max` based on `be_rate`. To address this issue, a `WARN_ON_ONCE(!num_input_formats)` check was added to ensure `num_input_formats` is greater than zero. If this condition fails, the function returns `-EINVAL`, preventing the use of an uninitialized `be_rate`. This change improves the robustness of the function by catching an invalid state early and providing better feedback during development. Signed-off-by: Suraj Sonawane Link: https://patch.msgid.link/20241107063609.11627-1-surajsonawane0215@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc4-pcm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 4df2be3d39eb..18fff2df76f9 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -603,6 +603,9 @@ static int sof_ipc4_pcm_dai_link_fixup_rate(struct snd_sof_dev *sdev, unsigned int be_rate; int i; + if (WARN_ON_ONCE(!num_input_formats)) + return -EINVAL; + /* * Copier does not change sampling rate, so we * need to only consider the input pin information. From 0f006e05df7d50a40bd99a03412a8f9b11f2e81f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:01 +0100 Subject: [PATCH 199/256] ASoC: max98088: Add left/right DAC volume control JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 14c7f4867b7e4ddbbde58b398452295051c77137 Author: Marek Vasut Date: Mon Nov 11 17:54:04 2024 +0100 ASoC: max98088: Add left/right DAC volume control Add left/right DAC digital volume control knob. Signed-off-by: Marek Vasut Link: https://patch.msgid.link/20241111165435.113086-1-marex@denx.de Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/max98088.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index abc3b16c9a41..614c58fd47f8 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -480,6 +480,9 @@ static const struct snd_kcontrol_new max98088_snd_controls[] = { SOC_SINGLE("INA Volume", M98088_REG_37_LVL_INA, 0, 7, 1), SOC_SINGLE("INB Volume", M98088_REG_38_LVL_INB, 0, 7, 1), + SOC_SINGLE("DACL Volume", M98088_REG_2F_LVL_DAI1_PLAY, 0, 15, 1), + SOC_SINGLE("DACR Volume", M98088_REG_31_LVL_DAI2_PLAY, 0, 15, 1), + SOC_SINGLE("ADCL Volume", M98088_REG_33_LVL_ADC_L, 0, 15, 0), SOC_SINGLE("ADCR Volume", M98088_REG_34_LVL_ADC_R, 0, 15, 0), From f528e7ae9657612782f3b5a3c7eb80941f21d491 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:01 +0100 Subject: [PATCH 200/256] ASoC: max98088: Add headphone mixer switch JIRA: https://issues.redhat.com/browse/RHEL-80681 commit d0621105eff307408ceb3d0eb61ca2a23c37fcbe Author: Marek Vasut Date: Mon Nov 11 17:55:04 2024 +0100 ASoC: max98088: Add headphone mixer switch Add enable/disable headphone output mixers knob. Signed-off-by: Marek Vasut Link: https://patch.msgid.link/20241111165523.113142-1-marex@denx.de Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/max98088.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 614c58fd47f8..9b0cba843b46 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -489,6 +489,9 @@ static const struct snd_kcontrol_new max98088_snd_controls[] = { SOC_SINGLE("ADCL Boost Volume", M98088_REG_33_LVL_ADC_L, 4, 3, 0), SOC_SINGLE("ADCR Boost Volume", M98088_REG_34_LVL_ADC_R, 4, 3, 0), + SOC_SINGLE("Left HP Output Mixer Switch", M98088_REG_27_MIX_HP_CNTL, 4, 1, 0), + SOC_SINGLE("Right HP Output Mixer Switch", M98088_REG_27_MIX_HP_CNTL, 5, 1, 0), + SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0), SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0), From e2965d44ad25b1f20957841389208c157d915f95 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:01 +0100 Subject: [PATCH 201/256] ASoC: test-component: Support continuous rates for test component JIRA: https://issues.redhat.com/browse/RHEL-80681 commit c853e96308c58f9a06fcf393bcfe0eabdb72ca9c Author: John Watts Date: Tue Nov 12 21:34:00 2024 +1100 ASoC: test-component: Support continuous rates for test component There's no reason to limit the supported rates of the test component to specific ones as if it's a real piece of hardware. Set the rates to continuous to aid in testing different rates. Signed-off-by: John Watts Link: https://patch.msgid.link/20241112-alsa_test_rates-v1-1-95cf529db871@jookia.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/generic/test-component.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c index f25c77a47cdf..973192e61978 100644 --- a/sound/soc/generic/test-component.c +++ b/sound/soc/generic/test-component.c @@ -224,7 +224,7 @@ static const struct snd_soc_dai_ops test_verbose_ops = { .num_auto_selectable_formats = 1, }; -#define STUB_RATES SNDRV_PCM_RATE_8000_384000 +#define STUB_RATES SNDRV_PCM_RATE_CONTINUOUS #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_U8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ From b2c406775c59a7ac436b53ea8d165e19edd0579e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:01 +0100 Subject: [PATCH 202/256] ASoC: simple-card-utils: care simple_util_dai for dummy DAI JIRA: https://issues.redhat.com/browse/RHEL-80681 commit add2332795a648b62fd52356001287c015a59e80 Author: Kuninori Morimoto Date: Tue Nov 12 02:39:44 2024 +0000 ASoC: simple-card-utils: care simple_util_dai for dummy DAI Simple Card Utils has simple_util_dai which is paired to snd_soc_dai, and assmus that CPU/Codec DAI and its paired simple_util_dai are same order for CPU/Codec simple_util_dai[0] <--> snd_soc_dai[0] simple_util_dai[1] <--> snd_soc_dai[1] ... So, it is using same index in for_each loop. (X) gets simple_util_dai (Y) gets snd_soc_dai (Y) for_each_rtd_cpu_dais(.., i, ..) { (X)(A) udai = simple_props_to_dai_cpu(.., i); } (X) for_each_prop_dai_cpu(.., i, ...) { (Y) dai = snd_soc_rtd_to_cpu(.., i); ... } But current Simple Card Utils didn't have simple_util_dai for dummy DAI. So above (A) will get NULL pointer in such case. This patch cares simple_util_dai for dummy DAI. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87msi5maz3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/generic/simple-card-utils.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 044a0c903ef5..fcd789c498e2 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -858,6 +858,10 @@ int simple_util_init_aux_jacks(struct simple_util_priv *priv, char *prefix) } EXPORT_SYMBOL_GPL(simple_util_init_aux_jacks); +static struct simple_util_dai dummy_util_dais = { + .name = "dummy_util_dais", +}; + int simple_util_init_priv(struct simple_util_priv *priv, struct link_info *li) { @@ -929,6 +933,7 @@ int simple_util_init_priv(struct simple_util_priv *priv, dai_link[i].cpus = &snd_soc_dummy_dlc; dai_props[i].num.cpus = dai_link[i].num_cpus = 1; + dai_props[i].cpu_dai = &dummy_util_dais; } if (li->num[i].codecs) { @@ -951,6 +956,7 @@ int simple_util_init_priv(struct simple_util_priv *priv, dai_link[i].codecs = &snd_soc_dummy_dlc; dai_props[i].num.codecs = dai_link[i].num_codecs = 1; + dai_props[i].codec_dai = &dummy_util_dais; } if (li->num[i].platforms) { From faf5e514cf23c3b5865f07b9d006bb67fb3009e6 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:01 +0100 Subject: [PATCH 203/256] ALSA: tidyup SNDRV_PCM_TRIGGER_xxx numbering JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 8f80f378e77eafdcdb7ea9a76cc645ecd04fb4e5 Author: Kuninori Morimoto Date: Wed Nov 13 01:17:25 2024 +0000 ALSA: tidyup SNDRV_PCM_TRIGGER_xxx numbering pcm.h has SNDRV_PCM_TRIGGER_xxx, but it is missing "2". Fixup it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ed3gsziy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/pcm.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 0bf7d25434d7..ef9cbeaf3784 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -97,11 +97,11 @@ struct snd_pcm_ops { #define SNDRV_PCM_TRIGGER_STOP 0 #define SNDRV_PCM_TRIGGER_START 1 -#define SNDRV_PCM_TRIGGER_PAUSE_PUSH 3 -#define SNDRV_PCM_TRIGGER_PAUSE_RELEASE 4 -#define SNDRV_PCM_TRIGGER_SUSPEND 5 -#define SNDRV_PCM_TRIGGER_RESUME 6 -#define SNDRV_PCM_TRIGGER_DRAIN 7 +#define SNDRV_PCM_TRIGGER_PAUSE_PUSH 2 +#define SNDRV_PCM_TRIGGER_PAUSE_RELEASE 3 +#define SNDRV_PCM_TRIGGER_SUSPEND 4 +#define SNDRV_PCM_TRIGGER_RESUME 5 +#define SNDRV_PCM_TRIGGER_DRAIN 6 #define SNDRV_PCM_POS_XRUN ((snd_pcm_uframes_t)-1) From 19816e5701719f0b549a067ff5a25b7cd0635d40 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:01 +0100 Subject: [PATCH 204/256] ALSA: pcm: Define snd_pcm_mmap_data_{open|close}() locally JIRA: https://issues.redhat.com/browse/RHEL-80681 commit f69c2861b05e29c69abed6aafe0cefd224d9d4db Author: Takashi Iwai Date: Wed Nov 13 12:16:27 2024 +0100 ALSA: pcm: Define snd_pcm_mmap_data_{open|close}() locally snd_pcm_mmap_data_open() and _close() are defined as inline functions in the public sound/pcm.h, but those are used only locally in pcm_native.c, hence they should be better placed there. Also, those are referred as callbacks, the useless inline is dropped. Link: https://patch.msgid.link/20241113111628.17069-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/pcm.h | 24 ------------------------ sound/core/pcm_native.c | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index ef9cbeaf3784..67c99ffbf51b 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1393,30 +1393,6 @@ snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, return snd_sgbuf_get_chunk_size(snd_pcm_get_dma_buf(substream), ofs, size); } -/** - * snd_pcm_mmap_data_open - increase the mmap counter - * @area: VMA - * - * PCM mmap callback should handle this counter properly - */ -static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) -{ - struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; - atomic_inc(&substream->mmap_count); -} - -/** - * snd_pcm_mmap_data_close - decrease the mmap counter - * @area: VMA - * - * PCM mmap callback should handle this counter properly - */ -static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) -{ - struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; - atomic_dec(&substream->mmap_count); -} - int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *area); /* mmap for io-memory area */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index eec0b763ef2f..518c45075480 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3773,6 +3773,26 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file } #endif /* coherent mmap */ +/* + * snd_pcm_mmap_data_open - increase the mmap counter + */ +static void snd_pcm_mmap_data_open(struct vm_area_struct *area) +{ + struct snd_pcm_substream *substream = area->vm_private_data; + + atomic_inc(&substream->mmap_count); +} + +/* + * snd_pcm_mmap_data_close - decrease the mmap counter + */ +static void snd_pcm_mmap_data_close(struct vm_area_struct *area) +{ + struct snd_pcm_substream *substream = area->vm_private_data; + + atomic_dec(&substream->mmap_count); +} + /* * fault callback for mmapping a RAM page */ From b0cf6a66c1f316bd48ba2391aab9f9dc96e766fb Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:02 +0100 Subject: [PATCH 205/256] ALSA: compress_offload: Add missing descriptions in structs JIRA: https://issues.redhat.com/browse/RHEL-80681 commit b773c086ed58c7e9111a4d4f251a98db3d4165d8 Author: Takashi Iwai Date: Wed Nov 13 08:23:03 2024 +0100 ALSA: compress_offload: Add missing descriptions in structs Add the missing descriptions for snd_compr_ops, snd_compr_task and snd_compr_task_status fields, in order to shut up the build warnings. Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode") Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/20241028193731.4b0c3788@canb.auug.org.au Link: https://patch.msgid.link/20241113072304.4447-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/compress_driver.h | 4 ++++ include/uapi/sound/compress_offload.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 5db4881b0681..b55c9eeb2b54 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -143,6 +143,10 @@ struct snd_compr_stream { * Not valid if copy is implemented * @get_caps: Retrieve DSP capabilities, mandatory * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory + * @task_create: Create a set of input/output buffers for accel operations + * @task_start: Start (queue) a task for accel operations + * @task_stop: Stop (dequeue) a task for accel operations + * @task_free: Free a set of input/output buffers for accel operations */ struct snd_compr_ops { int (*open)(struct snd_compr_stream *stream); diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index 98772b0cbcb7..d62eb93af0ed 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -139,6 +139,7 @@ struct snd_compr_metadata { * @output_fd: data output file descriptor (dma-buf) * @input_size: filled data in bytes (from caller, must not exceed fragment size) * @flags: see SND_COMPRESS_TFLG_* defines + * @reserved: reserved for future extension */ struct snd_compr_task { __u64 seqno; @@ -169,6 +170,7 @@ enum snd_compr_state { * @output_size: filled data in bytes (from driver) * @output_flags: reserved for future (all zeros - from driver) * @state: actual task state (SND_COMPRESS_TASK_STATE_*) + * @reserved: reserved for future extension */ struct snd_compr_task_status { __u64 seqno; From 7523706e6557d2aaa4f1a3eb43079e1f0ae2f1aa Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:02 +0100 Subject: [PATCH 206/256] ASoC: amd: acp: add rt722 based soundwire machines JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 804aaa9df6c3bf9744205ae51cad084ee97567bc Author: Vijendar Mukunda Date: Wed Nov 13 17:22:18 2024 +0530 ASoC: amd: acp: add rt722 based soundwire machines Add RT722 based soundwire machines for legacy(NO DSP) stack for acp 6.3 platform. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20241113115223.3274868-2-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/amd-acp63-acpi-match.c | 49 ++++++++++++++++++++++++ sound/soc/amd/mach-config.h | 1 + 2 files changed, 50 insertions(+) diff --git a/sound/soc/amd/acp/amd-acp63-acpi-match.c b/sound/soc/amd/acp/amd-acp63-acpi-match.c index be9367913073..5e506c9e3da6 100644 --- a/sound/soc/amd/acp/amd-acp63-acpi-match.c +++ b/sound/soc/amd/acp/amd-acp63-acpi-match.c @@ -73,6 +73,45 @@ static const struct snd_soc_acpi_link_adr acp63_4_in_1_sdca[] = { {} }; +static const struct snd_soc_acpi_endpoint rt722_endpoints[] = { + { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = { + { + .adr = 0x000030025d072201ull, + .num_endpoints = ARRAY_SIZE(rt722_endpoints), + .endpoints = rt722_endpoints, + .name_prefix = "rt722" + } +}; + +static const struct snd_soc_acpi_link_adr acp63_rt722_only[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt722_0_single_adr), + .adr_d = rt722_0_single_adr, + }, + {} +}; + struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[] = { { .link_mask = BIT(0) | BIT(1), @@ -85,6 +124,16 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[] = { }; EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_sdw_machines); +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[] = { + { + .link_mask = BIT(0), + .links = acp63_rt722_only, + .drv_name = "amd_sdw", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sdw_machines); + MODULE_DESCRIPTION("AMD ACP6.3 tables and support for ACPI enumeration"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h index 1a967da35a0f..a86c76f781f9 100644 --- a/sound/soc/amd/mach-config.h +++ b/sound/soc/amd/mach-config.h @@ -23,6 +23,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sof_machines[]; From 545b46c8af0c941148fe259550869afb999e1983 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:02 +0100 Subject: [PATCH 207/256] ASoC: amd: acp: add RT711, RT714 & RT1316 support for acp 6.3 platform JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7d3fe292efb637d1f748926390a3a4cc90c4c4e9 Author: Vijendar Mukunda Date: Wed Nov 13 17:22:19 2024 +0530 ASoC: amd: acp: add RT711, RT714 & RT1316 support for acp 6.3 platform This patch add supports for corresponding codecs on acp6.3 platform hardware configuration. SDW0: RT711 Jack SDW0: RT1316 Left Speaker SDW0: RT1316 Right Speaker SDW1: RT714 DMIC Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20241113115223.3274868-3-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/amd-acp63-acpi-match.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/amd/acp/amd-acp63-acpi-match.c b/sound/soc/amd/acp/amd-acp63-acpi-match.c index 5e506c9e3da6..9b6a49c051cd 100644 --- a/sound/soc/amd/acp/amd-acp63-acpi-match.c +++ b/sound/soc/amd/acp/amd-acp63-acpi-match.c @@ -130,6 +130,11 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[] = { .links = acp63_rt722_only, .drv_name = "amd_sdw", }, + { + .link_mask = BIT(0) | BIT(1), + .links = acp63_4_in_1_sdca, + .drv_name = "amd_sdw", + }, {}, }; EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sdw_machines); From 7a4ecdf5e914f0272a1f48c373ff39854a829962 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:02 +0100 Subject: [PATCH 208/256] ASoC: amd: ps: add soundwire machines for acp6.3 platform JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 56d540befd5940dc34b4e22cc9b8ce9bb45946f7 Author: Vijendar Mukunda Date: Wed Nov 13 17:22:20 2024 +0530 ASoC: amd: ps: add soundwire machines for acp6.3 platform Add SoundWire machines for acp 6.3 platform for legacy(No DSP) stack. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20241113115223.3274868-4-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/ps/pci-ps.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index cec97bcc98b6..7850b62e27c8 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -615,6 +615,7 @@ static int snd_acp63_probe(struct pci_dev *pci, dev_err(&pci->dev, "ACP platform devices creation failed\n"); goto de_init; } + adata->machines = snd_soc_acpi_amd_acp63_sdw_machines; ret = acp63_machine_register(&pci->dev); if (ret) { dev_err(&pci->dev, "ACP machine register failed\n"); From ba4ced99b8e186d1ef2ee5e670ed8c7dd1fdef84 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:03 +0100 Subject: [PATCH 209/256] ASoC: amd: acp: move get_acp63_cpu_pin_id() to common file JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 393347cc10ea24c9f93b45e8e2f90fcc48ab1d8e Author: Vijendar Mukunda Date: Wed Nov 13 17:22:21 2024 +0530 ASoC: amd: acp: move get_acp63_cpu_pin_id() to common file get_acp63_cpu_pin_id() is the common SoundWire machine driver helper function will be used for AMD Legacy(No DSP) generic SoundWire machine driver as well. Move get_acp63_cpu_pin_id() function to common place holder. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20241113115223.3274868-5-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/Kconfig | 7 +++ sound/soc/amd/acp/Makefile | 2 + sound/soc/amd/acp/acp-sdw-mach-common.c | 64 +++++++++++++++++++++++++ sound/soc/amd/acp/acp-sdw-sof-mach.c | 49 +------------------ sound/soc/amd/acp/soc_amd_sdw_common.h | 2 + 5 files changed, 76 insertions(+), 48 deletions(-) create mode 100644 sound/soc/amd/acp/acp-sdw-mach-common.c diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index 88391e4c17e3..acd047d558bd 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -119,10 +119,17 @@ config SND_SOC_AMD_SOF_MACH help This option enables SOF sound card support for ACP audio. +config SND_SOC_AMD_SDW_MACH_COMMON + tristate + help + This option enables common SoundWire Machine driver module for + AMD platforms. + config SND_SOC_AMD_SOF_SDW_MACH tristate "AMD SOF Soundwire Machine Driver Support" depends on X86 && PCI && ACPI depends on SOUNDWIRE + select SND_SOC_AMD_SDW_MACH_COMMON select SND_SOC_SDW_UTILS select SND_SOC_DMIC select SND_SOC_RT711_SDW diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile index 82cf5d180b3a..0e6c4022e7a2 100644 --- a/sound/soc/amd/acp/Makefile +++ b/sound/soc/amd/acp/Makefile @@ -23,6 +23,7 @@ snd-acp-mach-y := acp-mach-common.o snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o snd-acp-sof-mach-y := acp-sof-mach.o snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o +snd-acp-sdw-mach-y := acp-sdw-mach-common.o snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o @@ -41,4 +42,5 @@ obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o obj-$(CONFIG_SND_SOC_ACPI_AMD_MATCH) += snd-soc-acpi-amd-match.o +obj-$(CONFIG_SND_SOC_AMD_SDW_MACH_COMMON) += snd-acp-sdw-mach.o obj-$(CONFIG_SND_SOC_AMD_SOF_SDW_MACH) += snd-acp-sdw-sof-mach.o diff --git a/sound/soc/amd/acp/acp-sdw-mach-common.c b/sound/soc/amd/acp/acp-sdw-mach-common.c new file mode 100644 index 000000000000..d9393cc4a302 --- /dev/null +++ b/sound/soc/amd/acp/acp-sdw-mach-common.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2024 Advanced Micro Devices, Inc. + +/* + * acp-sdw-mach-common - Common machine driver helper functions for + * legacy(No DSP) stack and SOF stack. + */ + +#include +#include +#include "soc_amd_sdw_common.h" + +int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev) +{ + switch (sdw_link_id) { + case AMD_SDW0: + switch (be_id) { + case SOC_SDW_JACK_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO0_TX; + break; + case SOC_SDW_JACK_IN_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO0_RX; + break; + case SOC_SDW_AMP_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO1_TX; + break; + case SOC_SDW_AMP_IN_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO1_RX; + break; + case SOC_SDW_DMIC_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO2_RX; + break; + default: + dev_err(dev, "Invalid be id:%d\n", be_id); + return -EINVAL; + } + break; + case AMD_SDW1: + switch (be_id) { + case SOC_SDW_JACK_OUT_DAI_ID: + case SOC_SDW_AMP_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW1_AUDIO0_TX; + break; + case SOC_SDW_JACK_IN_DAI_ID: + case SOC_SDW_AMP_IN_DAI_ID: + case SOC_SDW_DMIC_DAI_ID: + *cpu_pin_id = ACP63_SW1_AUDIO0_RX; + break; + default: + dev_err(dev, "invalid be_id:%d\n", be_id); + return -EINVAL; + } + break; + default: + dev_err(dev, "Invalid link id:%d\n", sdw_link_id); + return -EINVAL; + } + return 0; +} +EXPORT_SYMBOL_NS_GPL(get_acp63_cpu_pin_id, SND_SOC_AMD_SDW_MACH); + +MODULE_DESCRIPTION("AMD SoundWire Common Machine driver"); +MODULE_AUTHOR("Vijendar Mukunda "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c index 17d3552ba3fc..8fbb501b84e1 100644 --- a/sound/soc/amd/acp/acp-sdw-sof-mach.c +++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c @@ -64,54 +64,6 @@ static const struct snd_soc_ops sdw_ops = { .shutdown = asoc_sdw_shutdown, }; -static int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev) -{ - switch (sdw_link_id) { - case AMD_SDW0: - switch (be_id) { - case SOC_SDW_JACK_OUT_DAI_ID: - *cpu_pin_id = ACP63_SW0_AUDIO0_TX; - break; - case SOC_SDW_JACK_IN_DAI_ID: - *cpu_pin_id = ACP63_SW0_AUDIO0_RX; - break; - case SOC_SDW_AMP_OUT_DAI_ID: - *cpu_pin_id = ACP63_SW0_AUDIO1_TX; - break; - case SOC_SDW_AMP_IN_DAI_ID: - *cpu_pin_id = ACP63_SW0_AUDIO1_RX; - break; - case SOC_SDW_DMIC_DAI_ID: - *cpu_pin_id = ACP63_SW0_AUDIO2_RX; - break; - default: - dev_err(dev, "Invalid be id:%d\n", be_id); - return -EINVAL; - } - break; - case AMD_SDW1: - switch (be_id) { - case SOC_SDW_JACK_OUT_DAI_ID: - case SOC_SDW_AMP_OUT_DAI_ID: - *cpu_pin_id = ACP63_SW1_AUDIO0_TX; - break; - case SOC_SDW_JACK_IN_DAI_ID: - case SOC_SDW_AMP_IN_DAI_ID: - case SOC_SDW_DMIC_DAI_ID: - *cpu_pin_id = ACP63_SW1_AUDIO0_RX; - break; - default: - dev_err(dev, "invalid be_id:%d\n", be_id); - return -EINVAL; - } - break; - default: - dev_err(dev, "Invalid link id:%d\n", sdw_link_id); - return -EINVAL; - } - return 0; -} - static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; static int create_sdw_dailink(struct snd_soc_card *card, @@ -491,3 +443,4 @@ MODULE_DESCRIPTION("ASoC AMD SoundWire Generic Machine driver"); MODULE_AUTHOR("Vijendar Mukunda Date: Mon, 17 Mar 2025 13:44:03 +0100 Subject: [PATCH 210/256] ASoC: amd: acp: add soundwire machine driver for legacy stack JIRA: https://issues.redhat.com/browse/RHEL-80681 Conflicts: use remove_new callback for platform_driver commit 2981d9b0789c44b7375e7d599caf71bd843afc9e Author: Vijendar Mukunda Date: Wed Nov 13 17:22:22 2024 +0530 ASoC: amd: acp: add soundwire machine driver for legacy stack Add SoundWire machine driver for legacy(No DSP) stack for ACP6.3 platform. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20241113115223.3274868-6-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/acp/Kconfig | 22 ++ sound/soc/amd/acp/Makefile | 2 + sound/soc/amd/acp/acp-sdw-legacy-mach.c | 486 ++++++++++++++++++++++++ sound/soc/amd/acp/soc_amd_sdw_common.h | 2 + 4 files changed, 512 insertions(+) create mode 100644 sound/soc/amd/acp/acp-sdw-legacy-mach.c diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index acd047d558bd..03f3fcbba5af 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -144,6 +144,28 @@ config SND_SOC_AMD_SOF_SDW_MACH on AMD platform. If unsure select "N". +config SND_SOC_AMD_LEGACY_SDW_MACH + tristate "AMD Legacy(No DSP) Soundwire Machine Driver Support" + depends on X86 && PCI && ACPI + depends on SOUNDWIRE + select SND_SOC_AMD_SDW_MACH_COMMON + select SND_SOC_SDW_UTILS + select SND_SOC_DMIC + select SND_SOC_RT711_SDW + select SND_SOC_RT711_SDCA_SDW + select SND_SOC_RT712_SDCA_SDW + select SND_SOC_RT712_SDCA_DMIC_SDW + select SND_SOC_RT1316_SDW + select SND_SOC_RT715_SDW + select SND_SOC_RT715_SDCA_SDW + select SND_SOC_RT722_SDCA_SDW + help + This option enables Legacy(No DSP) sound card support for SoundWire + enabled AMD platforms along with ACP PDM controller. + Say Y if you want to enable SoundWire based machine driver support + on AMD platform. + If unsure select "N". + endif # SND_SOC_AMD_ACP_COMMON config SND_AMD_SOUNDWIRE_ACPI diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile index 0e6c4022e7a2..bb2702036338 100644 --- a/sound/soc/amd/acp/Makefile +++ b/sound/soc/amd/acp/Makefile @@ -25,6 +25,7 @@ snd-acp-sof-mach-y := acp-sof-mach.o snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o snd-acp-sdw-mach-y := acp-sdw-mach-common.o snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o +snd-acp-sdw-legacy-mach-y += acp-sdw-legacy-mach.o obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o @@ -44,3 +45,4 @@ obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o obj-$(CONFIG_SND_SOC_ACPI_AMD_MATCH) += snd-soc-acpi-amd-match.o obj-$(CONFIG_SND_SOC_AMD_SDW_MACH_COMMON) += snd-acp-sdw-mach.o obj-$(CONFIG_SND_SOC_AMD_SOF_SDW_MACH) += snd-acp-sdw-sof-mach.o +obj-$(CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH) += snd-acp-sdw-legacy-mach.o diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c new file mode 100644 index 000000000000..9f62006c022e --- /dev/null +++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c @@ -0,0 +1,486 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2024 Advanced Micro Devices, Inc. + +/* + * acp-sdw-legacy-mach - ASoC legacy Machine driver for AMD SoundWire platforms + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "soc_amd_sdw_common.h" +#include "../../codecs/rt711.h" + +static unsigned long soc_sdw_quirk = RT711_JD1; +static int quirk_override = -1; +module_param_named(quirk, quirk_override, int, 0444); +MODULE_PARM_DESC(quirk, "Board-specific quirk override"); + +static void log_quirks(struct device *dev) +{ + if (SOC_JACK_JDSRC(soc_sdw_quirk)) + dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", + SOC_JACK_JDSRC(soc_sdw_quirk)); + if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC) + dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n"); +} + +static int soc_sdw_quirk_cb(const struct dmi_system_id *id) +{ + soc_sdw_quirk = (unsigned long)id->driver_data; + return 1; +} + +static const struct dmi_system_id soc_sdw_quirk_table[] = { + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AMD"), + DMI_MATCH(DMI_PRODUCT_NAME, "Birman-PHX"), + }, + .driver_data = (void *)RT711_JD2, + }, + {} +}; + +static const struct snd_soc_ops sdw_ops = { + .startup = asoc_sdw_startup, + .prepare = asoc_sdw_prepare, + .trigger = asoc_sdw_trigger, + .hw_params = asoc_sdw_hw_params, + .hw_free = asoc_sdw_hw_free, + .shutdown = asoc_sdw_shutdown, +}; + +static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; + +static int create_sdw_dailink(struct snd_soc_card *card, + struct asoc_sdw_dailink *soc_dai, + struct snd_soc_dai_link **dai_links, + int *be_id, struct snd_soc_codec_conf **codec_conf, + struct snd_soc_dai_link_component *sdw_platform_component) +{ + struct device *dev = card->dev; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; + struct asoc_sdw_endpoint *soc_end; + int cpu_pin_id; + int stream; + int ret; + + list_for_each_entry(soc_end, &soc_dai->endpoints, list) { + if (soc_end->name_prefix) { + (*codec_conf)->dlc.name = soc_end->codec_name; + (*codec_conf)->name_prefix = soc_end->name_prefix; + (*codec_conf)++; + } + + if (soc_end->include_sidecar) { + ret = soc_end->codec_info->add_sidecar(card, dai_links, codec_conf); + if (ret) + return ret; + } + } + + for_each_pcm_streams(stream) { + static const char * const sdw_stream_name[] = { + "SDW%d-PIN%d-PLAYBACK", + "SDW%d-PIN%d-CAPTURE", + "SDW%d-PIN%d-PLAYBACK-%s", + "SDW%d-PIN%d-CAPTURE-%s", + }; + struct snd_soc_dai_link_ch_map *codec_maps; + struct snd_soc_dai_link_component *codecs; + struct snd_soc_dai_link_component *cpus; + int num_cpus = hweight32(soc_dai->link_mask[stream]); + int num_codecs = soc_dai->num_devs[stream]; + int playback, capture; + int j = 0; + char *name; + + if (!soc_dai->num_devs[stream]) + continue; + + soc_end = list_first_entry(&soc_dai->endpoints, + struct asoc_sdw_endpoint, list); + + *be_id = soc_end->dai_info->dailink[stream]; + if (*be_id < 0) { + dev_err(dev, "Invalid dailink id %d\n", *be_id); + return -EINVAL; + } + + switch (amd_ctx->acp_rev) { + case ACP63_PCI_REV: + ret = get_acp63_cpu_pin_id(ffs(soc_end->link_mask - 1), + *be_id, &cpu_pin_id, dev); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + /* create stream name according to first link id */ + if (ctx->append_dai_type) { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream + 2], + ffs(soc_end->link_mask) - 1, + cpu_pin_id, + type_strings[soc_end->dai_info->dai_type]); + } else { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream], + ffs(soc_end->link_mask) - 1, + cpu_pin_id); + } + if (!name) + return -ENOMEM; + + cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL); + if (!cpus) + return -ENOMEM; + + codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL); + if (!codecs) + return -ENOMEM; + + codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL); + if (!codec_maps) + return -ENOMEM; + + list_for_each_entry(soc_end, &soc_dai->endpoints, list) { + if (!soc_end->dai_info->direction[stream]) + continue; + + int link_num = ffs(soc_end->link_mask) - 1; + + cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SDW%d Pin%d", + link_num, cpu_pin_id); + dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name); + if (!cpus->dai_name) + return -ENOMEM; + + codec_maps[j].cpu = 0; + codec_maps[j].codec = j; + + codecs[j].name = soc_end->codec_name; + codecs[j].dai_name = soc_end->dai_info->dai_name; + j++; + } + + WARN_ON(j != num_codecs); + + playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); + capture = (stream == SNDRV_PCM_STREAM_CAPTURE); + + asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture, + cpus, num_cpus, sdw_platform_component, + 1, codecs, num_codecs, + 0, asoc_sdw_rtd_init, &sdw_ops); + /* + * SoundWire DAILINKs use 'stream' functions and Bank Switch operations + * based on wait_for_completion(), tag them as 'nonatomic'. + */ + (*dai_links)->nonatomic = true; + (*dai_links)->ch_maps = codec_maps; + + list_for_each_entry(soc_end, &soc_dai->endpoints, list) { + if (soc_end->dai_info->init) + soc_end->dai_info->init(card, *dai_links, + soc_end->codec_info, + playback); + } + + (*dai_links)++; + } + + return 0; +} + +static int create_sdw_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, + struct asoc_sdw_dailink *soc_dais, + struct snd_soc_codec_conf **codec_conf) +{ + struct device *dev = card->dev; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; + struct snd_soc_dai_link_component *sdw_platform_component; + int ret; + + sdw_platform_component = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), + GFP_KERNEL); + if (!sdw_platform_component) + return -ENOMEM; + + switch (amd_ctx->acp_rev) { + case ACP63_PCI_REV: + sdw_platform_component->name = "amd_ps_sdw_dma.0"; + break; + default: + return -EINVAL; + } + + /* generate DAI links by each sdw link */ + while (soc_dais->initialised) { + int current_be_id; + + ret = create_sdw_dailink(card, soc_dais, dai_links, + ¤t_be_id, codec_conf, sdw_platform_component); + if (ret) + return ret; + + /* Update the be_id to match the highest ID used for SDW link */ + if (*be_id < current_be_id) + *be_id = current_be_id; + + soc_dais++; + } + + return 0; +} + +static int create_dmic_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, int no_pcm) +{ + struct device *dev = card->dev; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; + struct snd_soc_dai_link_component *pdm_cpu; + struct snd_soc_dai_link_component *pdm_platform; + int ret; + + pdm_cpu = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); + if (!pdm_cpu) + return -ENOMEM; + + pdm_platform = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); + if (!pdm_platform) + return -ENOMEM; + + switch (amd_ctx->acp_rev) { + case ACP63_PCI_REV: + pdm_cpu->name = "acp_ps_pdm_dma.0"; + pdm_platform->name = "acp_ps_pdm_dma.0"; + break; + default: + return -EINVAL; + } + + *be_id = ACP_DMIC_BE_ID; + ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec", + 0, 1, // DMIC only supports capture + pdm_cpu->name, pdm_platform->name, 1, + "dmic-codec.0", "dmic-hifi", no_pcm, + asoc_sdw_dmic_init, NULL); + if (ret) + return ret; + + (*dai_links)++; + + return 0; +} + +static int soc_card_dai_links_create(struct snd_soc_card *card) +{ + struct device *dev = card->dev; + struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); + int sdw_be_num = 0, dmic_num = 0; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; + struct asoc_sdw_endpoint *soc_ends __free(kfree) = NULL; + struct asoc_sdw_dailink *soc_dais __free(kfree) = NULL; + struct snd_soc_codec_conf *codec_conf; + struct snd_soc_dai_link *dai_links; + int num_devs = 0; + int num_ends = 0; + int num_links; + int be_id = 0; + int ret; + + ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends); + if (ret < 0) { + dev_err(dev, "failed to count devices/endpoints: %d\n", ret); + return ret; + } + + /* One per DAI link, worst case is a DAI link for every endpoint */ + soc_dais = kcalloc(num_ends, sizeof(*soc_dais), GFP_KERNEL); + if (!soc_dais) + return -ENOMEM; + + /* One per endpoint, ie. each DAI on each codec/amp */ + soc_ends = kcalloc(num_ends, sizeof(*soc_ends), GFP_KERNEL); + if (!soc_ends) + return -ENOMEM; + + ret = asoc_sdw_parse_sdw_endpoints(card, soc_dais, soc_ends, &num_devs); + if (ret < 0) + return ret; + + sdw_be_num = ret; + + /* enable dmic */ + if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC || mach_params->dmic_num) + dmic_num = 1; + + dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num); + + codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); + if (!codec_conf) + return -ENOMEM; + + /* allocate BE dailinks */ + num_links = sdw_be_num + dmic_num; + dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); + if (!dai_links) + return -ENOMEM; + + card->codec_conf = codec_conf; + card->num_configs = num_devs; + card->dai_link = dai_links; + card->num_links = num_links; + + /* SDW */ + if (sdw_be_num) { + ret = create_sdw_dailinks(card, &dai_links, &be_id, + soc_dais, &codec_conf); + if (ret) + return ret; + } + + /* dmic */ + if (dmic_num > 0) { + if (ctx->ignore_internal_dmic) { + dev_warn(dev, "Ignoring ACP DMIC\n"); + } else { + ret = create_dmic_dailinks(card, &dai_links, &be_id, 0); + if (ret) + return ret; + } + } + + WARN_ON(codec_conf != card->codec_conf + card->num_configs); + WARN_ON(dai_links != card->dai_link + card->num_links); + + return ret; +} + +static int mc_probe(struct platform_device *pdev) +{ + struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); + struct snd_soc_card *card; + struct amd_mc_ctx *amd_ctx; + struct asoc_sdw_mc_private *ctx; + int amp_num = 0, i; + int ret; + + amd_ctx = devm_kzalloc(&pdev->dev, sizeof(*amd_ctx), GFP_KERNEL); + if (!amd_ctx) + return -ENOMEM; + + amd_ctx->acp_rev = mach->mach_params.subsystem_rev; + amd_ctx->max_sdw_links = ACP63_SDW_MAX_LINKS; + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count(); + ctx->private = amd_ctx; + card = &ctx->card; + card->dev = &pdev->dev; + card->name = "amd-soundwire"; + card->owner = THIS_MODULE; + card->late_probe = asoc_sdw_card_late_probe; + + snd_soc_card_set_drvdata(card, ctx); + + dmi_check_system(soc_sdw_quirk_table); + + if (quirk_override != -1) { + dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n", + soc_sdw_quirk, quirk_override); + soc_sdw_quirk = quirk_override; + } + + log_quirks(card->dev); + + ctx->mc_quirk = soc_sdw_quirk; + dev_dbg(card->dev, "legacy quirk 0x%lx\n", ctx->mc_quirk); + /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ + for (i = 0; i < ctx->codec_info_list_count; i++) + codec_info_list[i].amp_num = 0; + + ret = soc_card_dai_links_create(card); + if (ret < 0) + return ret; + + /* + * the default amp_num is zero for each codec and + * amp_num will only be increased for active amp + * codecs on used platform + */ + for (i = 0; i < ctx->codec_info_list_count; i++) + amp_num += codec_info_list[i].amp_num; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + " cfg-amp:%d", amp_num); + if (!card->components) + return -ENOMEM; + if (mach->mach_params.dmic_num) { + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:dmic cfg-mics:%d", + card->components, + mach->mach_params.dmic_num); + if (!card->components) + return -ENOMEM; + } + + /* Register the card */ + ret = devm_snd_soc_register_card(card->dev, card); + if (ret) { + dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret); + asoc_sdw_mc_dailink_exit_loop(card); + return ret; + } + + platform_set_drvdata(pdev, card); + + return ret; +} + +static void mc_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + asoc_sdw_mc_dailink_exit_loop(card); +} + +static const struct platform_device_id mc_id_table[] = { + { "amd_sdw", }, + {} +}; +MODULE_DEVICE_TABLE(platform, mc_id_table); + +static struct platform_driver soc_sdw_driver = { + .driver = { + .name = "amd_sdw", + .pm = &snd_soc_pm_ops, + }, + .probe = mc_probe, + .remove_new = mc_remove, + .id_table = mc_id_table, +}; + +module_platform_driver(soc_sdw_driver); + +MODULE_DESCRIPTION("ASoC AMD SoundWire Legacy Generic Machine driver"); +MODULE_AUTHOR("Vijendar Mukunda "); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_SDW_UTILS); +MODULE_IMPORT_NS(SND_SOC_AMD_SDW_MACH); diff --git a/sound/soc/amd/acp/soc_amd_sdw_common.h b/sound/soc/amd/acp/soc_amd_sdw_common.h index eba92cd004d4..b7bae107c13e 100644 --- a/sound/soc/amd/acp/soc_amd_sdw_common.h +++ b/sound/soc/amd/acp/soc_amd_sdw_common.h @@ -36,6 +36,8 @@ #define ACP63_SW1_AUDIO0_TX 0 #define ACP63_SW1_AUDIO0_RX 1 +#define ACP_DMIC_BE_ID 4 + struct amd_mc_ctx { unsigned int acp_rev; unsigned int max_sdw_links; From cf4f9da4b1b5ea4bf035f759add0a1b852025757 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:03 +0100 Subject: [PATCH 211/256] ASoC: amd: ps: fix the pcm device numbering for acp 6.3 platform JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 76b5a3b2afdce1460dcd06221f7aa8eb2b807b1f Author: Vijendar Mukunda Date: Wed Nov 13 17:22:23 2024 +0530 ASoC: amd: ps: fix the pcm device numbering for acp 6.3 platform Fixed PCM device numbering is required for defining common alsa ucm changes for generic soundwire machine driver for legacy(No DSP) stack. Ex: For Headphone playback use case, use PCM device number as 0. For Headset mic Capture use case, PCM device number as 1. Set the 'use_dai_pcm_id' flag true in soundwire dma driver for acp 6.3 platform. This will fix the pcm device numbering based on dai_link->id. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20241113115223.3274868-7-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/ps/ps-sdw-dma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 2f630753278d..a81006be3e94 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -445,6 +445,8 @@ static const struct snd_soc_component_driver acp63_sdw_component = { .trigger = acp63_sdw_dma_trigger, .pointer = acp63_sdw_dma_pointer, .pcm_construct = acp63_sdw_dma_new, + .use_dai_pcm_id = true, + }; static int acp63_sdw_platform_probe(struct platform_device *pdev) From c31ee65d48295e82ea72a612bc02412e012388c9 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:03 +0100 Subject: [PATCH 212/256] ASoC: sdca: test adev before calling acpi_dev_for_each_child MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit de35b06bf15cb56c96c7a69474e305852cc170e3 Author: Bard Liao Date: Wed Nov 13 14:41:33 2024 +0800 ASoC: sdca: test adev before calling acpi_dev_for_each_child sdca_lookup_functions may be called by a Peripheral that is not listed in the ACPI table. Testing adev is required to avoid kernel NULL pointer dereference. Fixes: 3a513da1ae33 ("ASoC: SDCA: add initial module") Signed-off-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Liam Girdwood Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20241113064133.162501-1-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sdca/sdca_functions.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index a6ad57430dd4..e6e5629c7054 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -165,6 +165,10 @@ void sdca_lookup_functions(struct sdw_slave *slave) struct device *dev = &slave->dev; struct acpi_device *adev = to_acpi_device_node(dev->fwnode); + if (!adev) { + dev_info(dev, "No matching ACPI device found, ignoring peripheral\n"); + return; + } acpi_dev_for_each_child(adev, find_sdca_function, &slave->sdca_data); } EXPORT_SYMBOL_NS(sdca_lookup_functions, SND_SOC_SDCA); From d9d3543e87b0723aefba07a2baf9994d0cc32479 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:44:03 +0100 Subject: [PATCH 213/256] ASoC: SOF: ipc4-topology: remove redundant assignment to variable ret JIRA: https://issues.redhat.com/browse/RHEL-80681 commit fb5e67c9d03b4a65fd43acc18cbafffff15bd8f9 Author: Colin Ian King Date: Wed Nov 13 13:08:07 2024 +0000 ASoC: SOF: ipc4-topology: remove redundant assignment to variable ret The variable ret is being assigned a zero value however the value is never read because ret is being re-assigned later after the end of the switch statement. The assignment is redundant and can be removed. Signed-off-by: Colin Ian King Link: https://patch.msgid.link/20241113130807.1386754-1-colin.i.king@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sof/ipc4-topology.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 1fcf4692a21f..b55eb977e443 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -755,7 +755,6 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) * It is fine to call kfree(ipc4_copier->copier_config) since * ipc4_copier->copier_config is null. */ - ret = 0; break; } From 139966ea4c49df55c5431aa82af5026bf8d847de Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:47:57 +0100 Subject: [PATCH 214/256] soundwire: Update the includes on the sdw.h header JIRA: https://issues.redhat.com/browse/RHEL-80681 Conflicts: Fix sdca.h include (merge) commit e311b04db66aaed1819bdd479d42c4f338f105b9 Author: Charles Keepax Date: Tue Nov 12 12:56:45 2024 +0000 soundwire: Update the includes on the sdw.h header There are quite a few things used in the sdw.h header that it relies on the consumer to include. If something is used directly in the header it should be included by the header. Update the includes to cover the missing items, or add forward declarations for things that are only used as pointers. Whilst making the change also alphabetise the list of includes. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20241112125646.590240-1-ckeepax@opensource.cirrus.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- include/linux/soundwire/sdw.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 25db2b191e8f..7406eab6bdf3 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -4,14 +4,22 @@ #ifndef __SOUNDWIRE_H #define __SOUNDWIRE_H +#include #include -#include +#include +#include #include #include +#include #include -#include #include +#include +#include + +struct dentry; +struct fwnode_handle; + struct sdw_bus; struct sdw_slave; From 16e1350919a6b74ee6daaff091e4ca8554df0250 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:01 +0100 Subject: [PATCH 215/256] soundwire: Minor formatting fixups in sdw.h header JIRA: https://issues.redhat.com/browse/RHEL-80681 commit dd690b31de0ed46adc5856698880560b900386ba Author: Charles Keepax Date: Tue Nov 12 12:56:46 2024 +0000 soundwire: Minor formatting fixups in sdw.h header Fixup some minor formatting and whitespace in the sdw.h header file. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20241112125646.590240-2-ckeepax@opensource.cirrus.com Signed-off-by: Vinod Koul Signed-off-by: Jaroslav Kysela --- include/linux/soundwire/sdw.h | 40 +++++++++++++++-------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 7406eab6bdf3..87e89158ee30 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -618,7 +618,6 @@ struct sdw_slave_ops { int (*clk_stop)(struct sdw_slave *slave, enum sdw_clk_stop_mode mode, enum sdw_clk_stop_type type); - }; /** @@ -694,8 +693,7 @@ struct sdw_master_device { container_of(d, struct sdw_master_device, dev) struct sdw_driver { - int (*probe)(struct sdw_slave *sdw, - const struct sdw_device_id *id); + int (*probe)(struct sdw_slave *sdw, const struct sdw_device_id *id); int (*remove)(struct sdw_slave *sdw); void (*shutdown)(struct sdw_slave *sdw); @@ -714,7 +712,7 @@ struct sdw_driver { SDW_SLAVE_ENTRY_EXT((_mfg_id), (_part_id), 0, 0, (_drv_data)) int sdw_handle_slave_status(struct sdw_bus *bus, - enum sdw_slave_status status[]); + enum sdw_slave_status status[]); /* * SDW master structures and APIs @@ -796,15 +794,14 @@ struct sdw_enable_ch { */ struct sdw_master_port_ops { int (*dpn_set_port_params)(struct sdw_bus *bus, - struct sdw_port_params *port_params, - unsigned int bank); + struct sdw_port_params *port_params, + unsigned int bank); int (*dpn_set_port_transport_params)(struct sdw_bus *bus, - struct sdw_transport_params *transport_params, - enum sdw_reg_bank bank); - int (*dpn_port_prep)(struct sdw_bus *bus, - struct sdw_prepare_ch *prepare_ch); + struct sdw_transport_params *transport_params, + enum sdw_reg_bank bank); + int (*dpn_port_prep)(struct sdw_bus *bus, struct sdw_prepare_ch *prepare_ch); int (*dpn_port_enable_ch)(struct sdw_bus *bus, - struct sdw_enable_ch *enable_ch, unsigned int bank); + struct sdw_enable_ch *enable_ch, unsigned int bank); }; struct sdw_msg; @@ -839,14 +836,11 @@ struct sdw_defer { */ struct sdw_master_ops { int (*read_prop)(struct sdw_bus *bus); - u64 (*override_adr) - (struct sdw_bus *bus, u64 addr); - enum sdw_command_response (*xfer_msg) - (struct sdw_bus *bus, struct sdw_msg *msg); - enum sdw_command_response (*xfer_msg_defer) - (struct sdw_bus *bus); + u64 (*override_adr)(struct sdw_bus *bus, u64 addr); + enum sdw_command_response (*xfer_msg)(struct sdw_bus *bus, struct sdw_msg *msg); + enum sdw_command_response (*xfer_msg_defer)(struct sdw_bus *bus); int (*set_bus_conf)(struct sdw_bus *bus, - struct sdw_bus_params *params); + struct sdw_bus_params *params); int (*pre_bank_switch)(struct sdw_bus *bus); int (*post_bank_switch)(struct sdw_bus *bus); u32 (*read_ping_status)(struct sdw_bus *bus); @@ -1023,12 +1017,12 @@ void sdw_release_stream(struct sdw_stream_runtime *stream); int sdw_compute_params(struct sdw_bus *bus); int sdw_stream_add_master(struct sdw_bus *bus, - struct sdw_stream_config *stream_config, - const struct sdw_port_config *port_config, - unsigned int num_ports, - struct sdw_stream_runtime *stream); + struct sdw_stream_config *stream_config, + const struct sdw_port_config *port_config, + unsigned int num_ports, + struct sdw_stream_runtime *stream); int sdw_stream_remove_master(struct sdw_bus *bus, - struct sdw_stream_runtime *stream); + struct sdw_stream_runtime *stream); int sdw_startup_stream(void *sdw_substream); int sdw_prepare_stream(struct sdw_stream_runtime *stream); int sdw_enable_stream(struct sdw_stream_runtime *stream); From 5e33749c89523fc39d640259b3291df940b296e4 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:01 +0100 Subject: [PATCH 216/256] ASoc: simple-mux: add idle-state support JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 2b974284aa073d6e2936f9032e8ad7b99480b5b8 Author: Hendrik v. Raven Date: Thu Nov 14 12:01:25 2024 +0100 ASoc: simple-mux: add idle-state support So far the mux changes it state immediately, even when not in use. Allow overriding this behaviour by specifying an optional idle-state. This state is used whenever the mux is powered down, only switching to the selected state on power up. If unspecified it defaults to as-is, maintaining the previous behaviour. Signed-off-by: Hendrik v. Raven Link: https://patch.msgid.link/20241114-simple-mux-idle-state-v2-1-a30cb37d2be2@merzmedtech.de Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/simple-mux.c | 39 ++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/simple-mux.c b/sound/soc/codecs/simple-mux.c index 240af0563283..390696440155 100644 --- a/sound/soc/codecs/simple-mux.c +++ b/sound/soc/codecs/simple-mux.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -16,6 +17,7 @@ struct simple_mux { struct gpio_desc *gpiod_mux; unsigned int mux; const char *mux_texts[MUX_TEXT_SIZE]; + unsigned int idle_state; struct soc_enum mux_enum; struct snd_kcontrol_new mux_mux; struct snd_soc_dapm_widget mux_widgets[MUX_WIDGET_SIZE]; @@ -57,6 +59,9 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol, priv->mux = ucontrol->value.enumerated.item[0]; + if (priv->idle_state != MUX_IDLE_AS_IS && dapm->bias_level < SND_SOC_BIAS_PREPARE) + return 0; + gpiod_set_value_cansleep(priv->gpiod_mux, priv->mux); return snd_soc_dapm_mux_update_power(dapm, kcontrol, @@ -75,10 +80,33 @@ static unsigned int simple_mux_read(struct snd_soc_component *component, static const struct snd_kcontrol_new simple_mux_mux = SOC_DAPM_ENUM_EXT("Muxer", simple_mux_enum, simple_mux_control_get, simple_mux_control_put); +static int simple_mux_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); + struct simple_mux *priv = snd_soc_component_get_drvdata(c); + + if (priv->idle_state != MUX_IDLE_AS_IS) { + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + gpiod_set_value_cansleep(priv->gpiod_mux, priv->mux); + break; + case SND_SOC_DAPM_POST_PMD: + gpiod_set_value_cansleep(priv->gpiod_mux, priv->idle_state); + break; + default: + break; + } + } + + return 0; +} + static const struct snd_soc_dapm_widget simple_mux_dapm_widgets[MUX_WIDGET_SIZE] = { SND_SOC_DAPM_INPUT("IN1"), SND_SOC_DAPM_INPUT("IN2"), - SND_SOC_DAPM_MUX("MUX", SND_SOC_NOPM, 0, 0, &simple_mux_mux), // see simple_mux_probe() + SND_SOC_DAPM_MUX_E("MUX", SND_SOC_NOPM, 0, 0, &simple_mux_mux, // see simple_mux_probe() + simple_mux_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_OUTPUT("OUT"), }; @@ -93,6 +121,7 @@ static int simple_mux_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct simple_mux *priv; + int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -121,6 +150,14 @@ static int simple_mux_probe(struct platform_device *pdev) /* Overwrite text ("Input 1", "Input 2") if property exists */ of_property_read_string_array(np, "state-labels", priv->mux_texts, MUX_TEXT_SIZE); + ret = of_property_read_u32(np, "idle-state", &priv->idle_state); + if (ret < 0) { + priv->idle_state = MUX_IDLE_AS_IS; + } else if (priv->idle_state != MUX_IDLE_AS_IS && priv->idle_state >= 2) { + dev_err(dev, "invalid idle-state %u\n", priv->idle_state); + return -EINVAL; + } + /* switch to use priv data instead of default */ priv->mux_enum.texts = priv->mux_texts; priv->mux_mux.private_value = (unsigned long)&priv->mux_enum; From 8f3b544ab3bed12fadf5e0d8cb33b8bbf196db9f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:01 +0100 Subject: [PATCH 217/256] ASoC: dt-bindings: simple-mux: add idle-state property JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 3b7e11a0116c30848d44429650ad80f9cc3bd963 Author: Hendrik v. Raven Date: Thu Nov 14 12:01:26 2024 +0100 ASoC: dt-bindings: simple-mux: add idle-state property simple-mux immediately activates the new output, even when it is powered down. This can be undesirable in some cases, for example when a mechanical relais is used. Adds "idle-state" property from the mux controller to select the output state to be used when the mux is powered down. Signed-off-by: Hendrik v. Raven Link: https://patch.msgid.link/20241114-simple-mux-idle-state-v2-2-a30cb37d2be2@merzmedtech.de Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- .../devicetree/bindings/sound/simple-audio-mux.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml b/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml index 15d9d5a59498..09edce8baf07 100644 --- a/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml +++ b/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml @@ -29,6 +29,10 @@ properties: $ref: /schemas/types.yaml#/definitions/string-array maxItems: 2 + idle-state: + description: If present specifies the state when the mux is powered down + $ref: /schemas/mux/mux-controller.yaml#/properties/idle-state + sound-name-prefix: true required: @@ -43,4 +47,5 @@ examples: compatible = "simple-audio-mux"; mux-gpios = <&gpio 3 0>; state-labels = "Label_A", "Label_B"; + idle-state = <0>; }; From abda0b3569a22d53bd8722f8eb1462b093c5180e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:01 +0100 Subject: [PATCH 218/256] ASoC: sma1307: fix uninitialized variable refence JIRA: https://issues.redhat.com/browse/RHEL-80681 commit c48a4497356f701f94f1951626637ae240af909e Author: Arnd Bergmann Date: Wed Nov 13 18:57:13 2024 +0100 ASoC: sma1307: fix uninitialized variable refence When firmware loading is disabled, gcc warns that the local 'fw' variable fails to get initialized: sound/soc/codecs/sma1307.c: In function 'sma1307_setting_loaded.isra': sound/soc/codecs/sma1307.c:1717:12: error: 'fw' is used uninitialized [-Werror=uninitialized] 1717 | if (!fw) { | ^ sound/soc/codecs/sma1307.c:1712:32: note: 'fw' was declared here 1712 | const struct firmware *fw; Check the return code from request_firmware() to ensure that the firmware is correctly set, and drop the incorrect release_firmware() on that uninitialized data. Fixes: 576c57e6b4c1 ("ASoC: sma1307: Add driver for Iron Device SMA1307") Signed-off-by: Arnd Bergmann Link: https://patch.msgid.link/20241113175734.2443315-1-arnd@kernel.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/sma1307.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c index 81638768ac12..f2cea6186d98 100644 --- a/sound/soc/codecs/sma1307.c +++ b/sound/soc/codecs/sma1307.c @@ -1711,13 +1711,13 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil { const struct firmware *fw; int *data, size, offset, num_mode; + int ret; - request_firmware(&fw, file, sma1307->dev); + ret = request_firmware(&fw, file, sma1307->dev); - if (!fw) { - dev_err(sma1307->dev, "%s: failed to read \"%s\"\n", - __func__, setting_file); - release_firmware(fw); + if (ret) { + dev_err(sma1307->dev, "%s: failed to read \"%s\": %pe\n", + __func__, setting_file, ERR_PTR(ret)); sma1307->set.status = false; return; } else if ((fw->size) < SMA1307_SETTING_HEADER_SIZE) { From f5563c41328fc7383d1ac042089eb3c33a311348 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:02 +0100 Subject: [PATCH 219/256] ASoC: stm32: dfsdm: change rate upper limits JIRA: https://issues.redhat.com/browse/RHEL-80681 commit ba888450828befb0607219f34c03aa8645625447 Author: Olivier Moysan Date: Thu Nov 14 11:28:51 2024 +0100 ASoC: stm32: dfsdm: change rate upper limits Increase rate upper limit to 192kHz to reflect the rate range actually supported by the STM32 DFSDM peripheral. Signed-off-by: Olivier Moysan Link: https://patch.msgid.link/20241114102851.2497942-1-olivier.moysan@foss.st.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/stm/stm32_adfsdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index cc67dc5c5daf..609ad6c036f3 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -142,7 +142,7 @@ static const struct snd_soc_dai_driver stm32_adfsdm_dai = { SNDRV_PCM_FMTBIT_S32_LE, .rates = SNDRV_PCM_RATE_CONTINUOUS, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &stm32_adfsdm_dai_ops, }; From da49a639dd8c21e2786192b8b6f75cf20686f032 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:02 +0100 Subject: [PATCH 220/256] ASoC: Intel: soc-acpi-intel-lnl-match: add rt712_vb + rt1320 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JIRA: https://issues.redhat.com/browse/RHEL-80681 commit a59360466a712d416f8cddfa4e52e118c53aa3a3 Author: Bard Liao Date: Wed Nov 13 14:44:17 2024 +0800 ASoC: Intel: soc-acpi-intel-lnl-match: add rt712_vb + rt1320 support Realtek Gen6 AIOC supports rt712_vb on SoundWire link 2 and rt1320 on SoundWire link 1. Signed-off-by: Bard Liao Reviewed-by: Ranjani Sridharan Reviewed-by: Liam Girdwood Reviewed-by: Péter Ujfalusi Link: https://patch.msgid.link/20241113064418.162592-1-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- .../intel/common/soc-acpi-intel-lnl-match.c | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c index 094ed4b27cb0..98a9c36d7a4c 100644 --- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c @@ -8,6 +8,7 @@ #include #include +#include "soc-acpi-intel-sdca-quirks.h" #include "soc-acpi-intel-sdw-mockup-match.h" struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_machines[] = { @@ -90,6 +91,30 @@ static const struct snd_soc_acpi_endpoint rt722_endpoints[] = { }, }; +static const struct snd_soc_acpi_endpoint jack_amp_g1_dmic_endpoints_endpoints[] = { + /* Jack Endpoint */ + { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + /* Amp Endpoint, work as spk_l_endpoint */ + { + .num = 1, + .aggregated = 1, + .group_position = 0, + .group_id = 1, + }, + /* DMIC Endpoint */ + { + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { { /* Jack Playback Endpoint */ .num = 0, @@ -198,6 +223,15 @@ static const struct snd_soc_acpi_adr_device rt1712_3_single_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt712_vb_2_group1_adr[] = { + { + .adr = 0x000230025D071201ull, + .num_endpoints = ARRAY_SIZE(jack_amp_g1_dmic_endpoints_endpoints), + .endpoints = jack_amp_g1_dmic_endpoints_endpoints, + .name_prefix = "rt712" + } +}; + static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = { { .adr = 0x000030025d072201ull, @@ -252,6 +286,15 @@ static const struct snd_soc_acpi_adr_device rt1318_2_group1_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1320_1_group1_adr[] = { + { + .adr = 0x000130025D132001ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1320-1" + } +}; + static const struct snd_soc_acpi_adr_device rt713_0_adr[] = { { .adr = 0x000031025D071301ull, @@ -410,6 +453,21 @@ static const struct snd_soc_acpi_link_adr lnl_sdw_rt713_l0_rt1318_l1[] = { {} }; +static const struct snd_soc_acpi_link_adr lnl_sdw_rt712_vb_l2_rt1320_l1[] = { + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt712_vb_2_group1_adr), + .adr_d = rt712_vb_2_group1_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1320_1_group1_adr), + .adr_d = rt1320_1_group1_adr, + }, + {} +}; + +/* this table is used when there is no I2S codec present */ /* this table is used when there is no I2S codec present */ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = { /* mockup tests need to be first */ @@ -485,6 +543,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-lnl-rt713-l0-rt1318-l1.tplg" }, + { + .link_mask = BIT(1) | BIT(2), + .links = lnl_sdw_rt712_vb_l2_rt1320_l1, + .drv_name = "sof_sdw", + .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb, + .sof_tplg_filename = "sof-lnl-rt712-l2-rt1320-l1.tplg" + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_lnl_sdw_machines); From d3bbddcd74ef58634c8b576dd1683908361c5d14 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:02 +0100 Subject: [PATCH 221/256] ALSA: ump: Fix the wrong format specifier JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 9b4662d0df9f4433f1828904ba5e8733c1ad5158 Author: zhang jiao Date: Thu Nov 14 15:58:22 2024 +0800 ALSA: ump: Fix the wrong format specifier The format specifier of "unsigned int" in snprintf() should be "%u", not "%d". Signed-off-by: zhang jiao Link: https://patch.msgid.link/20241114075822.41614-1-zhangjiao2@cmss.chinamobile.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/core/ump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/ump.c b/sound/core/ump.c index ea6f0fe6d841..9198bff4768c 100644 --- a/sound/core/ump.c +++ b/sound/core/ump.c @@ -391,7 +391,7 @@ int snd_ump_block_new(struct snd_ump_endpoint *ump, unsigned int blk, fb->info.first_group = first_group; fb->info.num_groups = num_groups; /* fill the default name, may be overwritten to a better name */ - snprintf(fb->info.name, sizeof(fb->info.name), "Group %d-%d", + snprintf(fb->info.name, sizeof(fb->info.name), "Group %u-%u", first_group + 1, first_group + num_groups); /* put the entry in the ordered list */ From 5e4c66188e1e27d4b2d97527d25ddc5bed9db65f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:02 +0100 Subject: [PATCH 222/256] ALSA: hda: Poll jack events for LS7A HD-Audio JIRA: https://issues.redhat.com/browse/RHEL-80681 commit e3f8064d8b29036f037fd1ff6000e5d959d84843 Author: Huacai Chen Date: Fri Nov 15 23:06:53 2024 +0800 ALSA: hda: Poll jack events for LS7A HD-Audio LS7A HD-Audio disable interrupts and use polling mode due to hardware drawbacks. As a result, unsolicited jack events are also unusable. If we want to support headphone hotplug, we need to also poll jack events. Here we use 1500ms as the poll interval if no module parameter specify it. Cc: stable@vger.kernel.org Signed-off-by: Huacai Chen Link: https://patch.msgid.link/20241115150653.2819100-1-chenhuacai@loongson.cn Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_intel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index aa032bc94db3..df9779000812 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1858,6 +1858,8 @@ static int azx_first_init(struct azx *chip) bus->polling_mode = 1; bus->not_use_interrupts = 1; bus->access_sdnctl_in_dword = 1; + if (!chip->jackpoll_interval) + chip->jackpoll_interval = msecs_to_jiffies(1500); } err = pcim_iomap_regions(pci, 1 << 0, "ICH HD audio"); From ec88532de1f9418e7f8b100a9fa06a85af2ef03f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:02 +0100 Subject: [PATCH 223/256] ASoC: amd: Fix build dependencies for `SND_SOC_AMD_PS` JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0109ee00788e0ad7b888a799c26b5a93b343876b Author: Mario Limonciello Date: Sun Nov 17 20:55:27 2024 -0600 ASoC: amd: Fix build dependencies for `SND_SOC_AMD_PS` The pci-ps module now must have `SND_SOC_ACPI_AMD_MATCH` selected to reference the `snd_soc_acpi_amd_acp63_sdw_machines` symbol. Fixes: 56d540befd59 ("ASoC: amd: ps: add soundwire machines for acp6.3 platform") Cc: Vijendar.Mukunda@amd.com Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202411180658.mIeWje2V-lkp@intel.com/ Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20241118025527.3318493-1-superm1@kernel.org Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/amd/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 6dec44f516c1..c7590d4989bb 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -163,6 +163,7 @@ config SND_SOC_AMD_SOUNDWIRE config SND_SOC_AMD_PS tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support" select SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE + select SND_SOC_ACPI_AMD_MATCH depends on X86 && PCI && ACPI help This option enables Audio Coprocessor i.e ACP v6.3 support on From c1efe85a7b5eb14e59af12f25d54323017f278a1 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:03 +0100 Subject: [PATCH 224/256] ALSA: ac97: bus: Fix the mistake in the comment JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 0e84b414ca3778fd9308df52241a3617d82c20d2 Author: Pei Xiao Date: Wed Nov 20 14:30:19 2024 +0800 ALSA: ac97: bus: Fix the mistake in the comment Fix mistake in the comment. sound/ac97/bus.c:192: warning: Function parameter or member 'drv' not described in 'snd_ac97_codec_driver_register' sound/ac97/bus.c:192: warning: Excess function parameter 'dev' description in 'snd_ac97_codec_driver_register' sound/ac97/bus.c:205: warning: Function parameter or member 'drv' not described in 'snd_ac97_codec_driver_unregister' sound/ac97/bus.c:205: warning: Excess function parameter 'dev' description in 'snd_ac97_codec_driver_unregister' sound/ac97/bus.c:351: warning: Function parameter or member 'codecs_pdata' not described in 'snd_ac97_controller_register' Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202411180804.FUfdymYO-lkp@intel.com/ Fixes: 74426fbff66e ("ALSA: ac97: add an ac97 bus") Signed-off-by: Pei Xiao Link: https://patch.msgid.link/3990bfc8cd47637908eaa179802c1d91459d829b.1732083924.git.xiaopei01@kylinos.cn Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/ac97/bus.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c index 40e88d79c483..f3fcb5c24f5b 100644 --- a/sound/ac97/bus.c +++ b/sound/ac97/bus.c @@ -180,7 +180,7 @@ static int ac97_bus_reset(struct ac97_controller *ac97_ctrl) /** * snd_ac97_codec_driver_register - register an AC97 codec driver - * @dev: AC97 driver codec to register + * @drv: AC97 driver codec to register * * Register an AC97 codec driver to the ac97 bus driver, aka. the AC97 digital * controller. @@ -196,7 +196,7 @@ EXPORT_SYMBOL_GPL(snd_ac97_codec_driver_register); /** * snd_ac97_codec_driver_unregister - unregister an AC97 codec driver - * @dev: AC97 codec driver to unregister + * @drv: AC97 codec driver to unregister * * Unregister a previously registered ac97 codec driver. */ @@ -338,6 +338,7 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl) * @dev: the device providing the ac97 DC function * @slots_available: mask of the ac97 codecs that can be scanned and probed * bit0 => codec 0, bit1 => codec 1 ... bit 3 => codec 3 + * @codecs_pdata: codec platform data * * Register a digital controller which can control up to 4 ac97 codecs. This is * the controller side of the AC97 AC-link, while the slave side are the codecs. From 60bb794ce15328ca40860743b9df1ee1c9fee335 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:03 +0100 Subject: [PATCH 225/256] ALSA: docs: fix dead hyperlink to Intel HD-Audio spec JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 56386292a0b44b550432aaff92f28e0d0d0f0209 Author: Hridesh MG Date: Wed Nov 20 21:25:51 2024 +0530 ALSA: docs: fix dead hyperlink to Intel HD-Audio spec Update the hyperlink as it currently redirects to a generic site instead of the actual specification. Signed-off-by: Hridesh MG Link: https://patch.msgid.link/20241120155553.21099-1-hridesh699@gmail.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- Documentation/sound/hd-audio/notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/sound/hd-audio/notes.rst b/Documentation/sound/hd-audio/notes.rst index e199131bf5ab..f81e94d8f145 100644 --- a/Documentation/sound/hd-audio/notes.rst +++ b/Documentation/sound/hd-audio/notes.rst @@ -42,7 +42,7 @@ If you are interested in the deep debugging of HD-audio, read the HD-audio specification at first. The specification is found on Intel's web page, for example: -* https://www.intel.com/standards/hdaudio/ +* https://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html HD-Audio Controller From 5ec3cf204aff36095d7767930055fbd7e895e0c7 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:03 +0100 Subject: [PATCH 226/256] ASoC: apple: Fix the wrong format specifier JIRA: https://issues.redhat.com/browse/RHEL-80681 commit f32c3f01c21cdd6a354988006aaca5e3dfe478f9 Author: liujing Date: Wed Nov 13 09:57:58 2024 +0800 ASoC: apple: Fix the wrong format specifier In the mca_fe_hw_params(), the variable tdm_slot_width is of type unsigned int, so the output should be %u Signed-off-by: liujing Link: https://patch.msgid.link/20241113015758.5441-1-liujing@cmss.chinamobile.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/apple/mca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c index aea08c7b2ee8..106609123d35 100644 --- a/sound/soc/apple/mca.c +++ b/sound/soc/apple/mca.c @@ -616,7 +616,7 @@ static int mca_fe_hw_params(struct snd_pcm_substream *substream, tdm_slot_width = 32; if (tdm_slot_width < params_width(params)) { - dev_err(dev, "TDM slots too narrow (tdm=%d params=%d)\n", + dev_err(dev, "TDM slots too narrow (tdm=%u params=%d)\n", tdm_slot_width, params_width(params)); return -EINVAL; } From 37b352bbde5e31df58c75161e78fb14832081e42 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:03 +0100 Subject: [PATCH 227/256] ASoC: doc: dapm: Add location information for dapm-graph tool JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 8697ecc3274214c65ff271a58e7abb601216f2a8 Author: anish kumar Date: Thu Nov 21 15:29:58 2024 -0800 ASoC: doc: dapm: Add location information for dapm-graph tool To help developers debug DAPM issues and visualize widget connectivity, the dapm-graph tool provides a graphical representation of how widgets and routes are connected. This commit adds the location information for the tool to the documentation, making it easier for users to find and use it for troubleshooting DAPM-related problems. Signed-off-by: anish kumar Link: https://patch.msgid.link/20241121232958.46179-1-yesanishhere@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- Documentation/sound/soc/dapm.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index 14c4dc026e6b..73a42d5a9f30 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -35,6 +35,9 @@ The graph for the STM32MP1-DK1 sound card is shown in picture: :alt: Example DAPM graph :align: center +You can also generate compatible graph for your sound card using +`tools/sound/dapm-graph` utility. + DAPM power domains ================== From 86528bd829c3e5717080f6ce029b41f50215948b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:03 +0100 Subject: [PATCH 228/256] ALSA: hda/tas2781: Add speaker id check for ASUS projects JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 4e7035a75da9371c93dabcb789883e31d2765dcf Author: Baojun Xu Date: Sat Nov 23 15:37:18 2024 +0800 ALSA: hda/tas2781: Add speaker id check for ASUS projects Add speaker id check by gpio in ACPI for ASUS projects. In other vendors, speaker id was checked by BIOS, and was applied in last bit of subsys id, so we can load corresponding firmware binary file for its speaker by subsys id. But in ASUS project, the firmware binary name will be appended an extra number to tell the speakers from different vendors. And this single digit come from gpio level of speaker id in BIOS. Signed-off-by: Baojun Xu Link: https://patch.msgid.link/20241123073718.475-1-baojun.xu@ti.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/tas2781.h | 1 + sound/pci/hda/tas2781_hda_i2c.c | 63 ++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index 8cd6da0480b7..72d2060904f6 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -156,6 +156,7 @@ struct tasdevice_priv { struct tasdevice_rca rcabin; struct calidata cali_data; struct tasdevice_fw *fmw; + struct gpio_desc *speaker_id; struct gpio_desc *reset; struct mutex codec_lock; struct regmap *regmap; diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index 4575d96ad38e..90ac07029aac 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -110,10 +111,20 @@ static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data) return 1; } +static const struct acpi_gpio_params speakerid_gpios = { 0, 0, false }; + +static const struct acpi_gpio_mapping tas2781_speaker_id_gpios[] = { + { "speakerid-gpios", &speakerid_gpios, 1 }, + { } +}; + static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid) { struct acpi_device *adev; + struct device *physdev; LIST_HEAD(resources); + const char *sub; + uint32_t subid; int ret; adev = acpi_dev_get_first_match_dev(hid, NULL, -1); @@ -123,18 +134,45 @@ static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid) return -ENODEV; } + physdev = get_device(acpi_get_first_physical_node(adev)); ret = acpi_dev_get_resources(adev, &resources, tas2781_get_i2c_res, p); - if (ret < 0) + if (ret < 0) { + dev_err(p->dev, "Failed to get ACPI resource.\n"); goto err; + } + sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); + if (IS_ERR(sub)) { + dev_err(p->dev, "Failed to get SUBSYS ID.\n"); + goto err; + } + /* Speaker id was needed for ASUS projects. */ + ret = kstrtou32(sub, 16, &subid); + if (!ret && upper_16_bits(subid) == PCI_VENDOR_ID_ASUSTEK) { + ret = devm_acpi_dev_add_driver_gpios(p->dev, + tas2781_speaker_id_gpios); + if (ret < 0) + dev_err(p->dev, "Failed to add driver gpio %d.\n", + ret); + p->speaker_id = devm_gpiod_get(p->dev, "speakerid", GPIOD_IN); + if (IS_ERR(p->speaker_id)) { + dev_err(p->dev, "Failed to get Speaker id.\n"); + ret = PTR_ERR(p->speaker_id); + goto err; + } + } else { + p->speaker_id = NULL; + } acpi_dev_free_resource_list(&resources); strscpy(p->dev_name, hid, sizeof(p->dev_name)); + put_device(physdev); acpi_dev_put(adev); return 0; err: dev_err(p->dev, "read acpi error, ret: %d\n", ret); + put_device(physdev); acpi_dev_put(adev); return ret; @@ -615,7 +653,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context) struct tasdevice_priv *tas_priv = context; struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev); struct hda_codec *codec = tas_priv->codec; - int i, ret; + int i, ret, spk_id; pm_runtime_get_sync(tas_priv->dev); mutex_lock(&tas_priv->codec_lock); @@ -648,8 +686,25 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context) tasdevice_dsp_remove(tas_priv); tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING; - scnprintf(tas_priv->coef_binaryname, 64, "TAS2XXX%04X.bin", - codec->core.subsystem_id & 0xffff); + if (tas_priv->speaker_id != NULL) { + // Speaker id need to be checked for ASUS only. + spk_id = gpiod_get_value(tas_priv->speaker_id); + if (spk_id < 0) { + // Speaker id is not valid, use default. + dev_dbg(tas_priv->dev, "Wrong spk_id = %d\n", spk_id); + spk_id = 0; + } + snprintf(tas_priv->coef_binaryname, + sizeof(tas_priv->coef_binaryname), + "TAS2XXX%04X%d.bin", + lower_16_bits(codec->core.subsystem_id), + spk_id); + } else { + snprintf(tas_priv->coef_binaryname, + sizeof(tas_priv->coef_binaryname), + "TAS2XXX%04X.bin", + lower_16_bits(codec->core.subsystem_id)); + } ret = tasdevice_dsp_parser(tas_priv); if (ret) { dev_err(tas_priv->dev, "dspfw load %s error\n", From 97971df748bcdd9bc182fe8c731913017d44355d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:03 +0100 Subject: [PATCH 229/256] ALSA: asihpi: Remove unused variable JIRA: https://issues.redhat.com/browse/RHEL-80681 commit a166f80343cd436d6d414199d18ad0ab291caaa5 Author: Zhu Jun Date: Tue Nov 26 01:32:45 2024 -0800 ALSA: asihpi: Remove unused variable the variable is never referenced in the code, just remove it. Signed-off-by: Zhu Jun Link: https://patch.msgid.link/20241126093245.3228-1-zhujun2@cmss.chinamobile.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/asihpi/asihpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index fdd4fe16225f..5a84591b13fc 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -464,7 +464,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, return -ENOMEM; } - err = hpi_stream_get_info_ex(dpcm->h_stream, NULL, + hpi_stream_get_info_ex(dpcm->h_stream, NULL, &dpcm->hpi_buffer_attached, NULL, NULL, NULL); } bytes_per_sec = params_rate(params) * params_channels(params); From d477690b55bfac57e021e3681a1e2a68e340bf12 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:04 +0100 Subject: [PATCH 230/256] ALSA: hda: Show the codec quirk info at probing JIRA: https://issues.redhat.com/browse/RHEL-80681 commit db2eee61434808d66233a9d3ea5ec31b8867de23 Author: Takashi Iwai Date: Tue Nov 26 15:10:10 2024 +0100 ALSA: hda: Show the codec quirk info at probing Lots of HD-audio devices need the device-specific quirk, and it's often helpful to know which quirk is applied. But currently the driver shows it only as a debug output, hence we'd have to enable the debug option at each time we want to see it (and the output becomes too messy due to other debug messages). This patch changes the messages to the info level, so that they appear at probing normally. Link: https://patch.msgid.link/20241126141010.12567-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_auto_parser.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 8e74be038b0f..84393f4f429d 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -933,6 +933,7 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec, bool match_all_pins) { const struct snd_hda_pin_quirk *pq; + const char *name = NULL; if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) return; @@ -946,9 +947,10 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec, codec->fixup_id = pq->value; #ifdef CONFIG_SND_DEBUG_VERBOSE codec->fixup_name = pq->name; - codec_dbg(codec, "%s: picked fixup %s (pin match)\n", - codec->core.chip_name, codec->fixup_name); + name = pq->name; #endif + codec_info(codec, "%s: picked fixup %s (pin match)\n", + codec->core.chip_name, name ? name : ""); codec->fixup_list = fixlist; return; } @@ -1015,8 +1017,8 @@ void snd_hda_pick_fixup(struct hda_codec *codec, if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { id = HDA_FIXUP_ID_NO_FIXUP; fixlist = NULL; - codec_dbg(codec, "%s: picked no fixup (nofixup specified)\n", - codec->core.chip_name); + codec_info(codec, "%s: picked no fixup (nofixup specified)\n", + codec->core.chip_name); goto found; } @@ -1026,8 +1028,8 @@ void snd_hda_pick_fixup(struct hda_codec *codec, if (!strcmp(codec->modelname, models->name)) { id = models->id; name = models->name; - codec_dbg(codec, "%s: picked fixup %s (model specified)\n", - codec->core.chip_name, codec->fixup_name); + codec_info(codec, "%s: picked fixup %s (model specified)\n", + codec->core.chip_name, name); goto found; } models++; @@ -1085,9 +1087,9 @@ void snd_hda_pick_fixup(struct hda_codec *codec, #ifdef CONFIG_SND_DEBUG_VERBOSE name = q->name; #endif - codec_dbg(codec, "%s: picked fixup %s for %s %04x:%04x\n", - codec->core.chip_name, name ? name : "", - type, q->subvendor, q->subdevice); + codec_info(codec, "%s: picked fixup %s for %s %04x:%04x\n", + codec->core.chip_name, name ? name : "", + type, q->subvendor, q->subdevice); found: codec->fixup_id = id; codec->fixup_list = fixlist; From 44819f702704aad006b5b78330c7964d54552ca9 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:04 +0100 Subject: [PATCH 231/256] ALSA: hda: improve bass speaker support for ASUS Zenbook UM5606WA JIRA: https://issues.redhat.com/browse/RHEL-80681 commit a7df7f909cec96e2fb7813a9b0b7e06a976983ab Author: Jaroslav Kysela Date: Thu Nov 28 12:21:45 2024 +0100 ALSA: hda: improve bass speaker support for ASUS Zenbook UM5606WA This hardware has ALC294 codec with speaker NID 0x17 and bass speaker NID 0x15. This patch removes DAC NID 0x06 (without volume control) from the connection list for bass speaker NID 0x15. Both speaker PINs are routed to DAC NID 0x03 with this change. Link: https://github.com/alsa-project/alsa-ucm-conf/issues/467 Signed-off-by: Jaroslav Kysela Link: https://patch.msgid.link/20241128112145.3409492-1-perex@perex.cz Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_realtek.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 04dff49c8ae4..82e212cc736c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6491,6 +6491,16 @@ static void alc285_fixup_speaker2_to_dac1(struct hda_codec *codec, } } +/* disable DAC3 (0x06) selection on NID 0x15 - share Speaker/Bass Speaker DAC 0x03 */ +static void alc294_fixup_bass_speaker_15(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + static const hda_nid_t conn[] = { 0x02, 0x03 }; + snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn), conn); + } +} + /* Hook to update amp GPIO4 for automute */ static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec, struct hda_jack_callback *jack) @@ -7780,6 +7790,7 @@ enum { ALC245_FIXUP_CLEVO_NOISY_MIC, ALC269_FIXUP_VAIO_VJFH52_MIC_NO_PRESENCE, ALC233_FIXUP_MEDION_MTL_SPK, + ALC294_FIXUP_BASS_SPEAKER_15, }; /* A special fixup for Lenovo C940 and Yoga Duet 7; @@ -10114,6 +10125,10 @@ static const struct hda_fixup alc269_fixups[] = { { } }, }, + [ALC294_FIXUP_BASS_SPEAKER_15] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc294_fixup_bass_speaker_15, + }, }; static const struct hda_quirk alc269_fixup_tbl[] = { @@ -10633,6 +10648,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2), + SND_PCI_QUIRK(0x1043, 0x1df3, "ASUS UM5606WA", ALC294_FIXUP_BASS_SPEAKER_15), SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2), From 94be90edaa846c92ef0e86f05c73967b2ac82b1f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:04 +0100 Subject: [PATCH 232/256] ALSA: hda/tas2781: Fix error code tas2781_read_acpi() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit a0cd2b265fe3f675c121df848aec2e79ff7c100f Author: Dan Carpenter Date: Sat Nov 30 13:08:18 2024 +0300 ALSA: hda/tas2781: Fix error code tas2781_read_acpi() Return an error code if acpi_get_subsystem_id() fails. Don't return success. Fixes: 4e7035a75da9 ("ALSA: hda/tas2781: Add speaker id check for ASUS projects") Signed-off-by: Dan Carpenter Link: https://patch.msgid.link/ef773f8a-a61d-478b-9e81-41a38a75c77b@stanley.mountain Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/tas2781_hda_i2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index 90ac07029aac..69db598aef0e 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -143,6 +143,7 @@ static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid) sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); if (IS_ERR(sub)) { dev_err(p->dev, "Failed to get SUBSYS ID.\n"); + ret = PTR_ERR(sub); goto err; } /* Speaker id was needed for ASUS projects. */ From 8d811bc30118bf07235fd43320359a4a8c3da9cb Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:19 +0100 Subject: [PATCH 233/256] ASoC: Intel: avs: da7219: Remove suspend_pre() and resume_post() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 04c319e05d0b08cc789db7abccce0fcb13dbab16 Author: Marek Maslanka Date: Thu Nov 28 20:52:09 2024 +0000 ASoC: Intel: avs: da7219: Remove suspend_pre() and resume_post() The presence of a plugged jack is not detected after resuming the device if the jack was plugged before the device was suspended. This problem is caused by calling the sound/soc/codecs/da7219-aad.c:da7219_aad_jack_det() function on resume, which forces the jack insertion state to be unplugged. Signed-off-by: Marek Maslanka Link: https://patch.msgid.link/20241128205215.2435485-1-mmaslanka@google.com Reviewed-by: Cezary Rojewski Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/intel/avs/boards/da7219.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c index 93eba4fd2771..76078a7005b0 100644 --- a/sound/soc/intel/avs/boards/da7219.c +++ b/sound/soc/intel/avs/boards/da7219.c @@ -209,21 +209,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in return 0; } -static int avs_card_suspend_pre(struct snd_soc_card *card) -{ - struct snd_soc_dai *codec_dai = snd_soc_card_get_codec_dai(card, DA7219_DAI_NAME); - - return snd_soc_component_set_jack(codec_dai->component, NULL, NULL); -} - -static int avs_card_resume_post(struct snd_soc_card *card) -{ - struct snd_soc_dai *codec_dai = snd_soc_card_get_codec_dai(card, DA7219_DAI_NAME); - struct snd_soc_jack *jack = snd_soc_card_get_drvdata(card); - - return snd_soc_component_set_jack(codec_dai->component, jack, NULL); -} - static int avs_da7219_probe(struct platform_device *pdev) { struct snd_soc_dai_link *dai_link; @@ -255,8 +240,6 @@ static int avs_da7219_probe(struct platform_device *pdev) card->name = "avs_da7219"; card->dev = dev; card->owner = THIS_MODULE; - card->suspend_pre = avs_card_suspend_pre; - card->resume_post = avs_card_resume_post; card->dai_link = dai_link; card->num_links = 1; card->controls = card_controls; From e6774c6a7b743b9ae5d6d7d86105f86339a66f12 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:38 +0100 Subject: [PATCH 234/256] ASoC: SDCA: Use *-y for Makefile JIRA: https://issues.redhat.com/browse/RHEL-80681 commit f60646d9c3bd5b390728ed1a1caa9ded53d47afc Author: Takashi Iwai Date: Tue Dec 3 15:18:18 2024 +0100 ASoC: SDCA: Use *-y for Makefile We should use *-y instead of *-objs in Makefile for the module objects. *-objs is used rather for host programs. Fixes: 3a513da1ae33 ("ASoC: SDCA: add initial module") Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20241203141823.22393-4-tiwai@suse.de Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/sdca/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sdca/Makefile b/sound/soc/sdca/Makefile index c296bd5a0a7c..5d1ddbbfbf62 100644 --- a/sound/soc/sdca/Makefile +++ b/sound/soc/sdca/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-sdca-objs := sdca_functions.o sdca_device.o +snd-soc-sdca-y := sdca_functions.o sdca_device.o obj-$(CONFIG_SND_SOC_SDCA) += snd-soc-sdca.o From 0d7965de551cbefae3cd6a7c562507eabb30b024 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:38 +0100 Subject: [PATCH 235/256] ASoC: cs42l84: Use *-y for Makefile JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7916a8d8782d4e53fe0133c8dace20a925e0204e Author: Takashi Iwai Date: Tue Dec 3 15:18:19 2024 +0100 ASoC: cs42l84: Use *-y for Makefile We should use *-y instead of *-objs in Makefile for the module objects. *-objs is used rather for host programs. Fixes: 250304a0fb34 ("ASoC: cs42l84: Add new codec driver") Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20241203141823.22393-5-tiwai@suse.de Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index eba330568a26..69985070d140 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -91,7 +91,7 @@ snd-soc-cs42l52-y := cs42l52.o snd-soc-cs42l56-y := cs42l56.o snd-soc-cs42l73-y := cs42l73.o snd-soc-cs42l83-i2c-y := cs42l83-i2c.o -snd-soc-cs42l84-objs := cs42l84.o +snd-soc-cs42l84-y := cs42l84.o snd-soc-cs4234-y := cs4234.o snd-soc-cs4265-y := cs4265.o snd-soc-cs4270-y := cs4270.o From fed4c1ce62e3230fcca887b5ae09f0ac9abde26b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:38 +0100 Subject: [PATCH 236/256] ASoC: wcd937x: Use *-y for Makefile JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 582057d2233a5a38e1aec3f4a6d66b362b42076c Author: Takashi Iwai Date: Tue Dec 3 15:18:20 2024 +0100 ASoC: wcd937x: Use *-y for Makefile We should use *-y instead of *-objs in Makefile for the module objects. *-objs is used rather for host programs. Fixes: 313e978df7fc ("ASoC: codecs: wcd937x: add audio routing and Kconfig") Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20241203141823.22393-6-tiwai@suse.de Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 69985070d140..2ca8f697bdcf 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -324,8 +324,8 @@ snd-soc-wcd-classh-y := wcd-clsh-v2.o snd-soc-wcd-mbhc-y := wcd-mbhc-v2.o snd-soc-wcd9335-y := wcd9335.o snd-soc-wcd934x-y := wcd934x.o -snd-soc-wcd937x-objs := wcd937x.o -snd-soc-wcd937x-sdw-objs := wcd937x-sdw.o +snd-soc-wcd937x-y := wcd937x.o +snd-soc-wcd937x-sdw-y := wcd937x-sdw.o snd-soc-wcd938x-y := wcd938x.o snd-soc-wcd938x-sdw-y := wcd938x-sdw.o snd-soc-wcd939x-y := wcd939x.o From 52593b8cd1a6d3a0631cd4664a277e9cf67f8bd7 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:39 +0100 Subject: [PATCH 237/256] ALSA: compress_offload: avoid 64-bit get_user() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 6018f2fe1089b46c6c9eb136338eca7b16a92331 Author: Arnd Bergmann Date: Mon Dec 16 10:33:41 2024 +0100 ALSA: compress_offload: avoid 64-bit get_user() On some architectures, get_user() cannot read a 64-bit user variable: arm-linux-gnueabi-ld: sound/core/compress_offload.o: in function `snd_compr_ioctl': compress_offload.c:(.text.snd_compr_ioctl+0x538): undefined reference to `__get_user_bad' Use an equivalent copy_from_user() instead. Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode") Signed-off-by: Arnd Bergmann Acked-by: Shengjiu Wang Acked-by: Vinod Koul Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20241216093410.377112-2-arnd@kernel.org Signed-off-by: Jaroslav Kysela --- sound/core/compress_offload.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 86ed2fbee0c8..c2dfb32f08d0 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -1180,9 +1180,9 @@ static int snd_compr_task_seq(struct snd_compr_stream *stream, unsigned long arg if (stream->runtime->state != SNDRV_PCM_STATE_SETUP) return -EPERM; - retval = get_user(seqno, (__u64 __user *)arg); - if (retval < 0) - return retval; + retval = copy_from_user(&seqno, (__u64 __user *)arg, sizeof(seqno)); + if (retval) + return -EFAULT; retval = 0; if (seqno == 0) { list_for_each_entry_reverse(task, &stream->runtime->tasks, list) From 15440039dde422f68167371c5455e906a1248d55 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:39 +0100 Subject: [PATCH 238/256] ALSA: compress_offload: import DMA_BUF namespace JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 1ae40d5231732275c620a1c58c83884a979b6eb1 Author: Arnd Bergmann Date: Mon Dec 16 10:33:40 2024 +0100 ALSA: compress_offload: import DMA_BUF namespace The compression offload code cannot be in a loadable module unless it imports that namespace: ERROR: modpost: module snd-compress uses symbol dma_buf_get from namespace DMA_BUF, but does not import it. ERROR: modpost: module snd-compress uses symbol dma_buf_put from namespace DMA_BUF, but does not import it. ERROR: modpost: module snd-compress uses symbol dma_buf_fd from namespace DMA_BUF, but does not import it. Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode") Signed-off-by: Arnd Bergmann Acked-by: Shengjiu Wang Acked-by: Vinod Koul Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20241216093410.377112-1-arnd@kernel.org Signed-off-by: Jaroslav Kysela --- sound/core/compress_offload.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index c2dfb32f08d0..1d6769a66810 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -1247,6 +1247,7 @@ void snd_compr_task_finished(struct snd_compr_stream *stream, } EXPORT_SYMBOL_GPL(snd_compr_task_finished); +MODULE_IMPORT_NS("DMA_BUF"); #endif /* CONFIG_SND_COMPRESS_ACCEL */ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) From 0895f4dc691a1dde92e1b509b3967d29ce965754 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:39 +0100 Subject: [PATCH 239/256] ALSA: compress_offload: use safe list iteration in snd_compr_task_seq() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit f25a51b47c61540585a9e8a4e16f91677ebcbbc4 Author: Jaroslav Kysela Date: Tue Dec 17 11:07:07 2024 +0100 ALSA: compress_offload: use safe list iteration in snd_compr_task_seq() The sequence function can call snd_compr_task_free_one(). Use list_for_each_entry_safe_reverse() to make sure that the used pointers are safe. Link: https://lore.kernel.org/linux-sound/f2769cff-6c7a-4092-a2d1-c33a5411a182@stanley.mountain/ Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode") Reported-by: Dan Carpenter Cc: Vinod Koul Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20241217100707.732766-1-perex@perex.cz Signed-off-by: Jaroslav Kysela --- sound/core/compress_offload.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 1d6769a66810..bdb6e307e453 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -1174,7 +1174,7 @@ typedef void (*snd_compr_seq_func_t)(struct snd_compr_stream *stream, static int snd_compr_task_seq(struct snd_compr_stream *stream, unsigned long arg, snd_compr_seq_func_t fcn) { - struct snd_compr_task_runtime *task; + struct snd_compr_task_runtime *task, *temp; __u64 seqno; int retval; @@ -1185,7 +1185,7 @@ static int snd_compr_task_seq(struct snd_compr_stream *stream, unsigned long arg return -EFAULT; retval = 0; if (seqno == 0) { - list_for_each_entry_reverse(task, &stream->runtime->tasks, list) + list_for_each_entry_safe_reverse(task, temp, &stream->runtime->tasks, list) fcn(stream, task); } else { task = snd_compr_find_task(stream, seqno); From 05a94f9b3e0a94d6032546c6c5e07a2b7f7fecec Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:39 +0100 Subject: [PATCH 240/256] ALSA: compress_offload: improve file descriptors installation for dma-buf JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 3d3f43fab4cfb9cf245e3dbffa1736ce925bb54a Author: Jaroslav Kysela Date: Tue Dec 17 11:07:26 2024 +0100 ALSA: compress_offload: improve file descriptors installation for dma-buf Avoid to use single dma_buf_fd() call for both directions. This code ensures that both file descriptors are allocated before fd_install(). Link: https://lore.kernel.org/linux-sound/6a923647-4495-4cff-a253-b73f48cfd0ea@stanley.mountain/ Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode") Reported-by: Dan Carpenter Cc: Vinod Koul Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20241217100726.732863-1-perex@perex.cz Signed-off-by: Jaroslav Kysela --- sound/core/compress_offload.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index bdb6e307e453..edf5aadf38e5 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -1025,7 +1025,7 @@ static u64 snd_compr_seqno_next(struct snd_compr_stream *stream) static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_task *utask) { struct snd_compr_task_runtime *task; - int retval; + int retval, fd_i, fd_o; if (stream->runtime->total_tasks >= stream->runtime->fragments) return -EBUSY; @@ -1039,16 +1039,24 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_ retval = stream->ops->task_create(stream, task); if (retval < 0) goto cleanup; - utask->input_fd = dma_buf_fd(task->input, O_WRONLY|O_CLOEXEC); - if (utask->input_fd < 0) { - retval = utask->input_fd; + /* similar functionality as in dma_buf_fd(), but ensure that both + file descriptors are allocated before fd_install() */ + if (!task->input || !task->input->file || !task->output || !task->output->file) { + retval = -EINVAL; goto cleanup; } - utask->output_fd = dma_buf_fd(task->output, O_RDONLY|O_CLOEXEC); - if (utask->output_fd < 0) { - retval = utask->output_fd; + fd_i = get_unused_fd_flags(O_WRONLY|O_CLOEXEC); + if (fd_i < 0) + goto cleanup; + fd_o = get_unused_fd_flags(O_RDONLY|O_CLOEXEC); + if (fd_o < 0) { + put_unused_fd(fd_i); goto cleanup; } + fd_install(fd_i, task->input->file); + fd_install(fd_o, task->output->file); + utask->input_fd = fd_i; + utask->output_fd = fd_o; /* keep dmabuf reference until freed with task free ioctl */ dma_buf_get(utask->input_fd); dma_buf_get(utask->output_fd); From 640b38640c8d3c9aaf02d46e9cef9ddbfad81c6f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:40 +0100 Subject: [PATCH 241/256] ALSA: hda/tas2781: Ignore SUBSYS_ID not found for tas2563 projects JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 6a451e2c5c03e27aa3ec36be424fccaa286c3ccd Author: Baojun Xu Date: Mon Dec 30 14:49:10 2024 +0800 ALSA: hda/tas2781: Ignore SUBSYS_ID not found for tas2563 projects Driver will return error if no SUBSYS_ID found in BIOS(acpi). It will cause error in tas2563 projects, which have no SUBSYS_ID. Fixes: 4e7035a75da9 ("ALSA: hda/tas2781: Add speaker id check for ASUS projects") Signed-off-by: Baojun Xu Link: https://lore.kernel.org/20241223225442.1358491-1-stuart.a.hayhurst@gmail.com Link: https://patch.msgid.link/20241230064910.1583-1-baojun.xu@ti.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/tas2781_hda_i2c.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index 69db598aef0e..3e6cf8bd5022 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -142,6 +142,9 @@ static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid) } sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); if (IS_ERR(sub)) { + /* No subsys id in older tas2563 projects. */ + if (!strncmp(hid, "INT8866", sizeof("INT8866"))) + goto end_2563; dev_err(p->dev, "Failed to get SUBSYS ID.\n"); ret = PTR_ERR(sub); goto err; @@ -164,6 +167,7 @@ static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid) p->speaker_id = NULL; } +end_2563: acpi_dev_free_resource_list(&resources); strscpy(p->dev_name, hid, sizeof(p->dev_name)); put_device(physdev); From b668ac764135738c051c8e90ade9a85fcb15d39a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:40 +0100 Subject: [PATCH 242/256] ALSA: compress_offload: Drop unneeded no_free_ptr() JIRA: https://issues.redhat.com/browse/RHEL-80681 commit ac9fae799eda81e24bbf2e0d5cb9e5c33fc9bdcb Author: Takashi Iwai Date: Sun Dec 29 09:39:13 2024 +0100 ALSA: compress_offload: Drop unneeded no_free_ptr() The error path for memdup_user() no longer needs the tricky wrap with no_free_ptr() and we can safely return the error pointer directly. Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202412290846.cncnpGaw-lkp@intel.com/ Link: https://patch.msgid.link/20241229083917.14912-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/core/compress_offload.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index edf5aadf38e5..4ed6cec5fd5c 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -1077,7 +1077,7 @@ static int snd_compr_task_create(struct snd_compr_stream *stream, unsigned long return -EPERM; task = memdup_user((void __user *)arg, sizeof(*task)); if (IS_ERR(task)) - return PTR_ERR(no_free_ptr(task)); + return PTR_ERR(task); retval = snd_compr_task_new(stream, task); if (retval >= 0) if (copy_to_user((void __user *)arg, task, sizeof(*task))) @@ -1138,7 +1138,7 @@ static int snd_compr_task_start_ioctl(struct snd_compr_stream *stream, unsigned return -EPERM; task = memdup_user((void __user *)arg, sizeof(*task)); if (IS_ERR(task)) - return PTR_ERR(no_free_ptr(task)); + return PTR_ERR(task); retval = snd_compr_task_start(stream, task); if (retval >= 0) if (copy_to_user((void __user *)arg, task, sizeof(*task))) @@ -1229,7 +1229,7 @@ static int snd_compr_task_status_ioctl(struct snd_compr_stream *stream, unsigned return -EPERM; status = memdup_user((void __user *)arg, sizeof(*status)); if (IS_ERR(status)) - return PTR_ERR(no_free_ptr(status)); + return PTR_ERR(status); retval = snd_compr_task_status(stream, status); if (retval >= 0) if (copy_to_user((void __user *)arg, status, sizeof(*status))) From 680613b8180dd6f81458f1e14730cf0ad6d74c44 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:40 +0100 Subject: [PATCH 243/256] ALSA: compress_offload: fix remaining descriptor races in sound/core/compress_offload.c JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 7439b395211874e20c24b2fe0e4903864357a3f5 Author: Al Viro Date: Sun Dec 29 18:52:32 2024 +0000 ALSA: compress_offload: fix remaining descriptor races in sound/core/compress_offload.c 3d3f43fab4cf ("ALSA: compress_offload: improve file descriptors installation for dma-buf") fixed some of descriptor races in snd_compr_task_new(), but there's a couple more left. We need to grab the references to dmabuf before moving them into descriptor table - trying to do that by descriptor afterwards might end up getting a different object, with a dangling reference left in task->{input,output} Fixes: 3d3f43fab4cf ("ALSA: compress_offload: improve file descriptors installation for dma-buf") Signed-off-by: Al Viro Link: https://patch.msgid.link/20241229185232.GA1977892@ZenIV Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/core/compress_offload.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 4ed6cec5fd5c..840bb9cfe789 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -1053,13 +1053,13 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_ put_unused_fd(fd_i); goto cleanup; } + /* keep dmabuf reference until freed with task free ioctl */ + get_dma_buf(task->input); + get_dma_buf(task->output); fd_install(fd_i, task->input->file); fd_install(fd_o, task->output->file); utask->input_fd = fd_i; utask->output_fd = fd_o; - /* keep dmabuf reference until freed with task free ioctl */ - dma_buf_get(utask->input_fd); - dma_buf_get(utask->output_fd); list_add_tail(&task->list, &stream->runtime->tasks); stream->runtime->total_tasks++; return 0; From 61307fa494d26a80d133e46d55f38129d4d3521c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:40 +0100 Subject: [PATCH 244/256] ASoC: codecs: ES8326: Adjust ANA_MICBIAS to reduce pop noise JIRA: https://issues.redhat.com/browse/RHEL-80681 commit b1d4ac91a9246d7fb1906b2f38f529b097884c8e Author: Zhang Yi Date: Mon Dec 30 11:27:52 2024 +0800 ASoC: codecs: ES8326: Adjust ANA_MICBIAS to reduce pop noise We modify the value of ES8326_ANA_MICBIAS to reduce the pop noise Signed-off-by: Zhang Yi Link: https://patch.msgid.link/20241230032752.108298-1-zhangyi@everest-semi.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/es8326.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index 096772b35127..1ddf20e69690 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -617,7 +617,7 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) 0x0F, 0x0F); if (es8326->version > ES8326_VERSION_B) { regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); - regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x10); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x30); } } } else { @@ -632,6 +632,8 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) regmap_write(es8326->regmap, ES8326_HPR_OFFSET_INI, offset_r); es8326->calibrated = true; } + regmap_update_bits(es8326->regmap, ES8326_CLK_INV, 0xc0, 0x00); + regmap_update_bits(es8326->regmap, ES8326_CLK_MUX, 0x80, 0x00); if (direction == SNDRV_PCM_STREAM_PLAYBACK) { regmap_update_bits(es8326->regmap, ES8326_DAC_DSM, 0x01, 0x01); usleep_range(1000, 5000); @@ -646,7 +648,7 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) } else { msleep(300); if (es8326->version > ES8326_VERSION_B) { - regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x50); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x70); regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x00); } regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE, @@ -677,6 +679,10 @@ static int es8326_set_bias_level(struct snd_soc_component *codec, regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x00); regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x20); regmap_update_bits(es8326->regmap, ES8326_RESET, 0x02, 0x00); + if (es8326->version > ES8326_VERSION_B) { + regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x30); + } break; case SND_SOC_BIAS_PREPARE: break; @@ -684,6 +690,12 @@ static int es8326_set_bias_level(struct snd_soc_component *codec, regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x3b); regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x00); regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, ES8326_IO_INPUT); + if (es8326->version > ES8326_VERSION_B) { + regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x10); + } + regmap_update_bits(es8326->regmap, ES8326_CLK_INV, 0xc0, 0xc0); + regmap_update_bits(es8326->regmap, ES8326_CLK_MUX, 0x80, 0x80); break; case SND_SOC_BIAS_OFF: clk_disable_unprepare(es8326->mclk); @@ -774,7 +786,10 @@ static void es8326_jack_button_handler(struct work_struct *work) case 0x6f: case 0x4b: /* button volume up */ - cur_button = SND_JACK_BTN_1; + if ((iface == 0x6f) && (es8326->version > ES8326_VERSION_B)) + cur_button = SND_JACK_BTN_0; + else + cur_button = SND_JACK_BTN_1; break; case 0x27: /* button volume down */ @@ -1083,7 +1098,7 @@ static void es8326_init(struct snd_soc_component *component) regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66); es8326_disable_micbias(es8326->component); if (es8326->version > ES8326_VERSION_B) { - regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x73, 0x13); + regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x73, 0x10); regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40); } From 2ea474dfabe3d4ab32f054ced859fa7c1781d2db Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:40 +0100 Subject: [PATCH 245/256] ASoC: tas2781: Fix occasional calibration failture JIRA: https://issues.redhat.com/browse/RHEL-80681 commit cf86e0ae60a225e2c7921ced755e922da9012bea Author: Shenghao Ding Date: Fri Dec 27 15:49:09 2024 +0800 ASoC: tas2781: Fix occasional calibration failture The root cause is that TAS2781 internal register is not unlocked before writing data into TAS2781_PRM_TEST_57_REG. Fixes: 49e2e353fb0d ("ASoC: tas2781: Add Calibration Kcontrols for Chromebook") Signed-off-by: Shenghao Ding Link: https://patch.msgid.link/20241227074909.1974-1-shenghao-ding@ti.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/tas2781-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index 2fcb3bd254e3..0bd031bd8204 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -78,7 +78,7 @@ static const struct bulk_reg_val tas2781_cali_start_reg[] = { X2781_CL_STT_VAL(TAS2781_PRM_INT_MASK_REG, 0xfe, false), X2781_CL_STT_VAL(TAS2781_PRM_CLK_CFG_REG, 0xdd, false), X2781_CL_STT_VAL(TAS2781_PRM_RSVD_REG, 0x20, false), - X2781_CL_STT_VAL(TAS2781_PRM_TEST_57_REG, 0x14, false), + X2781_CL_STT_VAL(TAS2781_PRM_TEST_57_REG, 0x14, true), X2781_CL_STT_VAL(TAS2781_PRM_TEST_62_REG, 0x45, true), X2781_CL_STT_VAL(TAS2781_PRM_PVDD_UVLO_REG, 0x03, false), X2781_CL_STT_VAL(TAS2781_PRM_CHNL_0_REG, 0xa8, false), From 91c14904211c71e1b12179ca9053ac9cd5933071 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:40 +0100 Subject: [PATCH 246/256] ASoC: wm8994: Add depends on MFD core JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 5ed01155cea69801f1f0c908954a56a5a3474bed Author: Charles Keepax Date: Mon Jan 6 15:46:39 2025 +0000 ASoC: wm8994: Add depends on MFD core The ASoC driver should not be used without the MFD component. This was causing randconfig issues with regmap IRQ which is selected by the MFD part of the wm8994 driver. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202501061337.R0DlBUoD-lkp@intel.com/ Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250106154639.3999553-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9659190c854e..8bf47319ecc7 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2368,6 +2368,7 @@ config SND_SOC_WM8993 config SND_SOC_WM8994 tristate + depends on MFD_WM8994 config SND_SOC_WM8995 tristate From 3bc17b81746bd37d7271db77ab591154c7bed9c8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:41 +0100 Subject: [PATCH 247/256] ASoC: codecs: es8316: Fix HW rate calculation for 48Mhz MCLK JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 85c9ac7a56f731ecd59317c822cb6295464444cc Author: Marian Postevca Date: Fri Dec 27 22:27:51 2024 +0200 ASoC: codecs: es8316: Fix HW rate calculation for 48Mhz MCLK For 48Mhz MCLK systems the calculation of the HW rate is broken, and will not produce even one sane rate. Since es83xx supports the option to halve MCLK, calculate also rates with MCLK/2. Signed-off-by: Marian Postevca Link: https://patch.msgid.link/20241227202751.244954-1-posteuca@mutex.one Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/es8316.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index cd40de650e02..f21cb96cb535 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -39,7 +39,9 @@ struct es8316_priv { struct snd_soc_jack *jack; int irq; unsigned int sysclk; - unsigned int allowed_rates[ARRAY_SIZE(supported_mclk_lrck_ratios)]; + /* ES83xx supports halving the MCLK so it supports twice as many rates + */ + unsigned int allowed_rates[ARRAY_SIZE(supported_mclk_lrck_ratios) * 2]; struct snd_pcm_hw_constraint_list sysclk_constraints; bool jd_inverted; }; @@ -386,6 +388,12 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai, if (freq % ratio == 0) es8316->allowed_rates[count++] = freq / ratio; + + /* We also check if the halved MCLK produces a valid rate + * since the codec supports halving the MCLK. + */ + if ((freq / ratio) % 2 == 0) + es8316->allowed_rates[count++] = freq / ratio / 2; } if (count) { From 0c0a11a1946a3efaabd696ef32705dd31ce06d8e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:41 +0100 Subject: [PATCH 248/256] ASoC: samsung: Add missing selects for MFD_WM8994 JIRA: https://issues.redhat.com/browse/RHEL-80681 commit fd55c6065bec5268740e944a1800e6fad00974d9 Author: Charles Keepax Date: Tue Jan 7 10:41:34 2025 +0000 ASoC: samsung: Add missing selects for MFD_WM8994 Anything selecting SND_SOC_WM8994 should also select MFD_WM8994, as SND_SOC_WM8994 does not automatically do so. Add the missing selects. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202501071530.UwIXs7OL-lkp@intel.com/ Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250107104134.12147-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/samsung/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 93c2b1b08d0a..77d3beea1d71 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -127,8 +127,9 @@ config SND_SOC_SAMSUNG_TM2_WM5110 config SND_SOC_SAMSUNG_ARIES_WM8994 tristate "SoC I2S Audio support for WM8994 on Aries" - depends on SND_SOC_SAMSUNG && MFD_WM8994 && IIO && EXTCON + depends on SND_SOC_SAMSUNG && IIO && EXTCON select SND_SOC_BT_SCO + select MFD_WM8994 select SND_SOC_WM8994 select SND_SAMSUNG_I2S help @@ -142,6 +143,7 @@ config SND_SOC_SAMSUNG_MIDAS_WM1811 tristate "SoC I2S Audio support for Midas boards" depends on SND_SOC_SAMSUNG select SND_SAMSUNG_I2S + select MFD_WM8994 select SND_SOC_WM8994 help Say Y if you want to add support for SoC audio on the Midas boards. From 85f14d5237b4764bafe06a2102b8ef86e4ffb4bb Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:56 +0100 Subject: [PATCH 249/256] ALSA: doc: cs35l56: Add information about Cirrus Logic CS35L54/56/57 JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 088fb4ee17fc456fcbce0a9ff46d147e3b2be139 Author: Richard Fitzgerald Date: Wed Jan 8 14:10:45 2025 +0000 ALSA: doc: cs35l56: Add information about Cirrus Logic CS35L54/56/57 Add documentation for the Cirrus Logic CS35L54/56/57 amps, which are all managed by the cs35l56 drivers. The aim and scope of this documentation is to provide troubleshooting information for end-users. Signed-off-by: Richard Fitzgerald Link: https://patch.msgid.link/20250108141045.1032-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- Documentation/sound/codecs/cs35l56.rst | 292 +++++++++++++++++++++++++ Documentation/sound/codecs/index.rst | 9 + MAINTAINERS | 1 + 3 files changed, 302 insertions(+) create mode 100644 Documentation/sound/codecs/cs35l56.rst create mode 100644 Documentation/sound/codecs/index.rst diff --git a/Documentation/sound/codecs/cs35l56.rst b/Documentation/sound/codecs/cs35l56.rst new file mode 100644 index 000000000000..98c6f6c74394 --- /dev/null +++ b/Documentation/sound/codecs/cs35l56.rst @@ -0,0 +1,292 @@ +.. SPDX-License-Identifier: GPL-2.0-only + +===================================================================== +Audio drivers for Cirrus Logic CS35L54/56/57 Boosted Smart Amplifiers +===================================================================== +:Copyright: 2025 Cirrus Logic, Inc. and + Cirrus Logic International Semiconductor Ltd. + +Contact: patches@opensource.cirrus.com + +Summary +======= + +The high-level summary of this document is: + +**If you have a laptop that uses CS35L54/56/57 amplifiers but audio is not +working, DO NOT ATTEMPT TO USE FIRMWARE AND SETTINGS FROM ANOTHER LAPTOP, +EVEN IF THAT LAPTOP SEEMS SIMILAR.** + +The CS35L54/56/57 amplifiers must be correctly configured for the power +supply voltage, speaker impedance, maximum speaker voltage/current, and +other external hardware connections. + +The amplifiers feature advanced boost technology that increases the voltage +used to drive the speakers, while proprietary speaker protection algorithms +allow these boosted amplifiers to push the limits of the speakers without +causing damage. These **must** be configured correctly. + +Supported Cirrus Logic amplifiers +--------------------------------- + +The cs35l56 drivers support: + +* CS35L54 +* CS35L56 +* CS35L57 + +There are two drivers in the kernel + +*For systems using SoundWire*: sound/soc/codecs/cs35l56.c and associated files + +*For systems using HDA*: sound/pci/hda/cs35l56_hda.c + +Firmware +======== + +The amplifier is controlled and managed by firmware running on the internal +DSP. Firmware files are essential to enable the full capabilities of the +amplifier. + +Firmware is distributed in the linux-firmware repository: +https://gitlab.com/kernel-firmware/linux-firmware.git + +On most SoundWire systems the amplifier has a default minimum capability to +produce audio. However this will be + +* at low volume, to protect the speakers, since the speaker specifications + and power supply voltages are unknown. +* a mono mix of left and right channels. + +On some SoundWire systems that have both CS42L43 and CS35L56/57 the CS35L56/57 +receive their audio from the CS42L43 instead of directly from the host +SoundWire interface. These systems can be identified by the CS42L43 showing +in dmesg as a SoundWire device, but the CS35L56/57 as SPI. On these systems +the firmware is *mandatory* to enable receiving the audio from the CS42L43. + +On HDA systems the firmware is *mandatory* to enable HDA bridge mode. There +will not be any audio from the amplifiers without firmware. + +Cirrus Logic firmware files +--------------------------- + +Each amplifier requires two firmware files. One file has a .wmfw suffix, the +other has a .bin suffix. + +The firmware is customized by the OEM to match the hardware of each laptop, +and the firmware is specific to that laptop. Because of this, there are many +firmware files in linux-firmware for these amplifiers. Firmware files are +**not interchangeable between laptops**. + +Cirrus Logic submits files for known laptops to the upstream linux-firmware +repository. Providing Cirrus Logic is aware of a particular laptop and has +permission from the manufacturer to publish the firmware, it will be pushed +to linux-firmware. You may need to upgrade to a newer release of +linux-firmware to obtain the firmware for your laptop. + +**Important:** the Makefile for linux-firmware creates symlinks that are listed +in the WHENCE file. These symlinks are required for the CS35L56 driver to be +able to load the firmware. + +How do I know which firmware file I should have? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +All firmware file names are qualified with a unique "system ID". On normal +x86 PCs with PCI audio this is the Vendor Subsystem ID (SSID) of the host +PCI audio interface. + +The SSID can be viewed using the lspci tool:: + + lspci -v -nn | grep -A2 -i audio + 0000:00:1f.3 Audio device [0403]: Intel Corporation Meteor Lake-P HD Audio Controller [8086:7e28] + Subsystem: Dell Meteor Lake-P HD Audio Controller [1028:0c63] + +In this example the SSID is 10280c63. + +The format of the firmware file names is: + + cs35lxx-b0-dsp1-misc-SSID[-spkidX]-ampN + +Where: + + * cs35lxx-b0 is the amplifier model and silicon revision. This information + is logged by the driver during initialization. + * SSID is the 8-digit hexadecimal SSID value. + * ampN is the amplifier number (for example amp1). This is the same as + the prefix on the ALSA control names except that it is always lower-case + in the file name. + * spkidX is an optional part, used for laptops that have firmware + configurations for different makes and models of internal speakers. + +Sound Open Firmware and ALSA topology files +------------------------------------------- + +All SoundWire systems will require a Sound Open Firmware (SOF) for the +host CPU audio DSP, together with an ALSA topology file (.tplg). + +The SOF firmware will usually be provided by the manufacturer of the host +CPU (i.e. Intel or AMD). The .tplg file is normally part of the SOF firmware +release. + +SOF binary builds are available from: https://github.com/thesofproject/sof-bin/releases + +The main SOF source is here: https://github.com/thesofproject + +ALSA-ucm configurations +----------------------- +Typically an appropriate ALSA-ucm configuration file is needed for +use-case managers and audio servers such as PipeWire. + +Configuration files are available from the alsa-ucm-conf repository: +https://git.alsa-project.org/?p=alsa-ucm-conf.git + +Kernel log messages +=================== + +SoundWire +--------- +A successful initialization will look like this (this will be repeated for +each amplifier):: + + [ 7.568374] cs35l56 sdw:0:0:01fa:3556:01:0: supply VDD_P not found, using dummy regulator + [ 7.605208] cs35l56 sdw:0:0:01fa:3556:01:0: supply VDD_IO not found, using dummy regulator + [ 7.605313] cs35l56 sdw:0:0:01fa:3556:01:0: supply VDD_A not found, using dummy regulator + [ 7.939279] cs35l56 sdw:0:0:01fa:3556:01:0: Cirrus Logic CS35L56 Rev B0 OTP3 fw:3.4.4 (patched=0) + [ 7.947844] cs35l56 sdw:0:0:01fa:3556:01:0: Slave 4 state check1: UNATTACHED, status was 1 + [ 8.740280] cs35l56 sdw:0:0:01fa:3556:01:0: supply VDD_B not found, using dummy regulator + [ 8.740552] cs35l56 sdw:0:0:01fa:3556:01:0: supply VDD_AMP not found, using dummy regulator + [ 9.242164] cs35l56 sdw:0:0:01fa:3556:01:0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx.wmfw: format 3 timestamp 0x66b2b872 + [ 9.242173] cs35l56 sdw:0:0:01fa:3556:01:0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx.wmfw: Tue 05 Dec 2023 21:37:21 GMT Standard Time + [ 9.991709] cs35l56 sdw:0:0:01fa:3556:01:0: DSP1: Firmware: 1a00d6 vendor: 0x2 v3.11.23, 41 algorithms + [10.039098] cs35l56 sdw:0:0:01fa:3556:01:0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx-amp1.bin: v3.11.23 + [10.879235] cs35l56 sdw:0:0:01fa:3556:01:0: Slave 4 state check1: UNATTACHED, status was 1 + [11.401536] cs35l56 sdw:0:0:01fa:3556:01:0: Calibration applied + +HDA +--- +A successful initialization will look like this (this will be repeated for +each amplifier):: + + [ 6.306475] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: Cirrus Logic CS35L56 Rev B0 OTP3 fw:3.4.4 (patched=0) + [ 6.613892] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: DSP system name: 'xxxxxxxx', amp name: 'AMP1' + [ 8.266660] snd_hda_codec_cs8409 ehdaudio0D0: bound i2c-CSC3556:00-cs35l56-hda.0 (ops cs35l56_hda_comp_ops [snd_hda_scodec_cs35l56]) + [ 8.287525] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx.wmfw: format 3 timestamp 0x66b2b872 + [ 8.287528] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx.wmfw: Tue 05 Dec 2023 21:37:21 GMT Standard Time + [ 9.984335] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: DSP1: Firmware: 1a00d6 vendor: 0x2 v3.11.23, 41 algorithms + [10.085797] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx-amp1.bin: v3.11.23 + [10.655237] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: Calibration applied + +Important messages +~~~~~~~~~~~~~~~~~~ +Cirrus Logic CS35L56 Rev B0 OTP3 fw:3.4.4 (patched=0) + Shows that the driver has been able to read device ID registers from the + amplifier. + + * The actual amplifier type and silicon revision (CS35L56 B0 in this + example) is shown, as read from the amplifier identification registers. + * (patched=0) is normal, and indicates that the amplifier has been hard + reset and is running default ROM firmware. + * (patched=1) means that something has previously downloaded firmware + to the amplifier and the driver does not have control of the RESET + signal to be able to replace this preloaded firmware. This is normal + for systems where the BIOS downloads firmware to the amplifiers + before OS boot. + This status can also be seen if the cs35l56 kernel module is unloaded + and reloaded on a system where the driver does not have control of + RESET. SoundWire systems typically do not give the driver control of + RESET and only a BIOS (re)boot can reset the amplifiers. + +DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx.wmfw + Shows that a .wmfw firmware file was found and downloaded. + +DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx-amp1.bin + Shows that a .bin firmware file was found and downloaded. + +Calibration applied + Factory calibration data in EFI was written to the amplifier. + +Error messages +============== +This section explains some of the error messages that the driver can log. + +Algorithm coefficient version %d.%d.%d but expected %d.%d.%d + The version of the .bin file content does not match the loaded firmware. + Caused by mismatched .wmfw and .bin file, or .bin file was found but + .wmfw was not. + +No %s for algorithm %x + The version of the .bin file content does not match the loaded firmware. + Caused by mismatched .wmfw and .bin file, or .bin file was found but + .wmfw was not. + +.bin file required but not found + HDA driver did not find a .bin file that matches this hardware. + +Calibration disabled due to missing firmware controls + Driver was not able to write EFI calibration data to firmware registers. + This typically means that either: + + * The driver did not find a suitable wmfw for this hardware, or + * The amplifier has already been patched with firmware by something + previously, and the driver does not have control of a hard RESET line + to be able to reset the amplifier and download the firmware files it + found. This situation is indicated by the device identification + string in the kernel log shows "(patched=1)" + +Failed to write calibration + Same meaning and cause as "Calibration disabled due to missing firmware + controls" + +Failed to read calibration data from EFI + Factory calibration data in EFI is missing, empty or corrupt. + This is most likely to be cause by accidentally deleting the file from + the EFI filesystem. + +No calibration for silicon ID + The factory calibration data in EFI does not match this hardware. + The most likely cause is that an amplifier has been replaced on the + motherboard without going through manufacturer calibration process to + generate calibration data for the new amplifier. + +Did not find any buses for CSCxxxx + Only on HDA systems. The HDA codec driver found an ACPI entry for + Cirrus Logic companion amps, but could not enumerate the ACPI entries for + the I2C/SPI buses. The most likely cause of this is that: + + * The relevant bus driver (I2C or SPI) is not part of the kernel. + * The HDA codec driver was built-in to the kernel but the I2C/SPI + bus driver is a module and so the HDA codec driver cannot call the + bus driver functions. + +init_completion timed out + The SoundWire bus controller (host end) did not enumerate the amplifier. + In other words, the ACPI says there is an amplifier but for some reason + it was not detected on the bus. + +No AF01 node + Indicates an error in ACPI. A SoundWire system should have a Device() + node named "AF01" but it was not found. + +Failed to get spk-id-gpios + ACPI says that the driver should request a GPIO but the driver was not + able to get that GPIO. The most likely cause is that the kernel does not + include the correct GPIO or PINCTRL driver for this system. + +Failed to read spk-id + ACPI says that the driver should request a GPIO but the driver was not + able to read that GPIO. + +Unexpected spk-id element count + AF01 contains more speaker ID GPIO entries than the driver supports + +Overtemp error + Amplifier overheat protection was triggered and the amplifier shut down + to protect itself. + +Amp short error + Amplifier detected a short-circuit on the speaker output pins and shut + down for protection. This would normally indicate a damaged speaker. + +Hibernate wake failed + The driver tried to wake the amplifier from its power-saving state but + did not see the expected responses from the amplifier. This can be caused + by using firmware that does not match the hardware. diff --git a/Documentation/sound/codecs/index.rst b/Documentation/sound/codecs/index.rst new file mode 100644 index 000000000000..2cb95d87bbef --- /dev/null +++ b/Documentation/sound/codecs/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Codec-Specific Information +========================== + +.. toctree:: + :maxdepth: 2 + + cs35l56 diff --git a/MAINTAINERS b/MAINTAINERS index d09d814b2351..6a9507ce371f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4556,6 +4556,7 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: patches@opensource.cirrus.com S: Maintained F: Documentation/devicetree/bindings/sound/cirrus,cs* +F: Documentation/sound/codecs/cs* F: drivers/mfd/cs42l43* F: drivers/pinctrl/cirrus/pinctrl-cs42l43* F: include/dt-bindings/sound/cs* From e4e25b70ba0cd6e0f8651d28d50398885c4c99a2 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:56 +0100 Subject: [PATCH 250/256] ALSA: doc: Add codecs/index.rst to top-level index JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 080505f3c6c3fa5560f3b84249875fd26229124c Author: Richard Fitzgerald Date: Thu Jan 9 10:56:57 2025 +0000 ALSA: doc: Add codecs/index.rst to top-level index commit 088fb4ee17fc ("ALSA: doc: cs35l56: Add information about Cirrus Logic CS35L54/56/57") added a new subdirectory with an index file, so this file must be added to the top-level index. Fixes: 088fb4ee17fc ("ALSA: doc: cs35l56: Add information about Cirrus Logic CS35L54/56/57") Signed-off-by: Richard Fitzgerald Link: https://patch.msgid.link/20250109105657.96860-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- Documentation/sound/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/sound/index.rst b/Documentation/sound/index.rst index c437f2a4bc85..51cd736f65b5 100644 --- a/Documentation/sound/index.rst +++ b/Documentation/sound/index.rst @@ -13,6 +13,7 @@ Sound Subsystem Documentation alsa-configuration hd-audio/index cards/index + codecs/index utimers .. only:: subproject and html From caaf1ec343594bfb7ff6376bafd80699cf2fd5c5 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:49:56 +0100 Subject: [PATCH 251/256] ASoC: cs42l43: Add codec force suspend/resume ops JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 8f0defd2e52d22eb994d7e770b1261caa24917d8 Author: Maciej Strozek Date: Thu Jan 9 09:38:22 2025 +0000 ASoC: cs42l43: Add codec force suspend/resume ops This ensures codec will resume after suspending during playback. Signed-off-by: Maciej Strozek Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250109093822.5745-1-mstrozek@opensource.cirrus.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/cs42l43.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c index acb0a9187ead..1004f91f2d29 100644 --- a/sound/soc/codecs/cs42l43.c +++ b/sound/soc/codecs/cs42l43.c @@ -2406,6 +2406,7 @@ static int cs42l43_codec_runtime_resume(struct device *dev) static const struct dev_pm_ops cs42l43_codec_pm_ops = { RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static const struct platform_device_id cs42l43_codec_id_table[] = { From d623766119de24f3d58c3a204a236784b79d4d37 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:50:08 +0100 Subject: [PATCH 252/256] ALSA: hda/realtek: Fix volume adjustment issue on Lenovo ThinkBook 16P Gen5 JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 34c8e74cd6667ef5da90d448a1af702c4b873bd3 Author: Yage Geng Date: Mon Jan 13 16:52:08 2025 +0800 ALSA: hda/realtek: Fix volume adjustment issue on Lenovo ThinkBook 16P Gen5 This patch fixes the volume adjustment issue on the Lenovo ThinkBook 16P Gen5 by applying the necessary quirk configuration for the Realtek ALC287 codec. The issue was caused by incorrect configuration in the driver, which prevented proper volume control on certain systems. Signed-off-by: Yage Geng Link: https://patch.msgid.link/20250113085208.15351-1-icoderdev@gmail.com Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_realtek.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 82e212cc736c..6245f297996f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10946,8 +10946,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x38e0, "Yoga Y990 Intel VECO Dual", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x38f8, "Yoga Book 9i", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x38df, "Y990 YG DUAL", ALC287_FIXUP_TAS2781_I2C), - SND_PCI_QUIRK(0x17aa, 0x38f9, "Thinkbook 16P Gen5", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x17aa, 0x38fa, "Thinkbook 16P Gen5", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x17aa, 0x38f9, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), + SND_PCI_QUIRK(0x17aa, 0x38fa, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC), From b20826be125fb079ef92e2e21494b564c41f2863 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 13:50:08 +0100 Subject: [PATCH 253/256] ASoC: simple-card-utils: fix priv->dai_props indexing JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 04e97fa7dd7e3eda754712f92df2136acd1d9088 Author: Laurentiu Mihalcea Date: Tue Jan 14 13:43:14 2025 -0500 ASoC: simple-card-utils: fix priv->dai_props indexing As of commit cb18cd26039f ("ASoC: soc-core: do rtd->id trick at snd_soc_add_pcm_runtime()") the ID stored in the PCM runtime data can no longer be safely used to index the priv->dai_props array. This is because the ID may be modified during snd_soc_add_pcm_runtime(), thus resulting in an ID that's no longer a valid array index. To fix this, use the position of the dai_link stored inside the PCM runtime data relative to the start of the dai_link array as index into the priv->dai_props array. Signed-off-by: Laurentiu Mihalcea Acked-by: Kuninori Morimoto Link: https://patch.msgid.link/20250114184314.3583-2-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- include/sound/simple_card_utils.h | 7 +++++++ sound/soc/generic/simple-card-utils.c | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index dc4c1cf4472a..a8e04430d501 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -89,6 +89,13 @@ struct simple_util_priv { #define simple_props_to_dai_codec(props, i) ((props)->codec_dai + i) #define simple_props_to_codec_conf(props, i) ((props)->codec_conf + i) +/* has the same effect as simple_priv_to_props(). Preferred over + * simple_priv_to_props() when dealing with PCM runtime data as + * the ID stored in rtd->id may not be a valid array index. + */ +#define runtime_simple_priv_to_props(priv, rtd) \ + ((priv)->dai_props + ((rtd)->dai_link - (priv)->dai_link)) + #define for_each_prop_dlc_cpus(props, i, cpu) \ for ((i) = 0; \ ((i) < (props)->num.cpus) && \ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index fcd789c498e2..2323b1924acb 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -296,7 +296,7 @@ int simple_util_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id); + struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd); struct simple_util_dai *dai; unsigned int fixed_sysclk = 0; int i1, i2, i; @@ -357,7 +357,7 @@ void simple_util_shutdown(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id); + struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd); struct simple_util_dai *dai; int i; @@ -448,7 +448,7 @@ int simple_util_hw_params(struct snd_pcm_substream *substream, struct simple_util_dai *pdai; struct snd_soc_dai *sdai; struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id); + struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd); unsigned int mclk, mclk_fs = 0; int i, ret; @@ -517,7 +517,7 @@ int simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->id); + struct simple_dai_props *dai_props = runtime_simple_priv_to_props(priv, rtd); struct simple_util_data *data = &dai_props->adata; struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); @@ -628,7 +628,7 @@ static int simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd) { struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id); + struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd); struct simple_util_dai *dai; int i, ret; From 1a6c53bab0155338a09221bff0b5f651ea935f39 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 15:01:02 +0100 Subject: [PATCH 254/256] ASoC: tegra: Fix ADX S24_LE audio format JIRA: https://issues.redhat.com/browse/RHEL-80681 commit 3d6c9dd4cb3013fe83524949b914f1497855e3de Author: Thorsten Blum Date: Sat Feb 22 23:56:59 2025 +0100 ASoC: tegra: Fix ADX S24_LE audio format Commit 4204eccc7b2a ("ASoC: tegra: Add support for S24_LE audio format") added support for the S24_LE audio format, but duplicated S16_LE in OUT_DAI() for ADX instead. Fix this by adding support for the S24_LE audio format. Compile-tested only. Cc: stable@vger.kernel.org Fixes: 4204eccc7b2a ("ASoC: tegra: Add support for S24_LE audio format") Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250222225700.539673-2-thorsten.blum@linux.dev Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/tegra/tegra210_adx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c index b080e1303b4a..ed5e6f0477d5 100644 --- a/sound/soc/tegra/tegra210_adx.c +++ b/sound/soc/tegra/tegra210_adx.c @@ -264,7 +264,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .capture = { \ @@ -274,7 +274,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = { .rates = SNDRV_PCM_RATE_8000_192000, \ .formats = SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE, \ }, \ .ops = &tegra210_adx_out_dai_ops, \ From 711f5a74565cdd331e68e8ccc64edf61db52aaca Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 17 Mar 2025 14:24:40 +0100 Subject: [PATCH 255/256] ASoC: use playback_only/capture_only instead dpcm_playback/dpcm_capture flags JIRA: https://issues.redhat.com/browse/RHEL-80681 Upstream-status: RHEL-only The former flags were obsoleted in upstream commit c7ae6551533e7c7bf903a2d259044778f4b103ce ("ASoC: soc-pcm: remove dpcm_xxx flags"). Signed-off-by: Jaroslav Kysela --- sound/soc/intel/boards/bxt_da7219_max98357a.c | 32 +++++----- sound/soc/intel/boards/bxt_rt298.c | 28 ++++----- sound/soc/intel/boards/cml_rt1011_rt5682.c | 18 +++--- sound/soc/intel/boards/glk_rt5682_max98357a.c | 32 +++++----- sound/soc/intel/boards/kbl_da7219_max98357a.c | 28 ++++----- sound/soc/intel/boards/kbl_da7219_max98927.c | 60 +++++++++---------- sound/soc/intel/boards/kbl_rt5660.c | 20 +++---- sound/soc/intel/boards/kbl_rt5663_max98927.c | 48 +++++++-------- .../intel/boards/kbl_rt5663_rt5514_max98927.c | 26 ++++---- .../soc/intel/boards/skl_nau88l25_max98357a.c | 28 ++++----- sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 30 +++++----- sound/soc/intel/boards/skl_rt286.c | 28 ++++----- 12 files changed, 189 insertions(+), 189 deletions(-) diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 2ce2bf0e65f3..da85873a2c19 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -470,7 +470,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .init = broxton_da7219_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &broxton_da7219_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -482,7 +482,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, .ops = &broxton_da7219_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -493,7 +493,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &broxton_da7219_fe_ops, SND_SOC_DAILINK_REG(system2, dummy, platform), }, @@ -502,7 +502,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .name = "Bxt Audio Reference cap", .stream_name = "Refcap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &broxton_refcap_ops, @@ -513,7 +513,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .name = "Bxt Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &broxton_dmic_ops, @@ -523,7 +523,7 @@ static struct snd_soc_dai_link broxton_dais[] = { { .name = "Bxt HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -533,7 +533,7 @@ static struct snd_soc_dai_link broxton_dais[] = { { .name = "Bxt HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -543,7 +543,7 @@ static struct snd_soc_dai_link broxton_dais[] = { { .name = "Bxt HDMI Port3", .stream_name = "Hdmi3", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -560,7 +560,7 @@ static struct snd_soc_dai_link broxton_dais[] = { SND_SOC_DAIFMT_CBC_CFC, .ignore_pmdown_time = 1, .be_hw_params_fixup = broxton_ssp_fixup, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform), }, { @@ -573,8 +573,8 @@ static struct snd_soc_dai_link broxton_dais[] = { SND_SOC_DAIFMT_CBC_CFC, .ignore_pmdown_time = 1, .be_hw_params_fixup = broxton_ssp_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { @@ -582,7 +582,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .id = 2, .ignore_suspend = 1, .be_hw_params_fixup = broxton_dmic_fixup, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, @@ -590,7 +590,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .name = "iDisp1", .id = 3, .init = broxton_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, @@ -598,7 +598,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .name = "iDisp2", .id = 4, .init = broxton_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -606,7 +606,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .name = "iDisp3", .id = 5, .init = broxton_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, @@ -614,7 +614,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .name = "dmic16k", .id = 6, .be_hw_params_fixup = broxton_dmic_fixup, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), }, diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 6da1517c53c6..4e65ad6393aa 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -394,7 +394,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .dynamic = 1, .init = broxton_rt298_fe_init, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &broxton_rt286_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -405,7 +405,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .nonatomic = 1, .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, .ops = &broxton_rt286_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -414,7 +414,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .name = "Bxt Audio Reference cap", .stream_name = "refcap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, SND_SOC_DAILINK_REG(reference, dummy, platform), @@ -424,7 +424,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .name = "Bxt Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &broxton_dmic_ops, @@ -434,7 +434,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { { .name = "Bxt HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -444,7 +444,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { { .name = "Bxt HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -454,7 +454,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { { .name = "Bxt HDMI Port3", .stream_name = "Hdmi3", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -472,8 +472,8 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = broxton_ssp5_fixup, .ops = &broxton_rt298_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform), }, { @@ -481,7 +481,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .id = 1, .be_hw_params_fixup = broxton_dmic_fixup, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, @@ -490,7 +490,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .id = 2, .be_hw_params_fixup = broxton_dmic_fixup, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform), }, @@ -498,7 +498,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .name = "iDisp1", .id = 3, .init = broxton_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, @@ -506,7 +506,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .name = "iDisp2", .id = 4, .init = broxton_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -514,7 +514,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .name = "iDisp3", .id = 5, .init = broxton_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c index 679a09b63ea5..3cf8e68f357f 100644 --- a/sound/soc/intel/boards/cml_rt1011_rt5682.c +++ b/sound/soc/intel/boards/cml_rt1011_rt5682.c @@ -443,8 +443,8 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .exit = cml_rt5682_codec_exit, .ignore_pmdown_time = 1, .ops = &cml_rt5682_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, @@ -452,7 +452,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .name = "dmic01", .id = 1, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, @@ -460,7 +460,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .name = "dmic16k", .id = 2, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), }, @@ -468,7 +468,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .name = "iDisp1", .id = 3, .init = hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, @@ -476,7 +476,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .name = "iDisp2", .id = 4, .init = hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -484,7 +484,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .name = "iDisp3", .id = 5, .init = hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, @@ -496,8 +496,8 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { */ .name = "SSP1-Codec", .id = 6, - .dpcm_playback = 1, - .dpcm_capture = 1, /* Capture stream provides Feedback */ + .playback_only = 1, + .capture_only = 1, /* Capture stream provides Feedback */ .no_pcm = 1, .init = cml_rt1011_spk_init, .ops = &cml_rt1011_ops, diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c index 4098b2d32f9b..ed3a6015fd31 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -413,7 +413,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { .init = geminilake_rt5682_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(system, dummy, platform), }, [GLK_DPCM_AUDIO_CP] = { @@ -423,13 +423,13 @@ static struct snd_soc_dai_link geminilake_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(system, dummy, platform), }, [GLK_DPCM_AUDIO_HS_PB] = { .name = "Glk Audio Headset Playback", .stream_name = "Headset Audio", - .dpcm_playback = 1, + .playback_only = 1, .nonatomic = 1, .dynamic = 1, SND_SOC_DAILINK_REG(system2, dummy, platform), @@ -438,7 +438,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { .name = "Glk Audio Echo Reference cap", .stream_name = "Echoreference Capture", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, SND_SOC_DAILINK_REG(echoref, dummy, platform), @@ -447,7 +447,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { .name = "Glk Audio Reference cap", .stream_name = "Refcap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &geminilake_refcap_ops, @@ -457,7 +457,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { .name = "Glk Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &geminilake_dmic_ops, @@ -466,7 +466,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { [GLK_DPCM_AUDIO_HDMI1_PB] = { .name = "Glk HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -477,7 +477,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { [GLK_DPCM_AUDIO_HDMI2_PB] = { .name = "Glk HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -490,7 +490,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { .stream_name = "Hdmi3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -507,7 +507,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { SND_SOC_DAIFMT_CBC_CFC, .ignore_pmdown_time = 1, .be_hw_params_fixup = geminilake_ssp_fixup, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { @@ -521,8 +521,8 @@ static struct snd_soc_dai_link geminilake_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = geminilake_ssp_fixup, .ops = &geminilake_rt5682_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp2_pin, ssp2_codec_5682, platform), }, { @@ -530,7 +530,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { .id = 2, .ignore_suspend = 1, .be_hw_params_fixup = geminilake_dmic_fixup, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, @@ -538,7 +538,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { .name = "iDisp1", .id = 3, .init = geminilake_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, @@ -546,7 +546,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { .name = "iDisp2", .id = 4, .init = geminilake_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -554,7 +554,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { .name = "iDisp3", .id = 5, .init = geminilake_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c index 154f6a74ed15..a798c5c766c6 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c @@ -460,7 +460,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .init = kabylake_da7219_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &kabylake_da7219_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -471,7 +471,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, .ops = &kabylake_da7219_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -479,7 +479,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "Kbl Audio Reference cap", .stream_name = "Wake on Voice", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, @@ -489,7 +489,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &kabylake_dmic_ops, @@ -498,7 +498,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -509,7 +509,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -522,7 +522,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .stream_name = "Hdmi3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -540,7 +540,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { SND_SOC_DAIFMT_CBC_CFC, .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { @@ -553,8 +553,8 @@ static struct snd_soc_dai_link kabylake_dais[] = { SND_SOC_DAIFMT_CBC_CFC, .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { @@ -562,14 +562,14 @@ static struct snd_soc_dai_link kabylake_dais[] = { .id = 2, .be_hw_params_fixup = kabylake_dmic_fixup, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .dpcm_playback = 1, + .playback_only = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), @@ -578,7 +578,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "iDisp2", .id = 4, .init = kabylake_hdmi2_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -586,7 +586,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "iDisp3", .id = 5, .init = kabylake_hdmi3_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index 02ed77a07e23..4e2695784228 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -686,7 +686,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .init = kabylake_da7219_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &kabylake_da7219_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -694,7 +694,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "Kbl Audio Echo Reference cap", .stream_name = "Echoreference Capture", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, SND_SOC_DAILINK_REG(echoref, dummy, platform), }, @@ -702,7 +702,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "Kbl Audio Reference cap", .stream_name = "Wake on Voice", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, @@ -712,7 +712,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &kabylake_dmic_ops, @@ -721,7 +721,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -732,7 +732,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -745,7 +745,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .stream_name = "Hdmi3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -754,7 +754,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { [KBL_DPCM_AUDIO_HS_PB] = { .name = "Kbl Audio Headset Playback", .stream_name = "Headset Audio", - .dpcm_playback = 1, + .playback_only = 1, .nonatomic = 1, .dynamic = 1, .init = kabylake_da7219_fe_init, @@ -770,7 +770,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, .ops = &kabylake_da7219_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -784,8 +784,8 @@ static struct snd_soc_dai_link kabylake_dais[] = { .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, .ops = &kabylake_ssp0_ops, @@ -801,8 +801,8 @@ static struct snd_soc_dai_link kabylake_dais[] = { SND_SOC_DAIFMT_CBC_CFC, .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { @@ -811,14 +811,14 @@ static struct snd_soc_dai_link kabylake_dais[] = { .init = kabylake_dmic_init, .be_hw_params_fixup = kabylake_dmic_fixup, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .dpcm_playback = 1, + .playback_only = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), @@ -827,7 +827,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "iDisp2", .id = 4, .init = kabylake_hdmi2_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -835,7 +835,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "iDisp3", .id = 5, .init = kabylake_hdmi3_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, @@ -852,7 +852,7 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { .init = kabylake_da7219_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &kabylake_da7219_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -860,7 +860,7 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { .name = "Kbl Audio Echo Reference cap", .stream_name = "Echoreference Capture", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, SND_SOC_DAILINK_REG(echoref, dummy, platform), }, @@ -868,7 +868,7 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { .name = "Kbl Audio Reference cap", .stream_name = "Wake on Voice", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, @@ -878,7 +878,7 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &kabylake_dmic_ops, @@ -887,7 +887,7 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -898,7 +898,7 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -911,7 +911,7 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { .stream_name = "Hdmi3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -927,8 +927,8 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, .ops = &kabylake_ssp0_ops, @@ -940,14 +940,14 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { .init = kabylake_dmic_init, .be_hw_params_fixup = kabylake_dmic_fixup, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 2, - .dpcm_playback = 1, + .playback_only = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), @@ -956,7 +956,7 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { .name = "iDisp2", .id = 3, .init = kabylake_hdmi2_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -964,7 +964,7 @@ static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { .name = "iDisp3", .id = 4, .init = kabylake_hdmi3_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c index 66885cb36f24..fcf92fb9b5c9 100644 --- a/sound/soc/intel/boards/kbl_rt5660.c +++ b/sound/soc/intel/boards/kbl_rt5660.c @@ -377,7 +377,7 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &kabylake_rt5660_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -388,14 +388,14 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, .ops = &kabylake_rt5660_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -406,7 +406,7 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -419,7 +419,7 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { .stream_name = "Hdmi3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -440,14 +440,14 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp0_fixup, .ops = &kabylake_rt5660_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { .name = "iDisp1", .id = 1, - .dpcm_playback = 1, + .playback_only = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), @@ -456,7 +456,7 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { .name = "iDisp2", .id = 2, .init = kabylake_hdmi2_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -464,7 +464,7 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { .name = "iDisp3", .id = 3, .init = kabylake_hdmi3_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 9da89436a917..10898b69adc0 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -687,7 +687,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .init = kabylake_rt5663_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &kabylake_rt5663_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -698,14 +698,14 @@ static struct snd_soc_dai_link kabylake_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, .ops = &kabylake_rt5663_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_HS_PB] = { .name = "Kbl Audio Headset Playback", .stream_name = "Headset Audio", - .dpcm_playback = 1, + .playback_only = 1, .nonatomic = 1, .dynamic = 1, SND_SOC_DAILINK_REG(system2, dummy, platform), @@ -714,7 +714,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "Kbl Audio Echo Reference cap", .stream_name = "Echoreference Capture", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, SND_SOC_DAILINK_REG(echoref, dummy, platform), }, @@ -722,7 +722,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "Kbl Audio Reference cap", .stream_name = "Wake on Voice", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, @@ -732,7 +732,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &kabylake_dmic_ops, @@ -741,7 +741,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -752,7 +752,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -765,7 +765,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .stream_name = "Hdmi3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -783,7 +783,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { SND_SOC_DAIFMT_CBC_CFC, .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, - .dpcm_playback = 1, + .playback_only = 1, .ops = &kabylake_ssp0_ops, SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, @@ -798,8 +798,8 @@ static struct snd_soc_dai_link kabylake_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, .ops = &kabylake_rt5663_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { @@ -807,14 +807,14 @@ static struct snd_soc_dai_link kabylake_dais[] = { .id = 2, .be_hw_params_fixup = kabylake_dmic_fixup, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .dpcm_playback = 1, + .playback_only = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), @@ -823,7 +823,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "iDisp2", .id = 4, .init = kabylake_hdmi2_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -831,7 +831,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "iDisp3", .id = 5, .init = kabylake_hdmi3_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, @@ -846,7 +846,7 @@ static struct snd_soc_dai_link kabylake_5663_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &kabylake_rt5663_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -857,14 +857,14 @@ static struct snd_soc_dai_link kabylake_5663_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, .ops = &kabylake_rt5663_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_5663_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -875,7 +875,7 @@ static struct snd_soc_dai_link kabylake_5663_dais[] = { [KBL_DPCM_AUDIO_5663_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -896,14 +896,14 @@ static struct snd_soc_dai_link kabylake_5663_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, .ops = &kabylake_rt5663_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { .name = "iDisp1", .id = 1, - .dpcm_playback = 1, + .playback_only = 1, .init = kabylake_5663_hdmi1_init, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), @@ -912,7 +912,7 @@ static struct snd_soc_dai_link kabylake_5663_dais[] = { .name = "iDisp2", .id = 2, .init = kabylake_5663_hdmi2_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index a32ce8f972f3..9505e2b09cfa 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -575,7 +575,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .init = kabylake_rt5663_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &kabylake_rt5663_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -586,14 +586,14 @@ static struct snd_soc_dai_link kabylake_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, .ops = &kabylake_rt5663_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, [KBL_DPCM_AUDIO_HS_PB] = { .name = "Kbl Audio Headset Playback", .stream_name = "Headset Audio", - .dpcm_playback = 1, + .playback_only = 1, .nonatomic = 1, .dynamic = 1, SND_SOC_DAILINK_REG(system2, dummy, platform), @@ -602,7 +602,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "Kbl Audio Echo Reference cap", .stream_name = "Echoreference Capture", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, SND_SOC_DAILINK_REG(echoref, dummy, platform), }, @@ -615,7 +615,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &kabylake_dmic_ops, @@ -624,7 +624,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { [KBL_DPCM_AUDIO_HDMI1_PB] = { .name = "Kbl HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -635,7 +635,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { [KBL_DPCM_AUDIO_HDMI2_PB] = { .name = "Kbl HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -655,8 +655,8 @@ static struct snd_soc_dai_link kabylake_dais[] = { SND_SOC_DAIFMT_CBC_CFC, .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, .ops = &kabylake_ssp0_ops, SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, @@ -670,14 +670,14 @@ static struct snd_soc_dai_link kabylake_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = kabylake_ssp_fixup, .ops = &kabylake_rt5663_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { .name = "iDisp1", .id = 3, - .dpcm_playback = 1, + .playback_only = 1, .init = kabylake_hdmi1_init, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), @@ -686,7 +686,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .name = "iDisp2", .id = 4, .init = kabylake_hdmi2_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index 91fe9834aab4..6d2e6f45fd0f 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -474,7 +474,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .init = skylake_nau8825_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &skylake_nau8825_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -485,7 +485,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, .ops = &skylake_nau8825_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -493,7 +493,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .name = "Skl Audio Reference cap", .stream_name = "Wake on Voice", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, @@ -503,7 +503,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .name = "Skl Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_dmic_ops, @@ -512,7 +512,7 @@ static struct snd_soc_dai_link skylake_dais[] = { [SKL_DPCM_AUDIO_HDMI1_PB] = { .name = "Skl HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -523,7 +523,7 @@ static struct snd_soc_dai_link skylake_dais[] = { [SKL_DPCM_AUDIO_HDMI2_PB] = { .name = "Skl HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -536,7 +536,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .stream_name = "Hdmi3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -554,7 +554,7 @@ static struct snd_soc_dai_link skylake_dais[] = { SND_SOC_DAIFMT_CBC_CFC, .ignore_pmdown_time = 1, .be_hw_params_fixup = skylake_ssp_fixup, - .dpcm_playback = 1, + .playback_only = 1, SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { @@ -568,8 +568,8 @@ static struct snd_soc_dai_link skylake_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = skylake_ssp_fixup, .ops = &skylake_nau8825_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { @@ -577,14 +577,14 @@ static struct snd_soc_dai_link skylake_dais[] = { .id = 2, .be_hw_params_fixup = skylake_dmic_fixup, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .dpcm_playback = 1, + .playback_only = 1, .init = skylake_hdmi1_init, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), @@ -593,7 +593,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .name = "iDisp2", .id = 4, .init = skylake_hdmi2_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -601,7 +601,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .name = "iDisp3", .id = 5, .init = skylake_hdmi3_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index d53bf3516c0d..bb705667da8b 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -513,7 +513,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .init = skylake_nau8825_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .ops = &skylake_nau8825_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -524,7 +524,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .nonatomic = 1, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, + .capture_only = 1, .ops = &skylake_nau8825_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -532,7 +532,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .name = "Skl Audio Reference cap", .stream_name = "Wake on Voice", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_refcap_ops, @@ -542,7 +542,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .name = "Skl Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_dmic_ops, @@ -551,7 +551,7 @@ static struct snd_soc_dai_link skylake_dais[] = { [SKL_DPCM_AUDIO_HDMI1_PB] = { .name = "Skl HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -562,7 +562,7 @@ static struct snd_soc_dai_link skylake_dais[] = { [SKL_DPCM_AUDIO_HDMI2_PB] = { .name = "Skl HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, @@ -575,7 +575,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .stream_name = "Hdmi3", .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -594,8 +594,8 @@ static struct snd_soc_dai_link skylake_dais[] = { .init = skylake_ssm4567_codec_init, .ignore_pmdown_time = 1, .be_hw_params_fixup = skylake_ssp_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { @@ -609,8 +609,8 @@ static struct snd_soc_dai_link skylake_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = skylake_ssp_fixup, .ops = &skylake_nau8825_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), }, { @@ -618,14 +618,14 @@ static struct snd_soc_dai_link skylake_dais[] = { .id = 2, .ignore_suspend = 1, .be_hw_params_fixup = skylake_dmic_fixup, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform), }, { .name = "iDisp1", .id = 3, - .dpcm_playback = 1, + .playback_only = 1, .init = skylake_hdmi1_init, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), @@ -634,7 +634,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .name = "iDisp2", .id = 4, .init = skylake_hdmi2_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -642,7 +642,7 @@ static struct snd_soc_dai_link skylake_dais[] = { .name = "iDisp3", .id = 5, .init = skylake_hdmi3_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 3ea03f814403..18ecd82abaa1 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -348,7 +348,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST }, - .dpcm_playback = 1, + .playback_only = 1, .ops = &skylake_rt286_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -361,7 +361,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST }, - .dpcm_playback = 1, + .playback_only = 1, .ops = &skylake_rt286_fe_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -374,7 +374,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST }, - .dpcm_capture = 1, + .capture_only = 1, .ops = &skylake_rt286_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, @@ -382,7 +382,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .name = "Skl Audio Reference cap", .stream_name = "refcap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, SND_SOC_DAILINK_REG(reference, dummy, platform), @@ -391,7 +391,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .name = "Skl Audio DMIC cap", .stream_name = "dmiccap", .init = NULL, - .dpcm_capture = 1, + .capture_only = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_dmic_ops, @@ -400,7 +400,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { [SKL_DPCM_AUDIO_HDMI1_PB] = { .name = "Skl HDMI Port1", .stream_name = "Hdmi1", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -409,7 +409,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { [SKL_DPCM_AUDIO_HDMI2_PB] = { .name = "Skl HDMI Port2", .stream_name = "Hdmi2", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -418,7 +418,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { [SKL_DPCM_AUDIO_HDMI3_PB] = { .name = "Skl HDMI Port3", .stream_name = "Hdmi3", - .dpcm_playback = 1, + .playback_only = 1, .init = NULL, .nonatomic = 1, .dynamic = 1, @@ -438,8 +438,8 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .ignore_pmdown_time = 1, .be_hw_params_fixup = skylake_ssp0_fixup, .ops = &skylake_rt286_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, + .playback_only = 1, + .capture_only = 1, SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), }, { @@ -447,7 +447,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .id = 1, .be_hw_params_fixup = skylake_dmic_fixup, .ignore_suspend = 1, - .dpcm_capture = 1, + .capture_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform), }, @@ -455,7 +455,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .name = "iDisp1", .id = 2, .init = skylake_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), }, @@ -463,7 +463,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .name = "iDisp2", .id = 3, .init = skylake_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), }, @@ -471,7 +471,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .name = "iDisp3", .id = 4, .init = skylake_hdmi_init, - .dpcm_playback = 1, + .playback_only = 1, .no_pcm = 1, SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), }, From 57ef1d5d9c74b339a6da125a98f687152a4c0f74 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 12 Mar 2025 17:39:11 +0100 Subject: [PATCH 256/256] ALSA: update RHEL kconfigs for 6.13 upstream code JIRA: https://issues.redhat.com/browse/RHEL-80681 Upstream-status: RHEL-only Add rhel/generic:CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH=n Add rhel/generic/x86:CONFIG_SND_SOC_RT721_SDCA_SDW=m Add common/generic:CONFIG_SND_SOC_ADAU1373=n Add common/generic:CONFIG_SND_SOC_AW88081=n Add common/generic:CONFIG_SND_SOC_CS42L84=n Add common/generic:CONFIG_SND_SOC_ES8323=n Add common/generic:CONFIG_SND_SOC_SMA1307=n Add common/generic:CONFIG_SND_SOC_UDA1342=n Add common/generic:CONFIG_SND_SOC_NTP8918=n Add common/generic:CONFIG_SND_SOC_NTP8835=n Signed-off-by: Jaroslav Kysela --- redhat/configs/common/generic/CONFIG_SND_SOC_ADAU1373 | 1 + redhat/configs/common/generic/CONFIG_SND_SOC_AW88081 | 1 + redhat/configs/common/generic/CONFIG_SND_SOC_CS42L84 | 1 + redhat/configs/common/generic/CONFIG_SND_SOC_ES8323 | 1 + redhat/configs/common/generic/CONFIG_SND_SOC_NTP8835 | 1 + redhat/configs/common/generic/CONFIG_SND_SOC_NTP8918 | 1 + redhat/configs/common/generic/CONFIG_SND_SOC_SMA1307 | 1 + redhat/configs/common/generic/CONFIG_SND_SOC_UDA1342 | 1 + redhat/configs/rhel/generic/CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH | 1 + redhat/configs/rhel/generic/x86/CONFIG_SND_SOC_RT721_SDCA_SDW | 1 + 10 files changed, 10 insertions(+) create mode 100644 redhat/configs/common/generic/CONFIG_SND_SOC_ADAU1373 create mode 100644 redhat/configs/common/generic/CONFIG_SND_SOC_AW88081 create mode 100644 redhat/configs/common/generic/CONFIG_SND_SOC_CS42L84 create mode 100644 redhat/configs/common/generic/CONFIG_SND_SOC_ES8323 create mode 100644 redhat/configs/common/generic/CONFIG_SND_SOC_NTP8835 create mode 100644 redhat/configs/common/generic/CONFIG_SND_SOC_NTP8918 create mode 100644 redhat/configs/common/generic/CONFIG_SND_SOC_SMA1307 create mode 100644 redhat/configs/common/generic/CONFIG_SND_SOC_UDA1342 create mode 100644 redhat/configs/rhel/generic/CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH create mode 100644 redhat/configs/rhel/generic/x86/CONFIG_SND_SOC_RT721_SDCA_SDW diff --git a/redhat/configs/common/generic/CONFIG_SND_SOC_ADAU1373 b/redhat/configs/common/generic/CONFIG_SND_SOC_ADAU1373 new file mode 100644 index 000000000000..5b1fee14845c --- /dev/null +++ b/redhat/configs/common/generic/CONFIG_SND_SOC_ADAU1373 @@ -0,0 +1 @@ +# CONFIG_SND_SOC_ADAU1373 is not set diff --git a/redhat/configs/common/generic/CONFIG_SND_SOC_AW88081 b/redhat/configs/common/generic/CONFIG_SND_SOC_AW88081 new file mode 100644 index 000000000000..8ad524a7ce10 --- /dev/null +++ b/redhat/configs/common/generic/CONFIG_SND_SOC_AW88081 @@ -0,0 +1 @@ +# CONFIG_SND_SOC_AW88081 is not set diff --git a/redhat/configs/common/generic/CONFIG_SND_SOC_CS42L84 b/redhat/configs/common/generic/CONFIG_SND_SOC_CS42L84 new file mode 100644 index 000000000000..910524657aa6 --- /dev/null +++ b/redhat/configs/common/generic/CONFIG_SND_SOC_CS42L84 @@ -0,0 +1 @@ +# CONFIG_SND_SOC_CS42L84 is not set diff --git a/redhat/configs/common/generic/CONFIG_SND_SOC_ES8323 b/redhat/configs/common/generic/CONFIG_SND_SOC_ES8323 new file mode 100644 index 000000000000..37814a034f49 --- /dev/null +++ b/redhat/configs/common/generic/CONFIG_SND_SOC_ES8323 @@ -0,0 +1 @@ +# CONFIG_SND_SOC_ES8323 is not set diff --git a/redhat/configs/common/generic/CONFIG_SND_SOC_NTP8835 b/redhat/configs/common/generic/CONFIG_SND_SOC_NTP8835 new file mode 100644 index 000000000000..6af470816e74 --- /dev/null +++ b/redhat/configs/common/generic/CONFIG_SND_SOC_NTP8835 @@ -0,0 +1 @@ +# CONFIG_SND_SOC_NTP8835 is not set diff --git a/redhat/configs/common/generic/CONFIG_SND_SOC_NTP8918 b/redhat/configs/common/generic/CONFIG_SND_SOC_NTP8918 new file mode 100644 index 000000000000..41efebbf1403 --- /dev/null +++ b/redhat/configs/common/generic/CONFIG_SND_SOC_NTP8918 @@ -0,0 +1 @@ +# CONFIG_SND_SOC_NTP8918 is not set diff --git a/redhat/configs/common/generic/CONFIG_SND_SOC_SMA1307 b/redhat/configs/common/generic/CONFIG_SND_SOC_SMA1307 new file mode 100644 index 000000000000..23cf8ee699c8 --- /dev/null +++ b/redhat/configs/common/generic/CONFIG_SND_SOC_SMA1307 @@ -0,0 +1 @@ +# CONFIG_SND_SOC_SMA1307 is not set diff --git a/redhat/configs/common/generic/CONFIG_SND_SOC_UDA1342 b/redhat/configs/common/generic/CONFIG_SND_SOC_UDA1342 new file mode 100644 index 000000000000..71ccadb41e6e --- /dev/null +++ b/redhat/configs/common/generic/CONFIG_SND_SOC_UDA1342 @@ -0,0 +1 @@ +# CONFIG_SND_SOC_UDA1342 is not set diff --git a/redhat/configs/rhel/generic/CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH b/redhat/configs/rhel/generic/CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH new file mode 100644 index 000000000000..f84632649195 --- /dev/null +++ b/redhat/configs/rhel/generic/CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH @@ -0,0 +1 @@ +# CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH is not set diff --git a/redhat/configs/rhel/generic/x86/CONFIG_SND_SOC_RT721_SDCA_SDW b/redhat/configs/rhel/generic/x86/CONFIG_SND_SOC_RT721_SDCA_SDW new file mode 100644 index 000000000000..eb68415e29f1 --- /dev/null +++ b/redhat/configs/rhel/generic/x86/CONFIG_SND_SOC_RT721_SDCA_SDW @@ -0,0 +1 @@ +CONFIG_SND_SOC_RT721_SDCA_SDW=m