From 72cafe63b35d06b5cfbaf807e90ae657907858da Mon Sep 17 00:00:00 2001 From: Andrey Shumilin Date: Fri, 18 Oct 2024 09:00:18 +0300 Subject: [PATCH 01/53] ALSA: firewire-lib: Avoid division by zero in apply_constraint_to_size() The step variable is initialized to zero. It is changed in the loop, but if it's not changed it will remain zero. Add a variable check before the division. The observed behavior was introduced by commit 826b5de90c0b ("ALSA: firewire-lib: fix insufficient PCM rule for period/buffer size"), and it is difficult to show that any of the interval parameters will satisfy the snd_interval_test() condition with data from the amdtp_rate_table[] table. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 826b5de90c0b ("ALSA: firewire-lib: fix insufficient PCM rule for period/buffer size") Signed-off-by: Andrey Shumilin Reviewed-by: Takashi Sakamoto Link: https://patch.msgid.link/20241018060018.1189537-1-shum.sdl@nppct.ru Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index c72b2a75477598..7fc51f829eccac 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -172,6 +172,9 @@ static int apply_constraint_to_size(struct snd_pcm_hw_params *params, step = max(step, amdtp_syt_intervals[i]); } + if (step == 0) + return -EINVAL; + t.min = roundup(s->min, step); t.max = rounddown(s->max, step); t.integer = 1; From 35fdc6e1c16099078bcbd73a6c8f1733ae7f1909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Relvas?= Date: Sun, 20 Oct 2024 11:27:56 +0100 Subject: [PATCH 02/53] ALSA: hda/realtek: Add subwoofer quirk for Acer Predator G9-593 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Acer Predator G9-593 has a 2+1 speaker system which isn't probed correctly. This patch adds a quirk with the proper pin connections. Note that I do not own this laptop, so I cannot guarantee that this fixes the issue. Testing was done by other users here: https://discussion.fedoraproject.org/t/-/118482 This model appears to have two different dev IDs... - 0x1177 (as seen on the forum link above) - 0x1178 (as seen on https://linux-hardware.org/?probe=127df9999f) I don't think the audio system was changed between model revisions, so the patch applies for both IDs. Signed-off-by: José Relvas Link: https://patch.msgid.link/20241020102756.225258-1-josemonsantorelvas@gmail.com Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3bbf5fab288153..edf688f989c8a1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7649,6 +7649,7 @@ enum { ALC286_FIXUP_ACER_AIO_HEADSET_MIC, ALC256_FIXUP_ASUS_HEADSET_MIC, ALC256_FIXUP_ASUS_MIC_NO_PRESENCE, + ALC255_FIXUP_PREDATOR_SUBWOOFER, ALC299_FIXUP_PREDATOR_SPK, ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, ALC289_FIXUP_DELL_SPK1, @@ -9063,6 +9064,13 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE }, + [ALC255_FIXUP_PREDATOR_SUBWOOFER] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x17, 0x90170151 }, /* use as internal speaker (LFE) */ + { 0x1b, 0x90170152 } /* use as internal speaker (back) */ + } + }, [ALC299_FIXUP_PREDATOR_SPK] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -10150,6 +10158,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x110e, "Acer Aspire ES1-432", ALC255_FIXUP_ACER_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1025, 0x1166, "Acer Veriton N4640G", ALC269_FIXUP_LIFEBOOK), SND_PCI_QUIRK(0x1025, 0x1167, "Acer Veriton N6640G", ALC269_FIXUP_LIFEBOOK), + SND_PCI_QUIRK(0x1025, 0x1177, "Acer Predator G9-593", ALC255_FIXUP_PREDATOR_SUBWOOFER), + SND_PCI_QUIRK(0x1025, 0x1178, "Acer Predator G9-593", ALC255_FIXUP_PREDATOR_SUBWOOFER), SND_PCI_QUIRK(0x1025, 0x1246, "Acer Predator Helios 500", ALC299_FIXUP_PREDATOR_SPK), SND_PCI_QUIRK(0x1025, 0x1247, "Acer vCopperbox", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS), SND_PCI_QUIRK(0x1025, 0x1248, "Acer Veriton N4660G", ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE), From 86c96e7289c5758284b562ac7b5c94429f48d2d9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 20 Oct 2024 10:56:24 -0700 Subject: [PATCH 03/53] ALSA: hda/tas2781: select CRC32 instead of CRC32_SARWATE Fix the kconfig option for the tas2781 HDA driver to select CRC32 rather than CRC32_SARWATE. CRC32_SARWATE is an option from the kconfig 'choice' that selects the specific CRC32 implementation. Selecting a 'choice' option seems to have no effect, but even if it did work, it would be incorrect for a random driver to override the user's choice. CRC32 is the correct option to select for crc32() to be available. Fixes: 5be27f1e3ec9 ("ALSA: hda/tas2781: Add tas2781 HDA driver") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Link: https://patch.msgid.link/20241020175624.7095-1-ebiggers@kernel.org Signed-off-by: Takashi Iwai --- sound/pci/hda/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index bb15a0248250cc..68f1eee9e5c938 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -198,7 +198,7 @@ config SND_HDA_SCODEC_TAS2781_I2C depends on SND_SOC select SND_SOC_TAS2781_COMLIB select SND_SOC_TAS2781_FMWLIB - select CRC32_SARWATE + select CRC32 help Say Y or M here to include TAS2781 I2C HD-audio side codec support in snd-hda-intel driver, such as ALC287. From e3ea2757c312e51bbf62ebc434a6f7df1e3a201f Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Wed, 23 Oct 2024 16:13:10 +0800 Subject: [PATCH 04/53] ALSA: hda/realtek: Update default depop procedure Old procedure has a chance to meet Headphone no output. Fixes: c2d6af53a43f ("ALSA: hda/realtek - Add default procedure for suspend and resume state") Signed-off-by: Kailang Yang Link: https://lore.kernel.org/17b717a0a0b04a77aea4a8ec820cba13@realtek.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 38 ++++++++++++++++------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index edf688f989c8a1..3567b14b52b7c2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3868,20 +3868,18 @@ static void alc_default_init(struct hda_codec *codec) hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); - if (hp_pin_sense) + if (hp_pin_sense) { msleep(2); - snd_hda_codec_write(codec, hp_pin, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); - - if (hp_pin_sense) - msleep(85); + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); - snd_hda_codec_write(codec, hp_pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + msleep(75); - if (hp_pin_sense) - msleep(100); + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + msleep(75); + } } static void alc_default_shutup(struct hda_codec *codec) @@ -3897,22 +3895,20 @@ static void alc_default_shutup(struct hda_codec *codec) hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); - if (hp_pin_sense) + if (hp_pin_sense) { msleep(2); - snd_hda_codec_write(codec, hp_pin, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); - - if (hp_pin_sense) - msleep(85); - - if (!spec->no_shutup_pins) snd_hda_codec_write(codec, hp_pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); - if (hp_pin_sense) - msleep(100); + msleep(75); + if (!spec->no_shutup_pins) + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + + msleep(75); + } alc_auto_setup_eapd(codec, false); alc_shutup_pins(codec); } From 78e7be018784934081afec77f96d49a2483f9188 Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Fri, 18 Oct 2024 13:53:24 +0800 Subject: [PATCH 05/53] ALSA: hda/realtek: Limit internal Mic boost on Dell platform Dell want to limit internal Mic boost on all Dell platform. Signed-off-by: Kailang Yang Cc: Link: https://lore.kernel.org/561fc5f5eff04b6cbd79ed173cd1c1db@realtek.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3567b14b52b7c2..784ac058418fc9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7521,6 +7521,7 @@ enum { ALC286_FIXUP_SONY_MIC_NO_PRESENCE, ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC269_FIXUP_DELL1_LIMIT_INT_MIC_BOOST, ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, @@ -7555,6 +7556,7 @@ enum { ALC255_FIXUP_ACER_MIC_NO_PRESENCE, ALC255_FIXUP_ASUS_MIC_NO_PRESENCE, ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC255_FIXUP_DELL1_LIMIT_INT_MIC_BOOST, ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, ALC255_FIXUP_HEADSET_MODE, ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC, @@ -8114,6 +8116,12 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_HEADSET_MODE }, + [ALC269_FIXUP_DELL1_LIMIT_INT_MIC_BOOST] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc269_fixup_limit_int_mic_boost, + .chained = true, + .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE + }, [ALC269_FIXUP_DELL2_MIC_NO_PRESENCE] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -8394,6 +8402,12 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC255_FIXUP_HEADSET_MODE }, + [ALC255_FIXUP_DELL1_LIMIT_INT_MIC_BOOST] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc269_fixup_limit_int_mic_boost, + .chained = true, + .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE + }, [ALC255_FIXUP_DELL2_MIC_NO_PRESENCE] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -11076,6 +11090,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"}, {.id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, .name = "dell-headset3"}, {.id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, .name = "dell-headset4"}, + {.id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET, .name = "dell-headset4-quiet"}, {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"}, {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"}, {.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"}, @@ -11630,16 +11645,16 @@ static const struct snd_hda_pin_quirk alc269_fallback_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0289, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, {0x19, 0x40000000}, {0x1b, 0x40000000}), - SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, + SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET, {0x19, 0x40000000}, {0x1b, 0x40000000}), SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, {0x19, 0x40000000}, {0x1a, 0x40000000}), - SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_LIMIT_INT_MIC_BOOST, {0x19, 0x40000000}, {0x1a, 0x40000000}), - SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB, + SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC269_FIXUP_DELL1_LIMIT_INT_MIC_BOOST, {0x19, 0x40000000}, {0x1a, 0x40000000}), SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC2XX_FIXUP_HEADSET_MIC, From ef5fbdf732a158ec27eeba69d8be851351f29f73 Mon Sep 17 00:00:00 2001 From: Piyush Raj Chouhan Date: Mon, 28 Oct 2024 15:55:16 +0000 Subject: [PATCH 06/53] ALSA: hda/realtek: Add subwoofer quirk for Infinix ZERO BOOK 13 Infinix ZERO BOOK 13 has a 2+2 speaker system which isn't probed correctly. This patch adds a quirk with the proper pin connections. Also The mic in this laptop suffers too high gain resulting in mostly fan noise being recorded, This patch Also limit mic boost. HW Probe for device; https://linux-hardware.org/?probe=a2e892c47b Test: All 4 speaker works, Mic has low noise. Signed-off-by: Piyush Raj Chouhan Link: https://patch.msgid.link/20241028155516.15552-1-piyuschouhan1598@gmail.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 784ac058418fc9..7f4926194e50f2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7552,6 +7552,7 @@ enum { ALC290_FIXUP_SUBWOOFER_HSJACK, ALC269_FIXUP_THINKPAD_ACPI, ALC269_FIXUP_DMIC_THINKPAD_ACPI, + ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13, ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO, ALC255_FIXUP_ACER_MIC_NO_PRESENCE, ALC255_FIXUP_ASUS_MIC_NO_PRESENCE, @@ -7998,6 +7999,16 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc269_fixup_pincfg_U7x7_headset_mic, }, + [ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x14, 0x90170151 }, /* use as internal speaker (LFE) */ + { 0x1b, 0x90170152 }, /* use as internal speaker (back) */ + { } + }, + .chained = true, + .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST + }, [ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -11003,6 +11014,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC), SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13), SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO), SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME), SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC), From 4413665dd6c528b31284119e3571c25f371e1c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sch=C3=A4r?= Date: Tue, 29 Oct 2024 23:12:49 +0100 Subject: [PATCH 07/53] ALSA: usb-audio: Add quirks for Dell WD19 dock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The WD19 family of docks has the same audio chipset as the WD15. This change enables jack detection on the WD19. We don't need the dell_dock_mixer_init quirk for the WD19. It is only needed because of the dell_alc4020_map quirk for the WD15 in mixer_maps.c, which disables the volume controls. Even for the WD15, this quirk was apparently only needed when the dock firmware was not updated. Signed-off-by: Jan Schär Cc: Link: https://patch.msgid.link/20241029221249.15661-1-jan@jschaer.ch Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 2a9594f34dac6f..6456e87e2f3974 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -4042,6 +4042,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) break; err = dell_dock_mixer_init(mixer); break; + case USB_ID(0x0bda, 0x402e): /* Dell WD19 dock */ + err = dell_dock_mixer_create(mixer); + break; case USB_ID(0x2a39, 0x3fd2): /* RME ADI-2 Pro */ case USB_ID(0x2a39, 0x3fd3): /* RME ADI-2 DAC */ From 0b04fbe886b4274c8e5855011233aaa69fec6e75 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 29 Oct 2024 16:16:52 +0100 Subject: [PATCH 08/53] ALSA: hda/realtek: Fix headset mic on TUXEDO Gemini 17 Gen3 Quirk is needed to enable headset microphone on missing pin 0x19. Signed-off-by: Christoffer Sandberg Signed-off-by: Werner Sembach Cc: Link: https://patch.msgid.link/20241029151653.80726-1-wse@tuxedocomputers.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7f4926194e50f2..e06a6fdc0bab78 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10750,6 +10750,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x2624, "Clevo L240TU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x28c1, "Clevo V370VND", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), From e49370d769e71456db3fbd982e95bab8c69f73e8 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 29 Oct 2024 16:16:53 +0100 Subject: [PATCH 09/53] ALSA: hda/realtek: Fix headset mic on TUXEDO Stellaris 16 Gen6 mb1 Quirk is needed to enable headset microphone on missing pin 0x19. Signed-off-by: Christoffer Sandberg Signed-off-by: Werner Sembach Cc: Link: https://patch.msgid.link/20241029151653.80726-2-wse@tuxedocomputers.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e06a6fdc0bab78..571fa8a6c9e120 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -11008,6 +11008,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP), SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP), SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1d05, 0x1409, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1d17, 0x3288, "Haier Boyue G42", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS), SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC), SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE), From bd0aff85d5f3f3fc22735ab5869008dfd8ab4867 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 31 Oct 2024 12:33:02 +0200 Subject: [PATCH 10/53] 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 --- 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 45f32d28190813..a11f9be91da4e6 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 019610566757a749dde7e0c92777d2c1613afef8 Mon Sep 17 00:00:00 2001 From: anish kumar Date: Wed, 30 Oct 2024 20:58:29 -0700 Subject: [PATCH 11/53] 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 --- 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 32122d6877a3d3..25d016ea8b65f6 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 c9363bbb0f68dd1ddb8be7bbfe958cdfcd38d851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaros=C5=82aw=20Janik?= Date: Wed, 30 Oct 2024 18:18:12 +0100 Subject: [PATCH 12/53] Revert "ALSA: hda/conexant: Mute speakers at suspend / shutdown" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 4f61c8fe3520 ("ALSA: hda/conexant: Mute speakers at suspend / shutdown") mutes speakers on system shutdown or whenever HDA controller is suspended by PM; this however interacts badly with Thinkpad's ACPI firmware behavior which uses beeps to signal various events (enter/leave suspend or hibernation, AC power connect/disconnect, low battery, etc.); now those beeps are either muted altogether (for suspend/hibernate/ shutdown related events) or work more or less randomly (eg. AC plug/unplug is only audible when you are playing music at the moment, because HDA device is likely in suspend mode otherwise). Since the original bug report mentioned in 4f61c8fe3520 complained about Lenovo's Thinkpad laptop - revert this commit altogether. Fixes: 4f61c8fe3520 ("ALSA: hda/conexant: Mute speakers at suspend / shutdown") Signed-off-by: Jarosław Janik Link: https://patch.msgid.link/20241030171813.18941-2-jaroslaw.janik@gmail.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index c74f6742c35955..b2bcdf76da3058 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -205,8 +205,6 @@ static void cx_auto_shutdown(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; - snd_hda_gen_shutup_speakers(codec); - /* Turn the problematic codec into D3 to avoid spurious noises from the internal speaker during (and after) reboot */ cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false); From 1ed9b927e7dd8b8cff13052efe212a8ff72ec51d Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Thu, 31 Oct 2024 18:37:04 +0200 Subject: [PATCH 13/53] regmap: maple: Provide lockdep (sub)class for maple tree's internal lock In some cases when using the maple tree register cache, the lockdep validator might complain about invalid deadlocks: [7.131886] Possible interrupt unsafe locking scenario: [7.131890] CPU0 CPU1 [7.131893] ---- ---- [7.131896] lock(&mt->ma_lock); [7.131904] local_irq_disable(); [7.131907] lock(rockchip_drm_vop2:3114:(&vop2_regmap_config)->lock); [7.131916] lock(&mt->ma_lock); [7.131925] [7.131928] lock(rockchip_drm_vop2:3114:(&vop2_regmap_config)->lock); [7.131936] *** DEADLOCK *** [7.131939] no locks held by swapper/0/0. [7.131944] the shortest dependencies between 2nd lock and 1st lock: [7.131950] -> (&mt->ma_lock){+.+.}-{2:2} { [7.131966] HARDIRQ-ON-W at: [7.131973] lock_acquire+0x200/0x330 [7.131986] _raw_spin_lock+0x50/0x70 [7.131998] regcache_maple_write+0x68/0xe0 [7.132010] regcache_write+0x6c/0x90 [7.132019] _regmap_read+0x19c/0x1d0 [7.132029] _regmap_update_bits+0xc0/0x148 [7.132038] regmap_update_bits_base+0x6c/0xa8 [7.132048] rk8xx_probe+0x22c/0x3d8 [7.132057] rk8xx_spi_probe+0x74/0x88 [7.132065] spi_probe+0xa8/0xe0 [...] [7.132675] } [7.132678] ... key at: [] __key.0+0x0/0x10 [7.132691] ... acquired at: [7.132695] _raw_spin_lock+0x50/0x70 [7.132704] regcache_maple_write+0x68/0xe0 [7.132714] regcache_write+0x6c/0x90 [7.132724] _regmap_read+0x19c/0x1d0 [7.132732] _regmap_update_bits+0xc0/0x148 [7.132741] regmap_field_update_bits_base+0x74/0xb8 [7.132751] vop2_plane_atomic_update+0x480/0x14d8 [rockchipdrm] [7.132820] drm_atomic_helper_commit_planes+0x1a0/0x320 [drm_kms_helper] [...] [7.135112] -> (rockchip_drm_vop2:3114:(&vop2_regmap_config)->lock){-...}-{2:2} { [7.135130] IN-HARDIRQ-W at: [7.135136] lock_acquire+0x200/0x330 [7.135147] _raw_spin_lock_irqsave+0x6c/0x98 [7.135157] regmap_lock_spinlock+0x20/0x40 [7.135166] regmap_read+0x44/0x90 [7.135175] vop2_isr+0x90/0x290 [rockchipdrm] [7.135225] __handle_irq_event_percpu+0x124/0x2d0 In the example above, the validator seems to get the scope of dependencies wrong, since the regmap instance used in rk8xx-spi driver has nothing to do with the instance from vop2. Improve validation by sharing the regmap's lockdep class with the maple tree's internal lock, while also providing a subclass for the latter. Signed-off-by: Cristian Ciocaltea Link: https://patch.msgid.link/20241031-regmap-maple-lockdep-fix-v2-1-06a3710f3623@collabora.com Signed-off-by: Mark Brown --- drivers/base/regmap/internal.h | 1 + drivers/base/regmap/regcache-maple.c | 3 +++ drivers/base/regmap/regmap.c | 1 + 3 files changed, 5 insertions(+) diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 83acccdc100897..bdb450436cbc53 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -59,6 +59,7 @@ struct regmap { unsigned long raw_spinlock_flags; }; }; + struct lock_class_key *lock_key; regmap_lock lock; regmap_unlock unlock; void *lock_arg; /* This is passed to lock/unlock functions */ diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c index 8d27d3653ea3e7..23da7b31d71534 100644 --- a/drivers/base/regmap/regcache-maple.c +++ b/drivers/base/regmap/regcache-maple.c @@ -355,6 +355,9 @@ static int regcache_maple_init(struct regmap *map) mt_init(mt); + if (!mt_external_lock(mt) && map->lock_key) + lockdep_set_class_and_subclass(&mt->ma_lock, map->lock_key, 1); + if (!map->num_reg_defaults) return 0; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 4ded93687c1f0a..53131a7ede0a6a 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -745,6 +745,7 @@ struct regmap *__regmap_init(struct device *dev, lock_key, lock_name); } map->lock_arg = map; + map->lock_key = lock_key; } /* From 485df22866559e2f821a9754d51a9755ce56e7aa Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 1 Nov 2024 07:38:01 +0530 Subject: [PATCH 14/53] 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 --- 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 a25f94d6eb678c..0e82598e10af05 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 36e6d6db90c172..8fce8cb957c9b8 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 5614e706a0bbed..9ca284a1d66663 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -790,7 +790,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 @@ -867,7 +867,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; @@ -892,7 +892,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; @@ -903,7 +903,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) @@ -947,7 +947,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; @@ -975,7 +975,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 6610efe8af1851..e7f5938701effa 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 d280cf5fbfe3cdd373c98e858834ff87b6ea64de Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 1 Nov 2024 07:38:02 +0530 Subject: [PATCH 15/53] 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 --- 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 e7f5938701effa..19bd02e2cd6d67 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 1d534bfb2b2ecec4e67a1667c67169f7a22e46f5 Mon Sep 17 00:00:00 2001 From: Weidong Wang Date: Thu, 24 Oct 2024 17:03:23 +0800 Subject: [PATCH 16/53] 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 --- 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 ac5f2e0f42cbd5..3b0b743e49c4c8 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 88264e4f0b6695245cea2810bf54bebf1c98c070 Mon Sep 17 00:00:00 2001 From: Weidong Wang Date: Thu, 24 Oct 2024 17:03:24 +0800 Subject: [PATCH 17/53] 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 --- 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 d3cef4e497f3c8..7dead36be02c4b 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 @@ -689,6 +690,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 2c69df06677e54..ea93968f6bf627 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 @@ -465,6 +466,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 00000000000000..58b8e002d76f08 --- /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 00000000000000..b4bf7288021abc --- /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: Thu, 24 Oct 2024 01:29:13 +0000 Subject: [PATCH 18/53] 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 --- 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 0d1b215f24f4f0..9dbeedf6da13bc 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 5c240ea340276a..51840ceb3cd420 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -486,11 +486,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; } @@ -1195,7 +1195,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 a0c55246f424b6..fb664c775dda50 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 f04b671ce33ea6..3cb7482791669c 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 4a1c85ad5a8d60..2feb76bf57bb72 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 678400e76e53b7..81b63e547a0996 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 eae33f737c7a929d92b559fe1a1002d597b7b903 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 24 Oct 2024 01:29:20 +0000 Subject: [PATCH 19/53] 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 --- 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 0f11f20dc51a43..95a57fda025039 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 b19f75df8fa9f8d4aa8b5886dca0f2d832a76baa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 24 Oct 2024 01:29:27 +0000 Subject: [PATCH 20/53] 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 --- 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 5ebf287fe7004e..a2dfccb7990f3a 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 = snd_soc_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 455f6bfc9f8fa5..b408cc2bbc9193 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 = snd_soc_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 970a874b76d09d6a5880e8832e572850cfcb4008 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 24 Oct 2024 01:29:34 +0000 Subject: [PATCH 21/53] 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 --- sound/soc/renesas/rcar/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/renesas/rcar/core.c b/sound/soc/renesas/rcar/core.c index c32e88d6a141ed..e2234928c9e881 100644 --- a/sound/soc/renesas/rcar/core.c +++ b/sound/soc/renesas/rcar/core.c @@ -1843,7 +1843,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 742e622db67efc32affb5893fdcc0149f374533e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 24 Oct 2024 01:29:39 +0000 Subject: [PATCH 22/53] 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 --- 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 fedae7f6f70cc5..d47c372228b34c 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 c59db5ed233a19f6aadd086fb89149ec5f6fa855 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 24 Oct 2024 01:29:45 +0000 Subject: [PATCH 23/53] 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 --- 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 51840ceb3cd420..21a50a8057eb60 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1195,7 +1195,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 3cb7482791669c..233c91e60f0cbb 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 cb18cd26039f5cdecb0ac53fb447b6f0859f3d1c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 24 Oct 2024 01:29:52 +0000 Subject: [PATCH 24/53] 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 --- 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 233c91e60f0cbb..4f0bfe73fe15ef 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 8b12da9a18f4dd53e4b3a7393829a555e84f073c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 24 Oct 2024 01:29:58 +0000 Subject: [PATCH 25/53] 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 --- 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 9dbeedf6da13bc..b275201b02f608 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 21a50a8057eb60..4f5d411e3823f6 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -486,11 +486,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 fb664c775dda50..3c514703fa33d6 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 4f0bfe73fe15ef..a1dace4bb61664 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 2feb76bf57bb72..34ba1a93a4c95a 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 81b63e547a0996..fb7f25fd8ec5bd 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 953e549471cabc9d4980f1da2e9fa79f4c23da06 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 1 Nov 2024 18:55:53 +0200 Subject: [PATCH 26/53] regmap: irq: Set lockdep class for hierarchical IRQ domains Lockdep gives a false positive splat as it can't distinguish the lock which is taken by different IRQ descriptors from different IRQ chips that are organized in a way of a hierarchy: ====================================================== WARNING: possible circular locking dependency detected 6.12.0-rc5-next-20241101-00148-g9fabf8160b53 #562 Tainted: G W ------------------------------------------------------ modprobe/141 is trying to acquire lock: ffff899446947868 (intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock){+.+.}-{4:4}, at: regmap_update_bits_base+0x33/0x90 but task is already holding lock: ffff899446947c68 (&d->lock){+.+.}-{4:4}, at: __setup_irq+0x682/0x790 which lock already depends on the new lock. -> #3 (&d->lock){+.+.}-{4:4}: -> #2 (&desc->request_mutex){+.+.}-{4:4}: -> #1 (ipclock){+.+.}-{4:4}: -> #0 (intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock){+.+.}-{4:4}: Chain exists of: intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock --> &desc->request_mutex --> &d->lock Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&d->lock); lock(&desc->request_mutex); lock(&d->lock); lock(intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock); *** DEADLOCK *** 3 locks held by modprobe/141: #0: ffff8994419368f8 (&dev->mutex){....}-{4:4}, at: __driver_attach+0xf6/0x250 #1: ffff89944690b250 (&desc->request_mutex){+.+.}-{4:4}, at: __setup_irq+0x1a2/0x790 #2: ffff899446947c68 (&d->lock){+.+.}-{4:4}, at: __setup_irq+0x682/0x790 Set a lockdep class when we map the IRQ so that it doesn't warn about a lockdep bug that doesn't exist. Fixes: 4af8be67fd99 ("regmap: Convert regmap_irq to use irq_domain") Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20241101165553.4055617-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-irq.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 33ec28e3a80252..0bcd81389a29f8 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -511,12 +511,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) return IRQ_NONE; } +static struct lock_class_key regmap_irq_lock_class; +static struct lock_class_key regmap_irq_request_class; + static int regmap_irq_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { struct regmap_irq_chip_data *data = h->host_data; irq_set_chip_data(virq, data); + irq_set_lockdep_class(virq, ®map_irq_lock_class, ®map_irq_request_class); irq_set_chip(virq, &data->irq_chip); irq_set_nested_thread(virq, 1); irq_set_parent(virq, data->irq); From c2d188e137e77294323132a760a4608321a36a70 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 4 Nov 2024 11:07:34 +0100 Subject: [PATCH 27/53] ALSA: ump: Don't enumeration invalid groups for legacy rawmidi The legacy rawmidi tries to enumerate all possible UMP groups belonging to the UMP endpoint. But currently it shows all 16 ports when the UMP endpoint is configured with static blocks, although most of them may be unused. There was already a fix for the sequencer client side to ignore such groups in the commit 3bfd7c0ba184 ("ALSA: seq: ump: Skip useless ports for static blocks"), and this commit is a similar fix for UMP rawmidi devices; it adds simply the check for the validity of each group that has been already parsed. (Note that the group info was moved to snd_ump_endpoint.groups[] by the commit 0642a3c5cacc0321c755 ("ALSA: ump: Update substream name from assigned FB names")). Link: https://patch.msgid.link/20241104100735.16127-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- 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 cf22a17e38dd50..7d59a0a9b037ad 100644 --- a/sound/core/ump.c +++ b/sound/core/ump.c @@ -1233,7 +1233,7 @@ static int fill_legacy_mapping(struct snd_ump_endpoint *ump) num = 0; for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) - if (group_maps & (1U << i)) + if ((group_maps & (1U << i)) && ump->groups[i].valid) ump->legacy_mapping[num++] = i; return num; From 8abbf1f01d6a2ef9f911f793e30f7382154b5a3a Mon Sep 17 00:00:00 2001 From: Murad Masimov Date: Fri, 1 Nov 2024 21:55:13 +0300 Subject: [PATCH 28/53] ALSA: firewire-lib: fix return value on fail in amdtp_tscm_init() If amdtp_stream_init() fails in amdtp_tscm_init(), the latter returns zero, though it's supposed to return error code, which is checked inside init_stream() in file tascam-stream.c. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 47faeea25ef3 ("ALSA: firewire-tascam: add data block processing layer") Signed-off-by: Murad Masimov Reviewed-by: Takashi Sakamoto Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20241101185517.1819-1-m.masimov@maxima.ru --- sound/firewire/tascam/amdtp-tascam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 0b42d65590081a..079afa4bd3811b 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -238,7 +238,7 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, err = amdtp_stream_init(s, unit, dir, flags, fmt, process_ctx_payloads, sizeof(struct amdtp_tscm)); if (err < 0) - return 0; + return err; if (dir == AMDTP_OUT_STREAM) { // Use fixed value for FDF field. From cac99f73f0752e1c83674e12fb2c605dca9ce474 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 31 Oct 2024 20:32:52 +0100 Subject: [PATCH 29/53] 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 --- 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 b4540c5cd2a6f9..9fc5e6c5d80030 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1040,14 +1040,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; @@ -1062,11 +1054,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 149cb7d9537e241b43056fb4133f56832ac51b7a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 31 Oct 2024 20:41:12 +0100 Subject: [PATCH 30/53] 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 --- 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 9fc5e6c5d80030..fc329b6a70f55c 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -773,6 +773,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, @@ -786,7 +794,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; } @@ -1879,13 +1886,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); @@ -2037,7 +2040,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 fe09de2db2365eed8b44b572cff7d421eaf1754a Mon Sep 17 00:00:00 2001 From: Shenghao Ding Date: Mon, 4 Nov 2024 18:00:55 +0800 Subject: [PATCH 31/53] ASoC: tas2781: Add new driver version for tas2563 & tas2781 qfn chip Add new driver version to support tas2563 & tas2781 qfn chip Signed-off-by: Shenghao Ding Link: https://patch.msgid.link/20241104100055.48-1-shenghao-ding@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2781-fmwlib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index ae360c97fe1efb..0aeb88abbf52f1 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -1992,6 +1992,7 @@ static int tasdevice_dspfw_ready(const struct firmware *fmw, break; case 0x202: case 0x400: + case 0x401: tas_priv->fw_parse_variable_header = fw_parse_variable_header_git; tas_priv->fw_parse_program_data = From 8ae4c65d7ae82fead83202448453e47078ddfde7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 4 Nov 2024 20:06:53 +0100 Subject: [PATCH 32/53] 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 --- 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 fc329b6a70f55c..6e271777feb9c9 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1039,13 +1039,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 dabc44c28f118910dea96244d903f0c270225669 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 5 Nov 2024 13:02:17 +0100 Subject: [PATCH 33/53] ALSA: usb-audio: Add quirk for HP 320 FHD Webcam HP 320 FHD Webcam (03f0:654a) seems to have flaky firmware like other webcam devices that don't like the frequency inquiries. Also, Mic Capture Volume has an invalid resolution, hence fix it to be 16 (as a blind shot). Link: https://bugzilla.suse.com/show_bug.cgi?id=1232768 Cc: Link: https://patch.msgid.link/20241105120220.5740-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 1 + sound/usb/quirks.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 9945ae55b0d08b..bd67027c767751 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1205,6 +1205,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, } break; case USB_ID(0x1bcf, 0x2283): /* NexiGo N930AF FHD Webcam */ + case USB_ID(0x03f0, 0x654a): /* HP 320 FHD Webcam */ if (!strcmp(kctl->id.name, "Mic Capture Volume")) { usb_audio_info(chip, "set resolution quirk: cval->res = 16\n"); diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index e6278a24579559..c5fd180357d1e8 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -2114,6 +2114,8 @@ struct usb_audio_quirk_flags_table { static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { /* Device matches */ + DEVICE_FLG(0x03f0, 0x654a, /* HP 320 FHD Webcam */ + QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */ QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */ From d6e6b9218ced5249b9136833ef5ec3f554ec7fde Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 5 Nov 2024 13:02:18 +0100 Subject: [PATCH 34/53] ALSA: usb-audio: Make mic volume workarounds globally applicable It seems that many webcams have buggy firmware and don't expose the mic capture volume with the proper resolution. We have workarounds in mixer.c, but judging from the numbers, those can be better managed as global quirk flags. Link: https://patch.msgid.link/20241105120220.5740-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 58 ++++++++++++-------------------------------- sound/usb/quirks.c | 31 +++++++++++++++++++---- sound/usb/usbaudio.h | 4 +++ 3 files changed, 45 insertions(+), 48 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 341b32f5ddd0c1..66976be06bc088 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1084,6 +1084,21 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, struct snd_kcontrol *kctl) { struct snd_usb_audio *chip = cval->head.mixer->chip; + + if (chip->quirk_flags & QUIRK_FLAG_MIC_RES_384) { + if (!strcmp(kctl->id.name, "Mic Capture Volume")) { + usb_audio_info(chip, + "set resolution quirk: cval->res = 384\n"); + cval->res = 384; + } + } else if (chip->quirk_flags & QUIRK_FLAG_MIC_RES_16) { + if (!strcmp(kctl->id.name, "Mic Capture Volume")) { + usb_audio_info(chip, + "set resolution quirk: cval->res = 16\n"); + cval->res = 16; + } + } + switch (chip->usb_id) { case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ @@ -1168,27 +1183,6 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, } break; - case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */ - case USB_ID(0x046d, 0x0808): - case USB_ID(0x046d, 0x0809): - case USB_ID(0x046d, 0x0819): /* Logitech Webcam C210 */ - case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ - case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ - case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ - case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */ - case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */ - case USB_ID(0x046d, 0x0991): - case USB_ID(0x046d, 0x09a2): /* QuickCam Communicate Deluxe/S7500 */ - /* Most audio usb devices lie about volume resolution. - * Most Logitech webcams have res = 384. - * Probably there is some logitech magic behind this number --fishor - */ - if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - usb_audio_info(chip, - "set resolution quirk: cval->res = 384\n"); - cval->res = 384; - } - break; case USB_ID(0x0495, 0x3042): /* ESS Technology Asus USB DAC */ if ((strstr(kctl->id.name, "Playback Volume") != NULL) || strstr(kctl->id.name, "Capture Volume") != NULL) { @@ -1197,28 +1191,6 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, cval->res = 1; } break; - case USB_ID(0x1224, 0x2a25): /* Jieli Technology USB PHY 2.0 */ - if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - usb_audio_info(chip, - "set resolution quirk: cval->res = 16\n"); - cval->res = 16; - } - break; - case USB_ID(0x1bcf, 0x2283): /* NexiGo N930AF FHD Webcam */ - case USB_ID(0x03f0, 0x654a): /* HP 320 FHD Webcam */ - if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - usb_audio_info(chip, - "set resolution quirk: cval->res = 16\n"); - cval->res = 16; - } - break; - case USB_ID(0x1bcf, 0x2281): /* HD Webcam */ - if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - usb_audio_info(chip, - "set resolution quirk: cval->res = 16\n"); - cval->res = 16; - } - break; } } diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index c5fd180357d1e8..cbfbb064a9c23e 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -2115,7 +2115,7 @@ struct usb_audio_quirk_flags_table { static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { /* Device matches */ DEVICE_FLG(0x03f0, 0x654a, /* HP 320 FHD Webcam */ - QUIRK_FLAG_GET_SAMPLE_RATE), + QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */ QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */ @@ -2123,10 +2123,31 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x045e, 0x083c, /* MS USB Link headset */ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_DISABLE_AUTOSUSPEND), + DEVICE_FLG(0x046d, 0x0807, /* Logitech Webcam C500 */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), + DEVICE_FLG(0x046d, 0x0808, /* Logitech Webcam C600 */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), + DEVICE_FLG(0x046d, 0x0809, + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), + DEVICE_FLG(0x046d, 0x0819, /* Logitech Webcam C210 */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), + DEVICE_FLG(0x046d, 0x081b, /* HD Webcam c310 */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), + DEVICE_FLG(0x046d, 0x081d, /* HD Webcam c510 */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), + DEVICE_FLG(0x046d, 0x0825, /* HD Webcam c270 */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), + DEVICE_FLG(0x046d, 0x0826, /* HD Webcam c525 */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x046d, 0x08ca, /* Logitech Quickcam Fusion */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), DEVICE_FLG(0x046d, 0x0991, /* Logitech QuickCam Pro */ - QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR), + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR | + QUIRK_FLAG_MIC_RES_384), + DEVICE_FLG(0x046d, 0x09a2, /* QuickCam Communicate Deluxe/S7500 */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */ @@ -2194,7 +2215,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ - QUIRK_FLAG_GET_SAMPLE_RATE), + QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */ @@ -2232,9 +2253,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x1bcf, 0x2281, /* HD Webcam */ - QUIRK_FLAG_GET_SAMPLE_RATE), + QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */ - QUIRK_FLAG_GET_SAMPLE_RATE), + QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index b0f042c996087e..158ec053dc44dd 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -194,6 +194,8 @@ extern bool snd_usb_skip_validation; * QUIRK_FLAG_FIXED_RATE * Do not set PCM rate (frequency) when only one rate is available * for the given endpoint. + * QUIRK_FLAG_MIC_RES_16 and QUIRK_FLAG_MIC_RES_384 + * Set the fixed resolution for Mic Capture Volume (mostly for webcams) */ #define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) @@ -218,5 +220,7 @@ extern bool snd_usb_skip_validation; #define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19) #define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20) #define QUIRK_FLAG_FIXED_RATE (1U << 21) +#define QUIRK_FLAG_MIC_RES_16 (1U << 22) +#define QUIRK_FLAG_MIC_RES_384 (1U << 23) #endif /* __USBAUDIO_H */ From 224b898f7c5ff575b02911e21383f271761bdeb6 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Mon, 4 Nov 2024 14:43:10 +0530 Subject: [PATCH 35/53] 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 --- 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 67aa0ad83486a3..d314253207d5c3 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 82e54d65416b8e7cae422bee1755dd203c95d500 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 27 Oct 2024 23:07:49 -0300 Subject: [PATCH 36/53] ASoC: dt-bindings: fsl_spdif: Document imx6sl/sx compatible fallback i.MX6SL and i.MX6SX SPDIF blocks are compatible with i.MX35. Document 'fsl,imx35-spdif' as a fallback compatible for these two chip variants. This fixes the following dt-schema warnings: compatible: ['fsl,imx6sl-spdif', 'fsl,imx35-spdif'] is too long compatible: ['fsl,imx6sx-spdif', 'fsl,imx35-spdif'] is too long Signed-off-by: Fabio Estevam Link: https://patch.msgid.link/20241028020749.36972-1-festevam@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,spdif.yaml | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml index 204f361cea27ab..5654e9f61abaec 100644 --- a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml @@ -16,16 +16,23 @@ description: | properties: compatible: - enum: - - fsl,imx35-spdif - - fsl,vf610-spdif - - fsl,imx6sx-spdif - - fsl,imx8qm-spdif - - fsl,imx8qxp-spdif - - fsl,imx8mq-spdif - - fsl,imx8mm-spdif - - fsl,imx8mn-spdif - - fsl,imx8ulp-spdif + oneOf: + - items: + - enum: + - fsl,imx35-spdif + - fsl,imx6sx-spdif + - fsl,imx8mm-spdif + - fsl,imx8mn-spdif + - fsl,imx8mq-spdif + - fsl,imx8qm-spdif + - fsl,imx8qxp-spdif + - fsl,imx8ulp-spdif + - fsl,vf610-spdif + - items: + - enum: + - fsl,imx6sl-spdif + - fsl,imx6sx-spdif + - const: fsl,imx35-spdif reg: maxItems: 1 From 8f5fab5329b7e966344d59fd1c17adbf9f025c52 Mon Sep 17 00:00:00 2001 From: Zhang Yi Date: Thu, 31 Oct 2024 14:02:53 +0800 Subject: [PATCH 37/53] 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 --- 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 aa3e364827c8a5..a5603b6176889a 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -616,7 +616,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 { @@ -1082,7 +1082,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 159098859bf6d46b34a1e1f7d44d28987b875878 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 23 Oct 2024 14:41:52 +0200 Subject: [PATCH 38/53] 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 --- 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 898b5c26bf1ee6..8eb57fc12f0dab 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 1157733344651ca505e259d6554591ff156922fa Mon Sep 17 00:00:00 2001 From: Qiu-ji Chen Date: Mon, 30 Sep 2024 18:12:16 +0800 Subject: [PATCH 39/53] ASoC: codecs: Fix atomicity violation in snd_soc_component_get_drvdata() An atomicity violation occurs when the validity of the variables da7219->clk_src and da7219->mclk_rate is being assessed. Since the entire assessment is not protected by a lock, the da7219 variable might still be in flux during the assessment, rendering this check invalid. To fix this issue, we recommend adding a lock before the block if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq)) so that the legitimacy check for da7219->clk_src and da7219->mclk_rate is protected by the lock, ensuring the validity of the check. This possible bug is found by an experimental static analysis tool developed by our team. This tool analyzes the locking APIs to extract function pairs that can be concurrently executed, and then analyzes the instructions in the paired functions to identify possible concurrency bugs including data races and atomicity violations. Fixes: 6d817c0e9fd7 ("ASoC: codecs: Add da7219 codec driver") Cc: stable@vger.kernel.org Signed-off-by: Qiu-ji Chen Link: https://patch.msgid.link/20240930101216.23723-1-chenqiuji666@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7219.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 311ea7918b3124..e2da3e317b5a3e 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1167,17 +1167,20 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); int ret = 0; - if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq)) + mutex_lock(&da7219->pll_lock); + + if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq)) { + mutex_unlock(&da7219->pll_lock); return 0; + } if ((freq < 2000000) || (freq > 54000000)) { + mutex_unlock(&da7219->pll_lock); dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", freq); return -EINVAL; } - mutex_lock(&da7219->pll_lock); - switch (clk_id) { case DA7219_CLKSRC_MCLK_SQR: snd_soc_component_update_bits(component, DA7219_PLL_CTRL, From 28f7aa0c015036db260adbec37891984a31ed4c2 Mon Sep 17 00:00:00 2001 From: Suraj Sonawane Date: Sat, 2 Nov 2024 18:06:30 +0530 Subject: [PATCH 40/53] 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 --- 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 018f2372e892c2..e3a4fcc63a56dc 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 101c9023594ac937b11739aab149a0c14ab901b6 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 25 Oct 2024 14:29:35 +0800 Subject: [PATCH 41/53] ASoC: fsl_mqs: Support accessing registers by scmi interface On i.MX95, the MQS module in Always-on (AON) domain only can be accessed by System Controller Management Interface (SCMI) MISC Protocol. So define a specific regmap_config for the case. Signed-off-by: Shengjiu Wang Link: https://patch.msgid.link/20241025062935.1071408-1-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 1 + sound/soc/fsl/fsl_mqs.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index e283751abfefe8..8e88830e8e577c 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -30,6 +30,7 @@ config SND_SOC_FSL_MQS tristate "Medium Quality Sound (MQS) module support" depends on SND_SOC_FSL_SAI select REGMAP_MMIO + select IMX_SCMI_MISC_DRV if IMX_SCMI_MISC_EXT !=n help Say Y if you want to add Medium Quality Sound (MQS) support for the Freescale CPUs. diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index 145f9ca15e43cb..0513e9e8402e82 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -6,6 +6,7 @@ // Copyright 2019 NXP #include +#include #include #include #include @@ -74,6 +75,29 @@ struct fsl_mqs { #define FSL_MQS_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) #define FSL_MQS_FORMATS SNDRV_PCM_FMTBIT_S16_LE +static int fsl_mqs_sm_read(void *context, unsigned int reg, unsigned int *val) +{ + struct fsl_mqs *mqs_priv = context; + int num = 1; + + if (IS_ENABLED(CONFIG_IMX_SCMI_MISC_DRV) && + mqs_priv->soc->ctrl_off == reg) + return scmi_imx_misc_ctrl_get(SCMI_IMX_CTRL_MQS1_SETTINGS, &num, val); + + return -EINVAL; +}; + +static int fsl_mqs_sm_write(void *context, unsigned int reg, unsigned int val) +{ + struct fsl_mqs *mqs_priv = context; + + if (IS_ENABLED(CONFIG_IMX_SCMI_MISC_DRV) && + mqs_priv->soc->ctrl_off == reg) + return scmi_imx_misc_ctrl_set(SCMI_IMX_CTRL_MQS1_SETTINGS, val); + + return -EINVAL; +}; + static int fsl_mqs_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -188,6 +212,13 @@ static const struct regmap_config fsl_mqs_regmap_config = { .cache_type = REGCACHE_NONE, }; +static const struct regmap_config fsl_mqs_sm_regmap = { + .reg_bits = 32, + .val_bits = 32, + .reg_read = fsl_mqs_sm_read, + .reg_write = fsl_mqs_sm_write, +}; + static int fsl_mqs_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -219,6 +250,16 @@ static int fsl_mqs_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to get gpr regmap\n"); return PTR_ERR(mqs_priv->regmap); } + } else if (mqs_priv->soc->type == TYPE_REG_SM) { + mqs_priv->regmap = devm_regmap_init(&pdev->dev, + NULL, + mqs_priv, + &fsl_mqs_sm_regmap); + if (IS_ERR(mqs_priv->regmap)) { + dev_err(&pdev->dev, "failed to init regmap: %ld\n", + PTR_ERR(mqs_priv->regmap)); + return PTR_ERR(mqs_priv->regmap); + } } else { regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) From a80aedeb816c81e86e3a59384f010da3414479dd Mon Sep 17 00:00:00 2001 From: Stanislav Jakubek Date: Wed, 30 Oct 2024 18:48:38 +0100 Subject: [PATCH 42/53] ASoC: dt-bindings: sprd,pcm-platform: convert to YAML Convert the Spreadtrum DMA platform bindings to DT schema. Adjust filename to match compatible. Signed-off-by: Stanislav Jakubek Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/9fc646b70a73e7a6c513771d69b0edcd140f09d7.1730310275.git.stano.jakubek@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/sprd,pcm-platform.yaml | 56 +++++++++++++++++++ .../devicetree/bindings/sound/sprd-pcm.txt | 23 -------- 2 files changed, 56 insertions(+), 23 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/sprd,pcm-platform.yaml delete mode 100644 Documentation/devicetree/bindings/sound/sprd-pcm.txt diff --git a/Documentation/devicetree/bindings/sound/sprd,pcm-platform.yaml b/Documentation/devicetree/bindings/sound/sprd,pcm-platform.yaml new file mode 100644 index 00000000000000..c15c01bbb884af --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sprd,pcm-platform.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/sprd,pcm-platform.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Spreadtrum DMA platform + +maintainers: + - Orson Zhai + - Baolin Wang + - Chunyan Zhang + +properties: + compatible: + const: sprd,pcm-platform + + dmas: + maxItems: 10 + + dma-names: + items: + - const: normal_p_l + - const: normal_p_r + - const: normal_c_l + - const: normal_c_r + - const: voice_c + - const: fast_p + - const: loop_c + - const: loop_p + - const: voip_c + - const: voip_p + +required: + - compatible + - dmas + - dma-names + +additionalProperties: false + +examples: + - | + platform { + compatible = "sprd,pcm-platform"; + dmas = <&agcp_dma 1 1>, <&agcp_dma 2 2>, + <&agcp_dma 3 3>, <&agcp_dma 4 4>, + <&agcp_dma 5 5>, <&agcp_dma 6 6>, + <&agcp_dma 7 7>, <&agcp_dma 8 8>, + <&agcp_dma 9 9>, <&agcp_dma 10 10>; + dma-names = "normal_p_l", "normal_p_r", + "normal_c_l", "normal_c_r", + "voice_c", "fast_p", + "loop_c", "loop_p", + "voip_c", "voip_p"; + }; +... diff --git a/Documentation/devicetree/bindings/sound/sprd-pcm.txt b/Documentation/devicetree/bindings/sound/sprd-pcm.txt deleted file mode 100644 index fbbcade2181d80..00000000000000 --- a/Documentation/devicetree/bindings/sound/sprd-pcm.txt +++ /dev/null @@ -1,23 +0,0 @@ -* Spreadtrum DMA platform bindings - -Required properties: -- compatible: Should be "sprd,pcm-platform". -- dmas: Specify the list of DMA controller phandle and DMA request line ordered pairs. -- dma-names: Identifier string for each DMA request line in the dmas property. - These strings correspond 1:1 with the ordered pairs in dmas. - -Example: - - audio_platform:platform@0 { - compatible = "sprd,pcm-platform"; - dmas = <&agcp_dma 1 1>, <&agcp_dma 2 2>, - <&agcp_dma 3 3>, <&agcp_dma 4 4>, - <&agcp_dma 5 5>, <&agcp_dma 6 6>, - <&agcp_dma 7 7>, <&agcp_dma 8 8>, - <&agcp_dma 9 9>, <&agcp_dma 10 10>; - dma-names = "normal_p_l", "normal_p_r", - "normal_c_l", "normal_c_r", - "voice_c", "fast_p", - "loop_c", "loop_p", - "voip_c", "voip_p"; - }; From 310558120e5eaf48025c3947fc91b4d02bd90fac Mon Sep 17 00:00:00 2001 From: Stanislav Jakubek Date: Wed, 30 Oct 2024 18:49:22 +0100 Subject: [PATCH 43/53] ASoC: dt-bindings: sprd,sc9860-mcdt: convert to YAML Convert the Spreadtrum Multi-Channel Data Transfer controller bindings to DT schema. Adjust filename to match compatible. Signed-off-by: Stanislav Jakubek Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/140ee384c1c351ffa3abefa8dd3246d1625dda8d.1730310275.git.stano.jakubek@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/sprd,sc9860-mcdt.yaml | 47 +++++++++++++++++++ .../devicetree/bindings/sound/sprd-mcdt.txt | 19 -------- 2 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/sprd,sc9860-mcdt.yaml delete mode 100644 Documentation/devicetree/bindings/sound/sprd-mcdt.txt diff --git a/Documentation/devicetree/bindings/sound/sprd,sc9860-mcdt.yaml b/Documentation/devicetree/bindings/sound/sprd,sc9860-mcdt.yaml new file mode 100644 index 00000000000000..3b66bedeff9731 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sprd,sc9860-mcdt.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/sprd,sc9860-mcdt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Spreadtrum Multi-Channel Data Transfer controller + +description: + The Multi-channel data transfer controller is used for sound stream + transmission between the audio subsystem and other AP/CP subsystem. It + supports 10 DAC channels and 10 ADC channels, and each channel can be + configured with DMA mode or interrupt mode. + +maintainers: + - Orson Zhai + - Baolin Wang + - Chunyan Zhang + +properties: + compatible: + const: sprd,sc9860-mcdt + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + #include + + mcdt@41490000 { + compatible = "sprd,sc9860-mcdt"; + reg = <0x41490000 0x170>; + interrupts = ; + }; +... diff --git a/Documentation/devicetree/bindings/sound/sprd-mcdt.txt b/Documentation/devicetree/bindings/sound/sprd-mcdt.txt deleted file mode 100644 index 274ba0acbfd642..00000000000000 --- a/Documentation/devicetree/bindings/sound/sprd-mcdt.txt +++ /dev/null @@ -1,19 +0,0 @@ -Spreadtrum Multi-Channel Data Transfer Binding - -The Multi-channel data transfer controller is used for sound stream -transmission between audio subsystem and other AP/CP subsystem. It -supports 10 DAC channel and 10 ADC channel, and each channel can be -configured with DMA mode or interrupt mode. - -Required properties: -- compatible: Should be "sprd,sc9860-mcdt". -- reg: Should contain registers address and length. -- interrupts: Should contain one interrupt shared by all channel. - -Example: - -mcdt@41490000 { - compatible = "sprd,sc9860-mcdt"; - reg = <0 0x41490000 0 0x170>; - interrupts = ; -}; From 393de01870bcf2ea1eadd21ad12f927d78cbb726 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 1 Nov 2024 17:51:58 +0100 Subject: [PATCH 44/53] 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 --- 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 2e2e01493a5f4f..b9e33a7429b0c0 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,apq8096-sndcard From 4b9f02b6c5376b65dac398c4f06804c914cbb7be Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 1 Nov 2024 17:51:59 +0100 Subject: [PATCH 45/53] 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 --- 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 922ecada1cd8d9..3113773171761a 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -190,6 +190,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 adf7ea48ce05a6c5c44f0f9d3f81e83e5cb70c3e Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 28 Oct 2024 15:49:31 -0400 Subject: [PATCH 46/53] ASoC: dt-bindings: fsl-esai: allow fsl,imx8qm-esai fallback to fsl,imx6ull-esai The ESAI of i.MX8QM is the same as i.MX6ULL. So allow fsl,imx8qm-esai fallback to fsl,imx6ull-esai. Signed-off-by: Frank Li Acked-by: Rob Herring (Arm) Link: https://patch.msgid.link/20241028-esai_fix-v1-1-3c1432a5613c@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,esai.yaml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.yaml b/Documentation/devicetree/bindings/sound/fsl,esai.yaml index d1b4e23f1c95f5..27c34ce4c2e22a 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,esai.yaml @@ -18,11 +18,15 @@ description: properties: compatible: - enum: - - fsl,imx35-esai - - fsl,imx6ull-esai - - fsl,imx8qm-esai - - fsl,vf610-esai + oneOf: + - enum: + - fsl,imx35-esai + - fsl,imx6ull-esai + - fsl,vf610-esai + - items: + - enum: + - fsl,imx8qm-esai + - const: fsl,imx6ull-esai reg: maxItems: 1 From 08a3b241adfd90361c16c3e92f5275b816a73f04 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 5 Nov 2024 01:00:00 +0000 Subject: [PATCH 47/53] MAINTAINERS: Generic Sound Card section ALSA SoC Sound has Generic Sound Card (Simple-Card, Audio-Graph-Card, Audio-Graph-Card2). Adds its Maintainer. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ikt2a41c.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 9d6272c00fbd79..388626c3df1f64 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21697,6 +21697,15 @@ S: Supported W: https://github.com/thesofproject/linux/ F: sound/soc/sof/ +SOUND - GENERIC SOUND CARD (Simple-Audio-Card, Audio-Graph-Card) +M: Kuninori Morimoto +S: Supported +L: linux-sound@vger.kernel.org +F: sound/soc/generic/ +F: include/sound/simple_card* +F: Documentation/devicetree/bindings/sound/simple-card.yaml +F: Documentation/devicetree/bindings/sound/audio-graph*.yaml + SOUNDWIRE SUBSYSTEM M: Vinod Koul M: Bard Liao From 9bb4af400c386374ab1047df44c508512c08c31f Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Tue, 5 Nov 2024 15:02:42 +0100 Subject: [PATCH 48/53] ASoC: stm32: spdifrx: fix dma channel release in stm32_spdifrx_remove In case of error when requesting ctrl_chan DMA channel, ctrl_chan is not null. So the release of the dma channel leads to the following issue: [ 4.879000] st,stm32-spdifrx 500d0000.audio-controller: dma_request_slave_channel error -19 [ 4.888975] Unable to handle kernel NULL pointer dereference at virtual address 000000000000003d [...] [ 5.096577] Call trace: [ 5.099099] dma_release_channel+0x24/0x100 [ 5.103235] stm32_spdifrx_remove+0x24/0x60 [snd_soc_stm32_spdifrx] [ 5.109494] stm32_spdifrx_probe+0x320/0x4c4 [snd_soc_stm32_spdifrx] To avoid this issue, release channel only if the pointer is valid. Fixes: 794df9448edb ("ASoC: stm32: spdifrx: manage rebind issue") Signed-off-by: Amelie Delaunay Signed-off-by: Olivier Moysan Link: https://patch.msgid.link/20241105140242.527279-1-olivier.moysan@foss.st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_spdifrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index d1b32ba1e1a210..9e30852de93cdf 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -939,7 +939,7 @@ static void stm32_spdifrx_remove(struct platform_device *pdev) { struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); - if (spdifrx->ctrl_chan) + if (!IS_ERR(spdifrx->ctrl_chan)) dma_release_channel(spdifrx->ctrl_chan); if (spdifrx->dmab) From 93b763a5ab13509e9a2bcbcac3002607736e601b Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Tue, 5 Nov 2024 18:05:57 +0800 Subject: [PATCH 49/53] 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 --- 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 87354bb1564e8d..0abbd92cbc7e2a 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 f9f7512ca36087..908846e994df34 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 af23d38caae5841bd7aa754a7e7205ab719f568d Mon Sep 17 00:00:00 2001 From: Deep Harsora Date: Tue, 5 Nov 2024 19:10:56 +0800 Subject: [PATCH 50/53] ASoC: Intel: sof_sdw: Add missing quirks from some new Dell Add missing quirks for some new Dell laptops using cs42l43's speaker outputs. Signed-off-by: Deep Harsora Signed-off-by: Bard Liao Reviewed-by: Peter Ujfalusi Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20241105111057.182076-1-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 5614e706a0bbed..b12f700e842fd1 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -480,6 +480,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .driver_data = (void *)(SOF_SDW_TGL_HDMI | RT711_JD2), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF6") + }, + .driver_data = (void *)(SOC_SDW_CODEC_SPKR), + }, { .callback = sof_sdw_quirk_cb, .matches = { @@ -488,6 +496,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(SOC_SDW_CODEC_SPKR), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CFA") + }, + .driver_data = (void *)(SOC_SDW_CODEC_SPKR), + }, /* MeteorLake devices */ { .callback = sof_sdw_quirk_cb, @@ -572,6 +588,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(SOC_SDW_CODEC_SPKR), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D36") + }, + .driver_data = (void *)(SOC_SDW_CODEC_SPKR), + }, { .callback = sof_sdw_quirk_cb, .matches = { @@ -647,6 +671,30 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(SOC_SDW_CODEC_SPKR), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF3") + }, + .driver_data = (void *)(SOC_SDW_CODEC_SPKR), + }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF4") + }, + .driver_data = (void *)(SOC_SDW_CODEC_SPKR), + }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF5") + }, + .driver_data = (void *)(SOC_SDW_CODEC_SPKR), + }, /* Pantherlake devices*/ { .callback = sof_sdw_quirk_cb, From ed4bcfbcf45d02fa81c77cff86e914d71c1b3c1f Mon Sep 17 00:00:00 2001 From: Fei Shao Date: Tue, 5 Nov 2024 17:11:36 +0800 Subject: [PATCH 51/53] ASoC: dt-bindings: mediatek,mt8188-mt6359: Add mediatek,adsp property On some MediaTek SoCs, an Audio DSP (ADSP) is integrated as a separate hardware block that leverages Sound Open Firmware (SOF) and provides additional audio functionalities. This hardware is optional, and the audio subsystem will still function normally when it's not present. To enable ADSP support, a 'mediatek,adsp' property is required in the sound card node to pass the ADSP phandle. This allows AFE to link to ADSP when the sound card is probed. MT8188 has ADSP integrated, so add the 'mediatek,adsp' property to allow using it in the audio subsystem. This fixes dtbs_check error: Unevaluated properties are not allowed ('mediatek,adsp' was unexpected) Signed-off-by: Fei Shao Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20241105091246.3944946-1-fshao@chromium.org Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml index f94ad0715e3239..ba482747f0e664 100644 --- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml @@ -29,6 +29,13 @@ properties: $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8188 ASoC platform. + mediatek,adsp: + $ref: /schemas/types.yaml#/definitions/phandle + description: + The phandle of the MT8188 ADSP platform, which is the optional Audio DSP + hardware that provides additional audio functionalities if present. + The AFE will link to ADSP when the phandle is provided. + patternProperties: "^dai-link-[0-9]+$": type: object From b3cb7f2a3a1732a775861a2279d951e79c0e614c Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Tue, 5 Nov 2024 08:51:32 +0000 Subject: [PATCH 52/53] 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 --- 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 c0f8cccae3b2bb..c71453da088a01 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 bdd160b80b6465..1c9f32e405cf95 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 e2f071909da863..0a82c107b19a20 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 99348781d249817c8f96a7cbf636b7c6d74bd756 Mon Sep 17 00:00:00 2001 From: Fei Shao Date: Tue, 5 Nov 2024 17:18:11 +0800 Subject: [PATCH 53/53] ASoC: dt-bindings: everest,es8326: Document interrupt property The ES8326 audio codec has one interrupt pin for headset detection according to the datasheet. Document that in the binding. This fixes dtbs_check error: 'interrupts-extended' does not match any of the regexes: 'pinctrl-[0-9]+' Signed-off-by: Fei Shao Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20241105091910.3984381-1-fshao@chromium.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/everest,es8326.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/everest,es8326.yaml b/Documentation/devicetree/bindings/sound/everest,es8326.yaml index d51431df7acf9c..b5594a9d508e87 100644 --- a/Documentation/devicetree/bindings/sound/everest,es8326.yaml +++ b/Documentation/devicetree/bindings/sound/everest,es8326.yaml @@ -24,6 +24,10 @@ properties: items: - const: mclk + interrupts: + maxItems: 1 + description: interrupt output for headset detection + "#sound-dai-cells": const: 0