sound fixes for 7.1-rc5

As expected, we still continue receiving lots of small fixes.
 One major change is about HD-audio pending IRQ handling, but this
 would influence only on odd machines or slow VMs.  There are a few
 other fixes for the core part, but most of them are not-too-serious
 UAF fixes, while the rest are mostly device-specific fixes and quirks.
 
 ALSA Core:
 - Fix for PCM silencing with bogus iov_iter
 - Fixes for past-the-end iterators in timer and seq
 - Serialization of UMP output teardown
 - Rate-limit ELD parsing errors
 
 HD-audio:
 - Fixes for IRQ work handling and SSID matching
 - Various Realtek quirks for HP and ASUS laptops, including LED fixes
 
 ASoC:
 - Intel: ACPI match table updates for PTL, NVL, and ARL platforms
 - Cirrus Logic: Fixes for cs-amp-lib and cs35l56 codecs
 - Various platform fixes for AMD, FSL SAI, TI OMAP, and Qualcomm
 - DT-binding fix for MediaTek
 
 Others:
 - USB ua101: Reject too-short USB descriptors
 - Scarlett2: Fix for flash writes
 - ASIHPI: Fix for potential OOB access
 - AMD SPI: Fix for bus number in ACPI probe
 
 MAINTAINERS:
 - Updates for SOF and TI maintainers
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmoQGYEOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE++khAAxtTrTwq5GZMAA0C1OMBI9SxclGABBTaMMkYD
 lXjX7z/59Iw5YMkIuKEPZUn9Q9huoTd9vgfWUgCANP5zRGO63Tm+jottFco8w+YU
 KrOvBjy8kQ9GOjrN5Hoy8DKz1tJBz8SXQW08/GEL1gUqHdgxJjunAiYXcTJ+A3jo
 yL5GASW+C/G1sErpC+ixAlnRRnjt8PP4xtX05BtSQMw4hsEtlalBR20VqCKwUNpi
 9T2wxxB8+GwybeFE+3KTl2T3IsFPtUiqDfph54MW+9GaYGVcmxKR98Cs0EAx+ABZ
 XgnwofwTOSMOfpmjSBG4oCVyWL7RPd8thjcT52qrYECPLWiPwguvO0tc2dnWIiFN
 m1qsZh7lCEiROZ6ZRefQTLWTHzs/yo2oW41I+owJCERyw23IzuCJm2+JvCyepz4h
 wBxdnr6lC8DimwAOaqHM0eSmPLBGz//YW+lHwkVIsMMjEhCexm0BVDSjhh1beC0N
 NijeMeIDVj666hs41AcejWqOutSm37amWaCSpfiWNWqE6tJljPny+p9qwgzunb4d
 /NLxNSPIQaohQJ12axSR3fMU7FgMK56hzbb3x4t/da++JfJOviOA01zJq3oaHMOK
 XIpqt5W5c/mNRJWvnOKFXNbOGpLmfsI8ox7mbqZdHFpvqzpK2VDw6jQRMbagPZFL
 nOjwHWE=
 =7KbQ
 -----END PGP SIGNATURE-----

Merge tag 'sound-7.1-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "As expected, we still continue receiving lots of small fixes.

  One major change is about HD-audio pending IRQ handling, but this
  would influence only on odd machines or slow VMs. There are a few
  other fixes for the core part, but most of them are not-too-serious
  UAF fixes, while the rest are mostly device-specific fixes and quirks.

  ALSA Core:
   - Fix for PCM silencing with bogus iov_iter
   - Fixes for past-the-end iterators in timer and seq
   - Serialization of UMP output teardown
   - Rate-limit ELD parsing errors

  HD-audio:
   - Fixes for IRQ work handling and SSID matching
   - Various Realtek quirks for HP and ASUS laptops, including LED fixes

  ASoC:
   - Intel: ACPI match table updates for PTL, NVL, and ARL platforms
   - Cirrus Logic: Fixes for cs-amp-lib and cs35l56 codecs
   - Various platform fixes for AMD, FSL SAI, TI OMAP, and Qualcomm
   - DT-binding fix for MediaTek

  Others:
   - USB ua101: Reject too-short USB descriptors
   - Scarlett2: Fix for flash writes
   - ASIHPI: Fix for potential OOB access
   - AMD SPI: Fix for bus number in ACPI probe

  MAINTAINERS:
   - Updates for SOF and TI maintainers"

* tag 'sound-7.1-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (47 commits)
  ASoC: codecs: pcm512x: fix null-ptr dereference in pcm512x_overclock_xxx_put()
  ASoC: Intel: soc-acpi-intel-ptl-match: Remove unnecessary cs42l43 match
  ASoC: soc-acpi-intel-ptl-match: Make Chrome matches conditional
  ASoC: Intel: soc-acpi: Add entry for sof_es8336 in NVL match table.
  ASoC: Intel: sof_sdw: Add support for nvlrvp in NVL platform
  ASoC: cs-amp-lib: Fix typo in error message: write -> read
  ASoC: cs-amp-lib: Fix missing dput() after debugfs_lookup()
  ASoC: cs-amp-lib: Fix wrong sizeof() in _cs_amp_set_efi_calibration_data()
  ASoC: cs35l56: Fix flushing of IRQ work in cs35l56_sdw_remove()
  MAINTAINERS: ASoC: Intel/SOF: Remove Ranjani Sridharan as maintainer
  ALSA: seq: Serialize UMP output teardown with event_input
  ALSA: scarlett2: Allow flash writes ending at segment boundary
  ALSA: hda/realtek: Add LED quirk for HP ProBook 430 G6
  ALSA: hda/intel: Make sure to cancel irq-pending work at closing PCM stream
  ALSA: hda: Move irq pending work into hda-intel stream
  ASoC: soc-utils: Add missing va_end in snd_soc_ret()
  ALSA: ua101: Reject too-short USB descriptors
  ALSA: hda/realtek: Fix mute and mic-mute LEDs for HP 16 Piston OmniBook X
  ALSA: seq: avoid past-the-end iterator in snd_seq_create_port()
  ALSA: timer: avoid past-the-end iterator in snd_timer_dev_register()
  ...
This commit is contained in:
Linus Torvalds 2026-05-22 12:22:22 -07:00
commit c22407252a
37 changed files with 384 additions and 259 deletions

View File

@ -18,7 +18,9 @@ properties:
description: Phandles of rt5650 and rt5514 codecs
items:
- description: phandle of rt5650 codec
maxItems: 1
- description: phandle of rt5514 codec
maxItems: 1
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle

View File

@ -12791,7 +12791,6 @@ M: Cezary Rojewski <cezary.rojewski@intel.com>
M: Liam Girdwood <liam.r.girdwood@linux.intel.com>
M: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
M: Bard Liao <yung-chuan.liao@linux.intel.com>
M: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
M: Kai Vehmanen <kai.vehmanen@linux.intel.com>
R: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
L: linux-sound@vger.kernel.org
@ -19462,7 +19461,6 @@ F: include/misc/ocxl*
F: include/uapi/misc/ocxl.h
OMAP AUDIO SUPPORT
M: Peter Ujfalusi <peter.ujfalusi@gmail.com>
M: Jarkko Nikula <jarkko.nikula@bitmer.com>
L: linux-sound@vger.kernel.org
L: linux-omap@vger.kernel.org
@ -25070,7 +25068,6 @@ SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS
M: Liam Girdwood <lgirdwood@gmail.com>
M: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
M: Bard Liao <yung-chuan.liao@linux.intel.com>
M: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
M: Daniel Baluta <daniel.baluta@nxp.com>
R: Kai Vehmanen <kai.vehmanen@linux.intel.com>
R: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
@ -26363,7 +26360,7 @@ F: arch/xtensa/
F: drivers/irqchip/irq-xtensa-*
TEXAS INSTRUMENTS ASoC DRIVERS
M: Peter Ujfalusi <peter.ujfalusi@gmail.com>
M: Sen Wang <sen@ti.com>
L: linux-sound@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
@ -26865,12 +26862,6 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
F: drivers/iio/adc/ti-tsc2046.c
TI TWL4030 SERIES SOC CODEC DRIVER
M: Peter Ujfalusi <peter.ujfalusi@gmail.com>
L: linux-sound@vger.kernel.org
S: Maintained
F: sound/soc/codecs/twl4030*
TI VPE/CAL DRIVERS
M: Yemike Abhilash Chandra <y-abhilashchandra@ti.com>
L: linux-media@vger.kernel.org

View File

@ -868,7 +868,7 @@ static int amd_spi_probe(struct platform_device *pdev)
dev_dbg(dev, "io_remap_address: %p\n", amd_spi->io_remap_addr);
amd_spi->version = (uintptr_t)device_get_match_data(dev);
host->bus_num = 0;
host->bus_num = (amd_spi->version == AMD_HID2_SPI) ? 2 : 0;
return amd_spi_probe_common(dev, host);
}

View File

@ -334,7 +334,7 @@ int snd_parse_eld(struct device *dev, struct snd_parsed_hdmi_eld *e,
e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
if (e->eld_ver != ELD_VER_CEA_861D &&
e->eld_ver != ELD_VER_PARTIAL) {
dev_info(dev, "HDMI: Unknown ELD version %d\n", e->eld_ver);
dev_info_ratelimited(dev, "HDMI: Unknown ELD version %d\n", e->eld_ver);
goto out_fail;
}
@ -357,7 +357,7 @@ int snd_parse_eld(struct device *dev, struct snd_parsed_hdmi_eld *e,
e->product_id = get_unaligned_le16(buf + 18);
if (mnl > ELD_MAX_MNL) {
dev_info(dev, "HDMI: MNL is reserved value %d\n", mnl);
dev_info_ratelimited(dev, "HDMI: MNL is reserved value %d\n", mnl);
goto out_fail;
} else if (ELD_FIXED_BYTES + mnl > size) {
dev_info(dev, "HDMI: out of range MNL %d\n", mnl);

View File

@ -2138,6 +2138,9 @@ static int interleaved_copy(struct snd_pcm_substream *substream,
off = frames_to_bytes(runtime, off);
frames = frames_to_bytes(runtime, frames);
if (!data)
return fill_silence(substream, 0, hwoff, NULL, frames);
return do_transfer(substream, 0, hwoff, data + off, frames, transfer,
in_kernel);
}

View File

@ -144,18 +144,21 @@ int snd_seq_create_port(struct snd_seq_client *client, int port,
num = max(port, 0);
guard(mutex)(&client->ports_mutex);
guard(write_lock_irq)(&client->ports_lock);
struct list_head *insert_before = &client->ports_list_head;
list_for_each_entry(p, &client->ports_list_head, list) {
if (p->addr.port == port) {
kfree(new_port);
return -EBUSY;
}
if (p->addr.port > num)
if (p->addr.port > num) {
insert_before = &p->list;
break;
}
if (port < 0) /* auto-probe mode */
num = p->addr.port + 1;
}
/* insert the new port */
list_add_tail(&new_port->list, &p->list);
list_add_tail(&new_port->list, insert_before);
client->num_ports++;
new_port->addr.port = num; /* store the port number in the port */
sprintf(new_port->name, "port-%d", num);

View File

@ -37,6 +37,7 @@ struct seq_ump_client {
struct snd_ump_endpoint *ump; /* assigned endpoint */
int seq_client; /* sequencer client id */
int opened[2]; /* current opens for each direction */
rwlock_t output_lock; /* protects out_rfile output access */
struct snd_rawmidi_file out_rfile; /* rawmidi for output */
struct seq_ump_input_buffer input; /* input parser context */
void *ump_info[SNDRV_UMP_MAX_BLOCKS + 1]; /* shadow of seq client ump_info */
@ -88,6 +89,7 @@ static int seq_ump_process_event(struct snd_seq_event *ev, int direct,
unsigned char type;
int len;
guard(read_lock_irqsave)(&client->output_lock);
substream = client->out_rfile.output;
if (!substream)
return -ENODEV;
@ -106,6 +108,7 @@ static int seq_ump_process_event(struct snd_seq_event *ev, int direct,
static int seq_ump_client_open(struct seq_ump_client *client, int dir)
{
struct snd_ump_endpoint *ump = client->ump;
struct snd_rawmidi_file rfile = {};
int err;
guard(mutex)(&ump->open_mutex);
@ -113,9 +116,11 @@ static int seq_ump_client_open(struct seq_ump_client *client, int dir)
err = snd_rawmidi_kernel_open(&ump->core, 0,
SNDRV_RAWMIDI_LFLG_OUTPUT |
SNDRV_RAWMIDI_LFLG_APPEND,
&client->out_rfile);
&rfile);
if (err < 0)
return err;
scoped_guard(write_lock_irqsave, &client->output_lock)
client->out_rfile = rfile;
}
client->opened[dir]++;
return 0;
@ -125,11 +130,19 @@ static int seq_ump_client_open(struct seq_ump_client *client, int dir)
static int seq_ump_client_close(struct seq_ump_client *client, int dir)
{
struct snd_ump_endpoint *ump = client->ump;
struct snd_rawmidi_file rfile = {};
guard(mutex)(&ump->open_mutex);
if (!--client->opened[dir])
if (dir == STR_OUT)
snd_rawmidi_kernel_release(&client->out_rfile);
if (!--client->opened[dir]) {
if (dir == STR_OUT) {
scoped_guard(write_lock_irqsave, &client->output_lock) {
rfile = client->out_rfile;
client->out_rfile = (struct snd_rawmidi_file){};
}
if (rfile.rmidi)
snd_rawmidi_kernel_release(&rfile);
}
}
return 0;
}
@ -467,6 +480,7 @@ static int snd_seq_ump_probe(struct snd_seq_device *dev)
INIT_WORK(&client->group_notify_work, handle_group_notify);
client->ump = ump;
rwlock_init(&client->output_lock);
client->seq_client =
snd_seq_create_kernel_client(card, ump->core.device,

View File

@ -1007,6 +1007,7 @@ static int snd_timer_dev_register(struct snd_device *dev)
{
struct snd_timer *timer = dev->device_data;
struct snd_timer *timer1;
struct list_head *insert_before = &snd_timer_list;
if (snd_BUG_ON(!timer || !timer->hw.start || !timer->hw.stop))
return -ENXIO;
@ -1016,28 +1017,36 @@ static int snd_timer_dev_register(struct snd_device *dev)
guard(mutex)(&register_mutex);
list_for_each_entry(timer1, &snd_timer_list, device_list) {
if (timer1->tmr_class > timer->tmr_class)
if (timer1->tmr_class > timer->tmr_class) {
insert_before = &timer1->device_list;
break;
}
if (timer1->tmr_class < timer->tmr_class)
continue;
if (timer1->card && timer->card) {
if (timer1->card->number > timer->card->number)
if (timer1->card->number > timer->card->number) {
insert_before = &timer1->device_list;
break;
}
if (timer1->card->number < timer->card->number)
continue;
}
if (timer1->tmr_device > timer->tmr_device)
if (timer1->tmr_device > timer->tmr_device) {
insert_before = &timer1->device_list;
break;
}
if (timer1->tmr_device < timer->tmr_device)
continue;
if (timer1->tmr_subdevice > timer->tmr_subdevice)
if (timer1->tmr_subdevice > timer->tmr_subdevice) {
insert_before = &timer1->device_list;
break;
}
if (timer1->tmr_subdevice < timer->tmr_subdevice)
continue;
/* conflicts.. */
return -EBUSY;
}
list_add_tail(&timer->device_list, &timer1->device_list);
list_add_tail(&timer->device_list, insert_before);
return 0;
}

View File

@ -6955,6 +6955,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
SND_PCI_QUIRK(0x103c, 0x8536, "HP ProBook 430 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8537, "HP ProBook 440 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8548, "HP EliteBook x360 830 G6", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x854a, "HP EliteBook 830 G6", ALC285_FIXUP_HP_GPIO_LED),
@ -7084,6 +7085,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8a30, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8a31, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8a34, "HP Pavilion x360 2-in-1 Laptop 14-ek0xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x8a36, "HP Pavilion Plus 14-eh0xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x8a3d, "HP Victus 15-fb0xxx (MB 8A3D)", ALC245_FIXUP_HP_MUTE_LED_V2_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x8a4f, "HP Victus 15-fa0xxx (MB 8A4F)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x8a6e, "HP EDNA 360", ALC287_FIXUP_CS35L41_I2C_4),
@ -7103,6 +7105,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8ad8, "HP 800 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b0f, "HP Elite mt645 G7 Mobile Thin Client U81", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b2f, "HP 255 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8b34, "HP 250 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8b3a, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8b3f, "HP mt440 Mobile Thin Client U91", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b42, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
@ -7229,7 +7232,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8da0, "HP 16 Clipper OmniBook 7(X360)", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8da1, "HP 16 Clipper OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8da7, "HP 14 Enstrom OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8da8, "HP 16 Piston OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8da8, "HP 16 Piston OmniBook X", ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX),
SND_PCI_QUIRK(0x103c, 0x8dc9, "HP Laptop 15-fc0xxx", ALC236_FIXUP_HP_DMIC),
SND_PCI_QUIRK(0x103c, 0x8dd4, "HP EliteStudio 8 AIO", ALC274_FIXUP_HP_AIO_BIND_DACS),
SND_PCI_QUIRK(0x103c, 0x8dd7, "HP Laptop 15-fd0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
@ -7241,6 +7244,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8def, "HP EliteBook 660 G12", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8df0, "HP EliteBook 630 G12", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8df1, "HP EliteBook 630 G12", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8df7, "HP Z66 G6", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8dfb, "HP EliteBook 6 G1a 14", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8dfc, "HP EliteBook 645 G12", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8dfd, "HP EliteBook 6 G1a 16", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
@ -7453,12 +7457,12 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x3e00, "ASUS G814FH/FM/FP", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x3e20, "ASUS G814PH/PM/PP", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x3e30, "ASUS TP3607SA", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3ee0, "ASUS Strix G815_JHR_JMR_JPR", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3ef0, "ASUS Strix G635LR_LW_LX", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3f00, "ASUS Strix G815LH_LM_LP", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3f10, "ASUS Strix G835LR_LW_LX", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3f20, "ASUS Strix G615LR_LW", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3f30, "ASUS Strix G815LR_LW", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3ee0, "ASUS Strix G815_JHR_JMR_JPR", ALC287_FIXUP_TXNW2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3ef0, "ASUS Strix G635LR_LW_LX", ALC287_FIXUP_TXNW2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3f00, "ASUS Strix G815LH_LM_LP", ALC287_FIXUP_TXNW2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3f10, "ASUS Strix G835LR_LW_LX", ALC287_FIXUP_TXNW2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3f20, "ASUS Strix G615LR_LW", ALC287_FIXUP_TXNW2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3f30, "ASUS Strix G815LR_LW", ALC287_FIXUP_TXNW2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3fd0, "ASUS B3605CVA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x3ff0, "ASUS B5405CVA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),

View File

@ -1013,7 +1013,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
const char *name = NULL;
const char *type = NULL;
unsigned int vendor, device;
u16 pci_vendor, pci_device;
u16 pci_vendor = 0, pci_device = 0;
u16 codec_vendor, codec_device;
if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
@ -1066,7 +1066,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
/* match primarily with the PCI SSID */
for (q = quirk; q->subvendor || q->subdevice; q++) {
/* if the entry is specific to codec SSID, check with it */
if (!codec->bus->pci || q->match_codec_ssid) {
if (!pci_vendor || !pci_device || q->match_codec_ssid) {
if (hda_quirk_match(codec_vendor, codec_device, q)) {
type = "codec SSID";
goto found_device;

View File

@ -97,6 +97,8 @@ static int azx_pcm_close(struct snd_pcm_substream *substream)
trace_azx_pcm_close(chip, azx_dev);
scoped_guard(mutex, &chip->open_mutex) {
if (chip->ops->pcm_close)
chip->ops->pcm_close(chip, azx_dev);
azx_release_device(azx_dev);
if (hinfo->ops.close)
hinfo->ops.close(hinfo, apcm->codec, substream);
@ -1264,19 +1266,17 @@ int azx_codec_configure(struct azx *chip)
}
EXPORT_SYMBOL_GPL(azx_codec_configure);
static int stream_direction(struct azx *chip, unsigned char index)
void azx_add_stream(struct azx *chip, struct azx_dev *azx_dev, int idx, int tag)
{
if (index >= chip->capture_index_offset &&
index < chip->capture_index_offset + chip->capture_streams)
return SNDRV_PCM_STREAM_CAPTURE;
return SNDRV_PCM_STREAM_PLAYBACK;
snd_hdac_stream_init(azx_bus(chip), azx_stream(azx_dev), idx,
azx_stream_direction(chip, idx), tag);
}
EXPORT_SYMBOL_GPL(azx_add_stream);
/* initialize SD streams */
int azx_init_streams(struct azx *chip)
{
int i;
int stream_tags[2] = { 0, 0 };
/* initialize each stream (aka device)
* assign the starting bdl address to each stream (device)
@ -1284,24 +1284,10 @@ int azx_init_streams(struct azx *chip)
*/
for (i = 0; i < chip->num_streams; i++) {
struct azx_dev *azx_dev = kzalloc_obj(*azx_dev);
int dir, tag;
if (!azx_dev)
return -ENOMEM;
dir = stream_direction(chip, i);
/* stream tag must be unique throughout
* the stream direction group,
* valid values 1...15
* use separate stream tag if the flag
* AZX_DCAPS_SEPARATE_STREAM_TAG is used
*/
if (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG)
tag = ++stream_tags[dir];
else
tag = i + 1;
snd_hdac_stream_init(azx_bus(chip), azx_stream(azx_dev),
i, dir, tag);
azx_add_stream(chip, azx_dev, i, i + 1);
}
return 0;

View File

@ -57,13 +57,12 @@ enum {
struct azx_dev {
struct hdac_stream core;
unsigned int irq_pending:1;
/*
* For VIA:
* A flag to ensure DMA position is 0
* when link position is not greater than FIFO size
*/
unsigned int insufficient:1;
bool insufficient;
};
#define azx_stream(dev) (&(dev)->core)
@ -79,6 +78,8 @@ struct hda_controller_ops {
int (*position_check)(struct azx *chip, struct azx_dev *azx_dev);
/* enable/disable the link power */
int (*link_power)(struct azx *chip, bool enable);
/* additional hook for PCM */
void (*pcm_close)(struct azx *chip, struct azx_dev *azx_dev);
};
struct azx_pcm {
@ -206,6 +207,15 @@ int azx_bus_init(struct azx *chip, const char *model);
int azx_probe_codecs(struct azx *chip, unsigned int max_slots);
int azx_codec_configure(struct azx *chip);
int azx_init_streams(struct azx *chip);
void azx_add_stream(struct azx *chip, struct azx_dev *s, int idx, int tag);
void azx_free_streams(struct azx *chip);
static inline int azx_stream_direction(struct azx *chip, unsigned char index)
{
if (index >= chip->capture_index_offset &&
index < chip->capture_index_offset + chip->capture_streams)
return SNDRV_PCM_STREAM_CAPTURE;
return SNDRV_PCM_STREAM_PLAYBACK;
}
#endif /* __SOUND_HDA_CONTROLLER_H */

View File

@ -615,17 +615,17 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
/* called from IRQ */
static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
{
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
struct hda_intel_stream *istream = azx_dev_to_istream(azx_dev);
int ok;
ok = azx_position_ok(chip, azx_dev);
if (ok == 1) {
azx_dev->irq_pending = 0;
istream->irq_pending = false;
return ok;
} else if (ok == 0) {
/* bogus IRQ, process it later */
azx_dev->irq_pending = 1;
schedule_work(&hda->irq_pending_work);
istream->irq_pending = true;
schedule_work(&istream->irq_pending_work);
}
return 0;
}
@ -721,11 +721,13 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
*/
static void azx_irq_pending_work(struct work_struct *work)
{
struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work);
struct hda_intel_stream *istream =
container_of(work, struct hda_intel_stream, irq_pending_work);
struct azx_dev *azx_dev = &istream->azx_dev;
struct hda_intel *hda = istream->hda;
struct azx *chip = &hda->chip;
struct hdac_bus *bus = azx_bus(chip);
struct hdac_stream *s;
int pending, ok;
int ok;
if (!hda->irq_pending_warned) {
dev_info(chip->card->dev,
@ -735,42 +737,51 @@ static void azx_irq_pending_work(struct work_struct *work)
}
for (;;) {
pending = 0;
spin_lock_irq(&bus->reg_lock);
list_for_each_entry(s, &bus->stream_list, list) {
struct azx_dev *azx_dev = stream_to_azx_dev(s);
if (!azx_dev->irq_pending ||
!s->substream ||
!s->running)
continue;
scoped_guard(spinlock_irq, &bus->reg_lock) {
if (!istream->irq_pending ||
!azx_dev->core.substream ||
!azx_dev->core.running) {
return;
}
ok = azx_position_ok(chip, azx_dev);
if (ok > 0) {
azx_dev->irq_pending = 0;
spin_unlock(&bus->reg_lock);
snd_pcm_period_elapsed(s->substream);
spin_lock(&bus->reg_lock);
} else if (ok < 0) {
pending = 0; /* too early */
} else
pending++;
if (ok < 0)
return; /* too early */
if (ok > 0)
istream->irq_pending = false;
}
spin_unlock_irq(&bus->reg_lock);
if (!pending)
if (ok) {
snd_pcm_period_elapsed(azx_dev->core.substream);
return;
}
msleep(1);
}
}
/* clear irq_pending flags and assure no on-going workq */
static void hda_intel_stream_clear_irq_pending(struct azx_dev *azx_dev)
{
struct hda_intel_stream *istream = azx_dev_to_istream(azx_dev);
istream->irq_pending = false;
cancel_work_sync(&istream->irq_pending_work);
}
/* called at PCM close */
static void hda_intel_pcm_close(struct azx *chip, struct azx_dev *azx_dev)
{
hda_intel_stream_clear_irq_pending(azx_dev);
}
static void azx_clear_irq_pending(struct azx *chip)
{
struct hdac_bus *bus = azx_bus(chip);
struct hdac_stream *s;
guard(spinlock_irq)(&bus->reg_lock);
list_for_each_entry(s, &bus->stream_list, list) {
struct azx_dev *azx_dev = stream_to_azx_dev(s);
azx_dev->irq_pending = 0;
hda_intel_stream_clear_irq_pending(stream_to_azx_dev(s));
}
}
@ -1797,7 +1808,6 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
if (jackpoll_ms[dev] >= 50 && jackpoll_ms[dev] <= 60000)
chip->jackpoll_interval = msecs_to_jiffies(jackpoll_ms[dev]);
INIT_LIST_HEAD(&chip->pcm_list);
INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work);
INIT_LIST_HEAD(&hda->list);
init_vga_switcheroo(chip);
init_completion(&hda->probe_wait);
@ -1846,6 +1856,39 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
return 0;
}
/* create and assign streams */
static int hda_init_streams(struct azx *chip)
{
int i;
int stream_tags[2] = { 0, 0 };
for (i = 0; i < chip->num_streams; i++) {
struct hda_intel_stream *s = kzalloc_obj(*s);
int tag, dir;
if (!s)
return -ENOMEM;
s->hda = container_of(chip, struct hda_intel, chip);
INIT_WORK(&s->irq_pending_work, azx_irq_pending_work);
/* stream tag must be unique throughout
* the stream direction group,
* valid values 1...15
* use separate stream tag if the flag
* AZX_DCAPS_SEPARATE_STREAM_TAG is used
*/
dir = azx_stream_direction(chip, i);
if (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG)
tag = ++stream_tags[dir];
else
tag = i + 1;
azx_add_stream(chip, &s->azx_dev, i, tag);
}
return 0;
}
static int azx_first_init(struct azx *chip)
{
int dev = chip->dev_index;
@ -2000,7 +2043,7 @@ static int azx_first_init(struct azx *chip)
}
/* initialize streams */
err = azx_init_streams(chip);
err = hda_init_streams(chip);
if (err < 0)
return err;
@ -2099,6 +2142,7 @@ static const struct dmi_system_id driver_denylist_dmi[] = {
static const struct hda_controller_ops pci_hda_ops = {
.disable_msi_reset_irq = disable_msi_reset_irq,
.position_check = azx_position_check,
.pcm_close = hda_intel_pcm_close,
};
static DECLARE_BITMAP(probed_devs, SNDRV_CARDS);

View File

@ -9,9 +9,6 @@
struct hda_intel {
struct azx chip;
/* for pending irqs */
struct work_struct irq_pending_work;
/* sync probing */
struct completion probe_wait;
struct delayed_work probe_work;
@ -35,4 +32,16 @@ struct hda_intel {
int probe_retry; /* being probe-retry */
};
struct hda_intel_stream {
struct azx_dev azx_dev;
/* for pending irqs */
struct hda_intel *hda;
struct work_struct irq_pending_work;
bool irq_pending;
};
#define azx_dev_to_istream(azx_dev) \
container_of(azx_dev, struct hda_intel_stream, azx_dev)
#endif

View File

@ -276,6 +276,12 @@ static short find_control(u16 control_index,
return 0;
}
if (control_index >= p_cache->control_count) {
HPI_DEBUG_LOG(VERBOSE, "control_index out of bounce %d\n",
control_index);
return 0;
}
*pI = p_cache->p_info[control_index];
if (!*pI) {
HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",

View File

@ -30,6 +30,13 @@ static const struct dmi_system_id acp70_acpi_flag_override_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "HN7306EA"),
},
},
{
/* ASUS Zenbook S16 UM5606GA (Strix Point, ACP 7.0) */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "Zenbook S16 UM5606GA"),
},
},
{}
};

View File

@ -260,9 +260,9 @@ static int create_sdw_dailink(struct snd_soc_card *card,
cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
"SDW%d Pin%d",
link_num, cpu_pin_id);
dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name);
if (!cpus->dai_name)
return -ENOMEM;
dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name);
codec_maps[j].cpu = 0;
codec_maps[j].codec = j;

View File

@ -898,7 +898,6 @@ menu "CS35L56 driver options"
config SND_SOC_CS35L56_CAL_DEBUGFS
bool "CS35L56 create debugfs for factory calibration"
default N
depends on DEBUG_FS
select SND_SOC_CS35L56_CAL_DEBUGFS_COMMON
help
@ -909,7 +908,6 @@ config SND_SOC_CS35L56_CAL_DEBUGFS
config SND_SOC_CS35L56_CAL_SET_CTRL
bool "CS35L56 ALSA control to restore factory calibration"
default N
select SND_SOC_CS35L56_CAL_DEBUGFS_COMMON
help
Allow restoring factory calibration data through an ALSA
@ -923,7 +921,6 @@ config SND_SOC_CS35L56_CAL_SET_CTRL
config SND_SOC_CS35L56_CAL_PERFORM_CTRL
bool "CS35L56 ALSA control to perform factory calibration"
default N
select SND_SOC_CS35L56_CAL_DEBUGFS_COMMON
help
Allow performing factory calibration data through an ALSA

View File

@ -118,7 +118,7 @@ static int cs_amp_read_cal_coeff(struct cs_dsp *dsp,
}
if (ret < 0) {
dev_err(dsp->dev, "Failed to write to '%s': %d\n", ctl_name, ret);
dev_err(dsp->dev, "Failed to read '%s': %d\n", ctl_name, ret);
return ret;
}
@ -500,7 +500,7 @@ static int _cs_amp_set_efi_calibration_data(struct device *dev, int amp_index, i
* must be set.
*/
if (data->count == 0)
data->count = (data->size - sizeof(data)) / sizeof(data->data[0]);
data->count = (data->size - struct_offset(data, data)) / sizeof(data->data[0]);
if (amp_index < 0) {
/* Is there already a slot for this target? */
@ -833,11 +833,18 @@ EXPORT_SYMBOL_NS_GPL(cs_amp_devm_get_vendor_specific_variant_id, "SND_SOC_CS_AMP
*/
struct dentry *cs_amp_create_debugfs(struct device *dev)
{
struct dentry *dir;
struct dentry *dir, *created;
/* debugfs_lookup() can return NULL or ERR_PTR on error */
dir = debugfs_lookup("cirrus_logic", NULL);
if (!dir)
dir = debugfs_create_dir("cirrus_logic", NULL);
if (!IS_ERR_OR_NULL(dir)) {
created = debugfs_create_dir(dev_name(dev), dir);
dput(dir);
return created;
}
dir = debugfs_create_dir("cirrus_logic", NULL);
return debugfs_create_dir(dev_name(dev), dir);
}

View File

@ -385,18 +385,19 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral,
switch (status) {
case SDW_SLAVE_ATTACHED:
dev_dbg(cs35l56->base.dev, "%s: ATTACHED\n", __func__);
cs35l56->sdw_in_clock_stop_1 = false;
if (cs35l56->sdw_attached)
break;
dev_dbg(cs35l56->base.dev, "%s: ATTACHED\n", __func__);
if (!cs35l56->base.init_done || cs35l56->soft_resetting)
cs35l56_sdw_init(peripheral);
cs35l56->sdw_attached = true;
break;
case SDW_SLAVE_UNATTACHED:
dev_dbg(cs35l56->base.dev, "%s: UNATTACHED\n", __func__);
if (cs35l56->sdw_attached)
dev_dbg(cs35l56->base.dev, "%s: UNATTACHED\n", __func__);
cs35l56->sdw_attached = false;
break;
default:
@ -584,10 +585,11 @@ static void cs35l56_sdw_remove(struct sdw_slave *peripheral)
/* Disable SoundWire interrupts */
cs35l56->sdw_irq_no_unmask = true;
cancel_work_sync(&cs35l56->sdw_irq_work);
flush_work(&cs35l56->sdw_irq_work);
sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0);
sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1);
sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF);
flush_work(&cs35l56->sdw_irq_work);
cs35l56_remove(cs35l56);
}

View File

@ -867,11 +867,16 @@ static void cs35l56_dsp_work(struct work_struct *work)
if (!cs35l56->base.init_done)
return;
pm_runtime_get_sync(cs35l56->base.dev);
PM_RUNTIME_ACQUIRE(cs35l56->base.dev, pm);
ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
if (ret) {
dev_err(cs35l56->base.dev, "dsp_work failed to runtime-resume: %d\n", ret);
return;
}
ret = cs35l56_read_prot_status(&cs35l56->base, &firmware_missing, &firmware_version);
if (ret)
goto err;
return;
/* Populate fw file qualifier with the revision and security state */
kfree(cs35l56->dsp.fwf_name);
@ -887,7 +892,7 @@ static void cs35l56_dsp_work(struct work_struct *work)
}
if (!cs35l56->dsp.fwf_name)
goto err;
return;
dev_dbg(cs35l56->base.dev, "DSP fwf name: '%s' system name: '%s'\n",
cs35l56->dsp.fwf_name, cs35l56->dsp.system_name);
@ -905,8 +910,6 @@ static void cs35l56_dsp_work(struct work_struct *work)
cs35l56_patch(cs35l56, firmware_missing);
cs35l56_log_tuning(&cs35l56->base, &cs35l56->dsp.cs_dsp);
err:
pm_runtime_put_autosuspend(cs35l56->base.dev);
}
static struct snd_soc_dapm_context *cs35l56_power_up_for_cal(struct cs35l56_private *cs35l56)

View File

@ -968,7 +968,7 @@ static int fs210x_effect_scene_info(struct snd_kcontrol *kcontrol,
if (scene->name)
name = scene->name;
strscpy(uinfo->value.enumerated.name, name, strlen(name) + 1);
strscpy(uinfo->value.enumerated.name, name);
return 0;
}

View File

@ -235,7 +235,7 @@ static int pcm512x_overclock_pll_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
switch (snd_soc_dapm_get_bias_level(dapm)) {
@ -264,7 +264,7 @@ static int pcm512x_overclock_dsp_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
switch (snd_soc_dapm_get_bias_level(dapm)) {
@ -293,7 +293,7 @@ static int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
switch (snd_soc_dapm_get_bias_level(dapm)) {

View File

@ -1370,6 +1370,31 @@ static int fsl_sai_check_version(struct device *dev)
return 0;
}
static int fsl_sai_reset_hw(struct device *dev)
{
struct fsl_sai *sai = dev_get_drvdata(dev);
unsigned char ofs = sai->soc_data->reg_offset;
int ret;
/*
* Clear TCSR/RCSR to reset SAI and disable all interrupts.
* Bootloader may leave SAI running causing interrupt storm.
*/
ret = regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
if (ret) {
dev_err(dev, "Failed to clear TCSR: %d\n", ret);
return ret;
}
ret = regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
if (ret) {
dev_err(dev, "Failed to clear RCSR: %d\n", ret);
return ret;
}
return 0;
}
/*
* Calculate the offset between first two datalines, don't
* different offset in one case.
@ -1575,13 +1600,6 @@ static int fsl_sai_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
ret = devm_request_irq(dev, irq, fsl_sai_isr, IRQF_SHARED,
np->name, sai);
if (ret) {
dev_err(dev, "failed to claim irq %u\n", irq);
return ret;
}
memcpy(&sai->cpu_dai_drv, fsl_sai_dai_template,
sizeof(*fsl_sai_dai_template) * ARRAY_SIZE(fsl_sai_dai_template));
@ -1656,6 +1674,10 @@ static int fsl_sai_probe(struct platform_device *pdev)
if (ret < 0)
dev_warn(dev, "Error reading SAI version: %d\n", ret);
ret = fsl_sai_reset_hw(dev);
if (ret < 0)
dev_warn(dev, "Failed to reset hardware: %d\n", ret);
/* Select MCLK direction */
if (sai->mclk_direction_output &&
sai->soc_data->max_register >= FSL_SAI_MCTL) {
@ -1667,6 +1689,13 @@ static int fsl_sai_probe(struct platform_device *pdev)
if (ret < 0 && ret != -ENOSYS)
goto err_pm_get_sync;
ret = devm_request_irq(dev, irq, fsl_sai_isr, IRQF_SHARED,
np->name, sai);
if (ret) {
dev_err(dev, "failed to claim irq %u\n", irq);
goto err_pm_get_sync;
}
if (of_device_is_compatible(np, "fsl,imx952-sai") &&
!of_property_read_string(np, "fsl,sai-amix-mode", &str)) {
if (!strcmp(str, "bypass"))

View File

@ -837,6 +837,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
SOF_BT_OFFLOAD_SSP(2) |
SOF_SSP_BT_OFFLOAD_PRESENT),
},
/* Novalake devices*/
{
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_nvlrvp"),
},
.driver_data = (void *)(SOC_SDW_PCH_DMIC),
},
{}
};

View File

@ -8,6 +8,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
#include <sound/soc-acpi-intel-ssp-common.h>
#include "soc-acpi-intel-sdca-quirks.h"
#include "sof-function-topology-lib.h"
static const struct snd_soc_acpi_endpoint single_endpoint = {
@ -237,6 +238,15 @@ static const struct snd_soc_acpi_adr_device rt722_0_agg_adr[] = {
}
};
static const struct snd_soc_acpi_adr_device rt712_0_agg_adr[] = {
{
.adr = 0x000030025D071201ull,
.num_endpoints = ARRAY_SIZE(jack_amp_g1_dmic_endpoints),
.endpoints = jack_amp_g1_dmic_endpoints,
.name_prefix = "rt712"
}
};
static const struct snd_soc_acpi_adr_device rt1316_3_single_adr[] = {
{
.adr = 0x000330025D131601ull,
@ -255,6 +265,15 @@ static const struct snd_soc_acpi_adr_device rt1320_2_single_adr[] = {
}
};
static const struct snd_soc_acpi_adr_device rt1320_3_group1_adr[] = {
{
.adr = 0x000330025D132001ull,
.num_endpoints = 1,
.endpoints = &spk_r_endpoint,
.name_prefix = "rt1320-1"
}
};
static const struct snd_soc_acpi_link_adr arl_cs42l43_l0[] = {
{
.mask = BIT(0),
@ -404,6 +423,20 @@ static const struct snd_soc_acpi_link_adr arl_rt722_l0_rt1320_l2[] = {
{}
};
static const struct snd_soc_acpi_link_adr arl_rt712_l0_rt1320_l3[] = {
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(rt712_0_agg_adr),
.adr_d = rt712_0_agg_adr,
},
{
.mask = BIT(3),
.num_adr = ARRAY_SIZE(rt1320_3_group1_adr),
.adr_d = rt1320_3_group1_adr,
},
{}
};
static const struct snd_soc_acpi_codecs arl_essx_83x6 = {
.num_codecs = 3,
.codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
@ -483,10 +516,24 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = {
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
.link_mask = BIT(0),
.links = arl_cs42l43_l0,
.link_mask = BIT(0) | BIT(2),
.links = arl_rt722_l0_rt1320_l2,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-arl-cs42l43-l0.tplg",
.sof_tplg_filename = "sof-arl-rt722-l0_rt1320-l2.tplg",
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
.link_mask = BIT(0) | BIT(3),
.links = arl_rt711_l0_rt1316_l3,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-arl-rt711-l0-rt1316-l3.tplg",
},
{
.link_mask = BIT(0) | BIT(3),
.links = arl_rt712_l0_rt1320_l3,
.drv_name = "sof_sdw",
.machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb,
.sof_tplg_filename = "sof-arl-rt712-l0-rt1320-l3.tplg",
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
@ -497,18 +544,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = {
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
.link_mask = BIT(2),
.links = arl_cs42l43_l2,
.link_mask = BIT(0),
.links = arl_cs42l43_l0,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-arl-cs42l43-l2.tplg",
.sof_tplg_filename = "sof-arl-cs42l43-l0.tplg",
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
.link_mask = BIT(0) | BIT(3),
.links = arl_rt711_l0_rt1316_l3,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-arl-rt711-l0-rt1316-l3.tplg",
},
{
.link_mask = 0x1, /* link0 required */
.links = arl_rvp,
@ -522,10 +563,10 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = {
.sof_tplg_filename = "sof-arl-rt711-l0.tplg",
},
{
.link_mask = BIT(0) | BIT(2),
.links = arl_rt722_l0_rt1320_l2,
.link_mask = BIT(2),
.links = arl_cs42l43_l2,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-arl-rt722-l0_rt1320-l2.tplg",
.sof_tplg_filename = "sof-arl-cs42l43-l2.tplg",
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{},

View File

@ -10,7 +10,20 @@
#include <sound/soc-acpi-intel-match.h>
#include "soc-acpi-intel-sdw-mockup-match.h"
static const struct snd_soc_acpi_codecs nvl_essx_83x6 = {
.num_codecs = 3,
.codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
};
struct snd_soc_acpi_mach snd_soc_acpi_intel_nvl_machines[] = {
{
.comp_ids = &nvl_essx_83x6,
.drv_name = "sof-essx8336",
.sof_tplg_filename = "sof-nvl-es8336", /* the tplg suffix is added at run time */
.tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER |
SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
},
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_nvl_machines);

View File

@ -92,48 +92,6 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
.group_id = 1,
};
static const struct snd_soc_acpi_endpoint spk_1_endpoint = {
.num = 0,
.aggregated = 1,
.group_position = 1,
.group_id = 1,
};
static const struct snd_soc_acpi_endpoint spk_2_endpoint = {
.num = 0,
.aggregated = 1,
.group_position = 2,
.group_id = 1,
};
static const struct snd_soc_acpi_endpoint spk_3_endpoint = {
.num = 0,
.aggregated = 1,
.group_position = 3,
.group_id = 1,
};
static const struct snd_soc_acpi_endpoint spk_4_endpoint = {
.num = 0,
.aggregated = 1,
.group_position = 4,
.group_id = 1,
};
static const struct snd_soc_acpi_endpoint spk_5_endpoint = {
.num = 0,
.aggregated = 1,
.group_position = 5,
.group_id = 1,
};
static const struct snd_soc_acpi_endpoint spk_6_endpoint = {
.num = 0,
.aggregated = 1,
.group_position = 6,
.group_id = 1,
};
static const struct snd_soc_acpi_endpoint jack_dmic_endpoints[] = {
/* Jack Endpoint */
{
@ -202,15 +160,6 @@ static const struct snd_soc_acpi_endpoint cs42l43_amp_spkagg_endpoints[] = {
},
};
static const struct snd_soc_acpi_adr_device cs42l43_2_adr[] = {
{
.adr = 0x00023001fa424301ull,
.num_endpoints = ARRAY_SIZE(cs42l43_amp_spkagg_endpoints),
.endpoints = cs42l43_amp_spkagg_endpoints,
.name_prefix = "cs42l43"
}
};
static const struct snd_soc_acpi_adr_device cs42l43_3_agg_adr[] = {
{
.adr = 0x00033001FA424301ull,
@ -235,48 +184,6 @@ static const struct snd_soc_acpi_adr_device cs35l56_2_lr_adr[] = {
}
};
static const struct snd_soc_acpi_adr_device cs35l56_1_3amp_adr[] = {
{
.adr = 0x00013001fa355601ull,
.num_endpoints = 1,
.endpoints = &spk_1_endpoint,
.name_prefix = "AMP1"
},
{
.adr = 0x00013101fa355601ull,
.num_endpoints = 1,
.endpoints = &spk_2_endpoint,
.name_prefix = "AMP2"
},
{
.adr = 0x00013201fa355601ull,
.num_endpoints = 1,
.endpoints = &spk_3_endpoint,
.name_prefix = "AMP3"
}
};
static const struct snd_soc_acpi_adr_device cs35l56_3_3amp_adr[] = {
{
.adr = 0x00033301fa355601ull,
.num_endpoints = 1,
.endpoints = &spk_4_endpoint,
.name_prefix = "AMP4"
},
{
.adr = 0x00033401fa355601ull,
.num_endpoints = 1,
.endpoints = &spk_5_endpoint,
.name_prefix = "AMP5"
},
{
.adr = 0x00033501fa355601ull,
.num_endpoints = 1,
.endpoints = &spk_6_endpoint,
.name_prefix = "AMP6"
}
};
static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = {
{
.adr = 0x000030025D071101ull,
@ -408,25 +315,6 @@ static const struct snd_soc_acpi_link_adr ptl_cs42l43_agg_l3_cs35l56_l2[] = {
{}
};
static const struct snd_soc_acpi_link_adr ptl_cs42l43_l2_cs35l56x6_l13[] = {
{
.mask = BIT(2),
.num_adr = ARRAY_SIZE(cs42l43_2_adr),
.adr_d = cs42l43_2_adr,
},
{
.mask = BIT(1),
.num_adr = ARRAY_SIZE(cs35l56_1_3amp_adr),
.adr_d = cs35l56_1_3amp_adr,
},
{
.mask = BIT(3),
.num_adr = ARRAY_SIZE(cs35l56_3_3amp_adr),
.adr_d = cs35l56_3_3amp_adr,
},
{}
};
static const struct snd_soc_acpi_link_adr ptl_rt722_l0_rt1320_l23[] = {
{
.mask = BIT(0),
@ -493,6 +381,20 @@ static const struct snd_soc_acpi_link_adr ptl_sdw_rt713_vb_l3_rt1320_l12[] = {
{}
};
static const struct snd_soc_acpi_link_adr ptl_sdw_rt713_vb_l3_rt1320_l1[] = {
{
.mask = BIT(3),
.num_adr = ARRAY_SIZE(rt713_vb_3_adr),
.adr_d = rt713_vb_3_adr,
},
{
.mask = BIT(1),
.num_adr = ARRAY_SIZE(rt1320_1_group2_adr),
.adr_d = rt1320_1_group2_adr,
},
{}
};
static const struct snd_soc_acpi_link_adr ptl_sdw_rt712_vb_l2_rt1320_l1[] = {
{
.mask = BIT(2),
@ -579,10 +481,11 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = {
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
.link_mask = BIT(1) | BIT(2) | BIT(3),
.links = ptl_cs42l43_l2_cs35l56x6_l13,
.link_mask = BIT(1) | BIT(3),
.links = ptl_sdw_rt713_vb_l3_rt1320_l1,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-ptl-cs42l43-l2-cs35l56x6-l13.tplg",
.sof_tplg_filename = "sof-ptl-rt713-l3-rt1320-l1.tplg",
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
.link_mask = BIT(0) | BIT(2) | BIT(3),
@ -611,6 +514,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = {
.link_mask = BIT(2) | BIT(3),
.links = ptl_cs42l43_agg_l3_cs35l56_l2,
.drv_name = "sof_sdw",
.machine_check = snd_soc_acpi_intel_no_function_topology,
.sof_tplg_filename = "sof-ptl-cs42l43-agg-l3-cs35l56-l2.tplg",
},
{

View File

@ -6,6 +6,7 @@
*
*/
#include <linux/dmi.h>
#include <linux/soundwire/sdw_intel.h>
#include <sound/sdca.h>
#include <sound/soc-acpi.h>
@ -37,6 +38,21 @@ bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg)
}
EXPORT_SYMBOL_NS(snd_soc_acpi_intel_sdca_is_device_rt712_vb, "SND_SOC_ACPI_INTEL_SDCA_QUIRKS");
static const struct dmi_system_id function_topology_quirk_table[] = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
},
},
{}
};
bool snd_soc_acpi_intel_no_function_topology(void *arg)
{
return !!dmi_check_system(function_topology_quirk_table);
}
EXPORT_SYMBOL_NS(snd_soc_acpi_intel_no_function_topology, "SND_SOC_ACPI_INTEL_SDCA_QUIRKS");
MODULE_DESCRIPTION("ASoC ACPI Intel SDCA quirks");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("SND_SOC_SDCA");

View File

@ -10,5 +10,6 @@
#define _SND_SOC_ACPI_INTEL_SDCA_QUIRKS
bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg);
bool snd_soc_acpi_intel_no_function_topology(void *arg);
#endif

View File

@ -497,7 +497,12 @@ static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc
{
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct snd_pcm *pcm = rtd->pcm;
int size = BUFFER_BYTES_MAX;
/*
* Allocate one extra page as a workaround for a DSP bug where 32-bit
* address arithmetic can overflow when the buffer is placed near the
* end of the addressable range.
*/
int size = BUFFER_BYTES_MAX + PAGE_SIZE;
int graph_id, ret;
struct snd_pcm_substream *substream;

View File

@ -194,6 +194,8 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_type = SOC_SDW_DAI_TYPE_MIC,
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
.quirk = SOC_SDW_CODEC_MIC,
.quirk_exclude = true,
},
},
.dai_num = 3,
@ -501,6 +503,8 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_type = SOC_SDW_DAI_TYPE_MIC,
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
.quirk = SOC_SDW_CODEC_MIC,
.quirk_exclude = true,
},
},
.dai_num = 3,
@ -1110,7 +1114,7 @@ int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
struct asoc_sdw_codec_info *codec_info;
struct snd_soc_dai *dai;
struct sdw_slave *sdw_peripheral;
const char *spk_components="";
const char *spk_components = NULL;
int dai_index;
int ret;
int i;
@ -1193,7 +1197,7 @@ int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
else
component = codec_info->dais[dai_index].component_name;
if (strlen (spk_components) == 0)
if (!spk_components)
spk_components =
devm_kasprintf(card->dev, GFP_KERNEL, "%s", component);
else
@ -1201,13 +1205,15 @@ int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
spk_components =
devm_kasprintf(card->dev, GFP_KERNEL,
"%s+%s", spk_components, component);
if (!spk_components)
return -ENOMEM;
}
codec_info->dais[dai_index].rtd_init_done = true;
}
if (strlen (spk_components) > 0) {
if (spk_components) {
/* Update card components for speaker components */
card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:%s",
card->components, spk_components);

View File

@ -36,6 +36,7 @@ int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...)
vaf.va = &args;
dev_err(dev, "ASoC error (%d): %pV", ret, &vaf);
va_end(args);
}
return ret;

View File

@ -223,7 +223,7 @@ static int psp_send_cmd(struct acp_dev_data *adata, int cmd)
{
struct snd_sof_dev *sdev = adata->dev;
int ret;
u32 data;
int data;
if (!cmd)
return -EINVAL;

View File

@ -328,7 +328,7 @@ static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
}
mux = clk_get_parent(dmic->fclk);
if (IS_ERR(mux)) {
if (!mux) {
dev_err(dmic->dev, "can't get fck mux parent\n");
clk_put(parent_clk);
return -ENODEV;

View File

@ -894,8 +894,9 @@ find_format_descriptor(struct usb_interface *interface)
struct uac_format_type_i_discrete_descriptor *desc;
desc = (struct uac_format_type_i_discrete_descriptor *)extra;
if (desc->bLength > extralen) {
dev_err(&interface->dev, "descriptor overflow\n");
if (desc->bLength < sizeof(struct usb_descriptor_header) ||
desc->bLength > extralen) {
dev_err(&interface->dev, "invalid descriptor length\n");
return NULL;
}
if (desc->bLength == UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1) &&

View File

@ -9187,12 +9187,15 @@ static long scarlett2_hwdep_write(struct snd_hwdep *hw,
flash_size = private->flash_segment_blocks[segment_id] *
SCARLETT2_FLASH_BLOCK_SIZE;
if (count < 0 || *offset < 0 || *offset + count >= flash_size)
return -ENOSPC;
if (count < 0 || *offset < 0)
return -EINVAL;
if (!count)
return 0;
if (*offset >= flash_size || count > flash_size - *offset)
return -ENOSPC;
/* Limit the *req size to SCARLETT2_FLASH_RW_MAX */
if (count > max_data_size)
count = max_data_size;