sound fixes for 7.2-rc5

A collection of fixes that have been accumulated recently.
 The amount is still "new normal", but all small fixes.
 Mostly hardware-specific quirks, but including a few core fixes, too.
 
 ALSA Core:
 - Fix potential UAF and race fixes in ALSA timer core
 - Fix sequencer queue timer cleanup to prevent leaks and double-free
 
 HD-audio:
 - Fix silent streams with Intel HDMI keep-alive silent mode
 - Quirks for HP laptops (Pavilion x360, EliteBook 830 G8, ZBook 8
   G2a), Samsung 750XBE/730XBE, and Dell Pro QC1255, Alienware x16 R2,
   Lunnen Ground 14
 - Properly validate ACPI mute object in CS35L41 HDA companion driver
 - Reset calibration data size on failure in TAS2781 HDA driver.
 
 USB-audio:
 - Support FIXED_RATE quirk for JBL Quantum650 Wireless USB headset
 
 ASoC:
 - Intel SOF SoundWire board driver quirks for new Dell laptops
 - DMI overrides and quirks for AMD ACP/YC platforms, including new
   ASUS TUF platforms and MSI Vector A16 HX laptops
 - Skip sysclk reset for active DAIs in shutdown for FSL imx-card
 - Fix spurious BCLK on resume by clearing BYP in FSL SAI driver
 - Add playback-only quirk for H616 codec in Allwinner driver
 - Fix Cirrus Logic CS35L56 potential probe deadlock
 - Fix cache write-through on resume in FS210X codec
 - Bound firmware description string parsing in TAS2781 codec driver
 - Fix duplicate DAPM widget names for wideband DAI in BT-SCO codec
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmpfdfoOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE8GsA/8DOTRLmfsOkdCRd23LcQtmU0vLypZD1Mb4mpW
 0syspvylS7RnUN+2pGOqP/k4BbOFPtoVHel0RTHqmolesA0OFTMk86nHZF/sOpno
 VspMoiI9ptFjOFQdrCVt9wM+Yj9A5n/cRXuwgNJ3RxLuBPPgStzIPQqrfB2ofMIo
 ox+iYu57kvm4eH+WU8gul5snxTh1g9y2CdWCvtKSCVtTpK9IoMTdPV7DWizti2eA
 u3Na0wt6FuDnO74bg81Oku7u4rsfjBUEc8p6EOk+p8zWpQ12WFmH7QS+1Q2lLHqz
 m8IdgLH4PwRZjqdX/k9SggNyNoGc3LIE3bhyuioFQBr+9brZluuj9rVYWARAg+wF
 WZGJoY1o9Pr+lQk24Uk1kEdrOYYHUqPJj4JuPdLI9gnA5j0GyF28dke4QV2Z0849
 NXnX/R0u8nV1QQQLFmyTsTm4FghfWGZTLnQnTvuG0zoEyktrGVSWpR77nN+zQGFx
 gsv0hJAf8PKPEK6uyxfVzcG+vy0N/m2BDQ6CekcLQYjqKpYj9wV8Z9ftbCAKlD6w
 s1Z9pR5SQgbzDLxCE4XHUgz3rox+5Tni9ulgnkhHlkTLVHmRB84rEJ1+J3VJTLYt
 fxogK3LpD7pu70w+DR7byUtx8jHLD5wQCw/fY7VSf2cxbqTQpLPzJ6HyLxxR9TPY
 fFEiG8A=
 =Shbe
 -----END PGP SIGNATURE-----

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

Pull sound fixes from Takashi Iwai:
 "A collection of fixes that have been accumulated recently.

  The amount is still "new normal", but all small fixes. Mostly
  hardware-specific quirks, but including a few core fixes, too.

  ALSA Core:
   - Fix potential UAF and race fixes in ALSA timer core
   - Fix sequencer queue timer cleanup to prevent leaks and double-free

  HD-audio:
   - Fix silent streams with Intel HDMI keep-alive silent mode
   - Quirks for HP laptops (Pavilion x360, EliteBook 830 G8, ZBook 8
     G2a), Samsung 750XBE/730XBE, and Dell Pro QC1255, Alienware x16 R2,
     Lunnen Ground 14
   - Properly validate ACPI mute object in CS35L41 HDA companion driver
   - Reset calibration data size on failure in TAS2781 HDA driver.

  USB-audio:
   - Support FIXED_RATE quirk for JBL Quantum650 Wireless USB headset

  ASoC:
   - Intel SOF SoundWire board driver quirks for new Dell laptops
   - DMI overrides and quirks for AMD ACP/YC platforms, including new
     ASUS TUF platforms and MSI Vector A16 HX laptops
   - Skip sysclk reset for active DAIs in shutdown for FSL imx-card
   - Fix spurious BCLK on resume by clearing BYP in FSL SAI driver
   - Add playback-only quirk for H616 codec in Allwinner driver
   - Fix Cirrus Logic CS35L56 potential probe deadlock
   - Fix cache write-through on resume in FS210X codec
   - Bound firmware description string parsing in TAS2781 codec driver
   - Fix duplicate DAPM widget names for wideband DAI in BT-SCO codec"

* tag 'sound-7.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (25 commits)
  ALSA: hda/realtek - Add quirk for Dell Pro QC1255
  ALSA: hda/tas2781: clear cali_data.total_sz when calibration read fails
  ALSA: hda/realtek: Add HDA_CODEC_QUIRK for Samsung 750XBE/730XBE
  ALSA: hda/realtek: Fix speakers on Lunnen Ground 14
  ALSA: timer: drain a slave's callback before its master detaches it
  ALSA: timer: don't re-enter an instance callback that is still running
  ALSA: usb-audio: Add FIXED_RATE quirk for JBL Quantum650 Wireless
  ALSA: hda/realtek: Add quirk for HP Pavilion x360
  ASoC: Intel: sof_sdw: Add quirks for new Dell laptops
  ASoC: cs35l56: Use complete_all() to signal init_completion
  ASoC: cs35l56: Fix potential probe() deadlock
  ASoC: fs210x: Make cache write through again during resume
  ALSA: hda/realtek: Add inverted LED quirk for HP ZBook 8 G2a
  ALSA: hda: codecs: hdmi: disable keep-alive before audio format change
  ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI
  ALSA: hda: cs35l41: validate and free ACPI mute object
  ALSA: hda/realtek: Fix speakers on Alienware x16 R2
  ALSA: hda/realtek: Add quirk for HP EliteBook 830 G8 (8AB8) to enable mute LEDs
  ASoC: amd: yc: Add DMI quirk for MSI Vector A16 HX A8WIG
  ASoC: fsl: imx-card: Skip sysclk reset for active DAIs in shutdown
  ...
This commit is contained in:
Linus Torvalds 2026-07-22 10:22:23 -07:00
commit 57a92aaba9
21 changed files with 300 additions and 36 deletions

View File

@ -61,12 +61,23 @@ struct snd_seq_timer *snd_seq_timer_new(void)
void snd_seq_timer_delete(struct snd_seq_timer **tmr)
{
struct snd_seq_timer *t = *tmr;
*tmr = NULL;
struct snd_timer_instance *ti;
if (t == NULL) {
pr_debug("ALSA: seq: snd_seq_timer_delete() called with NULL timer\n");
return;
}
scoped_guard(spinlock_irq, &t->lock) {
ti = t->timeri;
t->timeri = NULL;
}
if (ti) {
snd_timer_close(ti);
snd_timer_instance_free(ti);
}
*tmr = NULL;
t->running = 0;
/* reset time */

View File

@ -489,10 +489,20 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
snd_timer_stop(timeri);
if (timer) {
struct snd_timer_instance *slave;
bool busy;
timer->num_instances--;
/* wait, until the active callback is finished */
/* unqueue then drain the slaves' callbacks before remove_slave_links() severs them */
spin_lock_irq(&timer->lock);
while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
list_for_each_entry(slave, &timeri->slave_list_head, open_list)
list_del_init(&slave->ack_list);
for (;;) {
busy = timeri->flags & SNDRV_TIMER_IFLG_CALLBACK;
list_for_each_entry(slave, &timeri->slave_list_head, open_list)
busy |= slave->flags & SNDRV_TIMER_IFLG_CALLBACK;
if (!busy)
break;
spin_unlock_irq(&timer->lock);
udelay(10);
spin_lock_irq(&timer->lock);
@ -927,12 +937,15 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
ack_list_head = &timer->ack_list_head;
else
ack_list_head = &timer->sack_list_head;
if (list_empty(&ti->ack_list))
/* don't requeue an instance whose callback is still running */
if (list_empty(&ti->ack_list) &&
!(ti->flags & SNDRV_TIMER_IFLG_CALLBACK))
list_add_tail(&ti->ack_list, ack_list_head);
list_for_each_entry(ts, &ti->slave_active_head, active_list) {
ts->pticks = ti->pticks;
ts->resolution = resolution;
if (list_empty(&ts->ack_list))
if (list_empty(&ts->ack_list) &&
!(ts->flags & SNDRV_TIMER_IFLG_CALLBACK))
list_add_tail(&ts->ack_list, ack_list_head);
}
}

View File

@ -1688,6 +1688,9 @@ int snd_hda_hdmi_generic_pcm_prepare(struct hda_pcm_stream *hinfo,
per_pin->channels = substream->runtime->channels;
per_pin->setup = true;
if (spec->ops.prepare)
spec->ops.prepare(codec, per_pin);
if (get_wcaps(codec, cvt_nid) & AC_WCAP_STRIPE) {
stripe = snd_hdac_get_stream_stripe_ctl(&codec->bus->core,
substream);

View File

@ -74,6 +74,15 @@ struct hdmi_ops {
hda_nid_t pin_nid, int dev_id, u32 stream_tag,
int format);
/*
* Optional hook invoked at the beginning of the PCM prepare
* sequence, before the audio infoframe and stream format are
* (re)programmed. Used to disable keep-alive / silent stream so
* that the format change is not done while keep-alive is active.
*/
void (*prepare)(struct hda_codec *codec,
struct hdmi_spec_per_pin *per_pin);
void (*pin_cvt_fixup)(struct hda_codec *codec,
struct hdmi_spec_per_pin *per_pin,
hda_nid_t cvt_nid);

View File

@ -418,6 +418,28 @@ static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec,
intel_not_share_assigned_cvt(codec, pin_nid, dev_id, mux_idx);
}
/*
* prepare ops override for HSW+
*
* Disable keep-alive before the converter format and audio infoframe are
* reprogrammed by the PCM prepare sequence. Changing the audio format (e.g.
* the channel count when switching to multichannel PCM) while a keep-alive
* stream is active is not safe, so release keep-alive here, early in the
* sequence. It is re-enabled once the new stream has been set up, in
* i915_hsw_setup_stream().
*/
static void i915_hsw_prepare(struct hda_codec *codec,
struct hdmi_spec_per_pin *per_pin)
{
struct hdmi_spec *spec = codec->spec;
if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin->silent_stream) {
silent_stream_set_kae(codec, per_pin, false);
/* wait for pending transfers in codec to clear */
usleep_range(100, 200);
}
}
/* setup_stream ops override for HSW+ */
static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
hda_nid_t pin_nid, int dev_id, u32 stream_tag,
@ -435,15 +457,16 @@ static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
haswell_verify_D0(codec, cvt_nid, pin_nid);
if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) {
silent_stream_set_kae(codec, per_pin, false);
/* wait for pending transfers in codec to clear */
usleep_range(100, 200);
}
res = snd_hda_hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id,
stream_tag, format);
/*
* Keep-alive was disabled in i915_hsw_prepare(), re-enable it now.
* The pin lookup above resolves to the same per_pin that prepare
* used (pin_nid comes from that per_pin), so this stays balanced; a
* NULL per_pin only occurs on a lookup failure that also implies no
* active keep-alive stream to restore.
*/
if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) {
usleep_range(100, 200);
silent_stream_set_kae(codec, per_pin, true);
@ -607,6 +630,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
codec->depop_delay = 0;
codec->auto_runtime_pm = 1;
spec->ops.prepare = i915_hsw_prepare;
spec->ops.setup_stream = i915_hsw_setup_stream;
spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;
spec->ops.silent_stream = i915_set_silent_stream;

View File

@ -3773,6 +3773,15 @@ static void alc245_hp_spk_mute_led_update(void *private_data, int enabled)
alc_update_coef_idx(codec, 0x0b, 0x0c, val);
}
static void alc245_hp_spk_mute_led_update_inverted(void *private_data, int enabled)
{
struct hda_codec *codec = private_data;
unsigned int val;
val = enabled ? 0x04 : 0x08; /* inverted: 0x04 led off, 0x08 led on */
alc_update_coef_idx(codec, 0x0b, 0x0c, val);
}
/* JD2: mute led GPIO3: micmute led */
static void alc245_tas2781_i2c_hp_fixup_muteled(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
@ -3801,6 +3810,33 @@ static void alc245_tas2781_i2c_hp_fixup_muteled(struct hda_codec *codec,
alc245_fixup_hp_mute_led_coefbit(codec, fix, action);
alc285_fixup_hp_coef_micmute_led(codec, fix, action);
}
/* Same as alc245_tas2781_i2c_hp_fixup_muteled(), but with inverted speaker
* mute LED polarity. The HP ZBook 8 G2a 14/16 (0x103c:0x8f94, 0x103c:0x8f95)
* are speaker-only models without an HP pin, so the LED is driven directly
* through the vmaster_mute hook.
*/
static void alc245_tas2781_i2c_hp_fixup_muteled_inverted(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
static const hda_nid_t conn[] = { 0x02 };
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
spec->gen.vmaster_mute.hook = alc245_hp_spk_mute_led_update_inverted;
spec->gen.vmaster_mute_led = 1;
spec->gen.auto_mute_via_amp = 1;
snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
break;
case HDA_FIXUP_ACT_INIT:
alc245_hp_spk_mute_led_update_inverted(codec, !spec->gen.master_mute);
break;
}
tas2781_fixup_txnw_i2c(codec, fix, action);
alc285_fixup_hp_coef_micmute_led(codec, fix, action);
}
/*
* Clear COEF 0x0d (PCBEEP passthrough) bit 0x40 where BIOS sets it wrongly
* at PM resume
@ -3903,6 +3939,7 @@ enum {
ALC269_FIXUP_DMIC_THINKPAD_ACPI,
ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13,
ALC269VC_FIXUP_INFINIX_Y4_MAX,
ALC269VC_FIXUP_LUNNEN_GROUND_14,
ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO,
ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
ALC255_FIXUP_ASUS_MIC_NO_PRESENCE,
@ -3983,6 +4020,7 @@ enum {
ALC256_FIXUP_HUAWEI_MACH_WX9_PINS,
ALC298_FIXUP_HUAWEI_MBX_STEREO,
ALC295_FIXUP_HP_X360,
ALC295_FIXUP_HP_PAVILION_X360,
ALC221_FIXUP_HP_HEADSET_MIC,
ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
ALC295_FIXUP_HP_AUTO_MUTE,
@ -4163,6 +4201,7 @@ enum {
ALC256_FIXUP_VAIO_RPL_MIC_NO_PRESENCE,
ALC245_FIXUP_HP_TAS2781_SPI_MUTE_LED,
ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED,
ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED_INVERTED,
ALC288_FIXUP_SURFACE_SWAP_DACS,
ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO,
ALC233_FIXUP_LENOVO_GPIO2_MIC_HOTKEY,
@ -4370,6 +4409,13 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
},
[ALC269VC_FIXUP_LUNNEN_GROUND_14] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1b, 0x90170150 }, /* internal speaker */
{ }
},
},
[ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@ -5306,6 +5352,19 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HP_MUTE_LED_MIC3
},
[ALC295_FIXUP_HP_PAVILION_X360] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* force amp gain and processing state */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x7770 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x0d },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x3000 },
{}
},
.chained = true,
.chain_id = ALC295_FIXUP_HP_X360
},
[ALC221_FIXUP_HP_HEADSET_MIC] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@ -6734,6 +6793,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc245_tas2781_i2c_hp_fixup_muteled,
},
[ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED_INVERTED] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc245_tas2781_i2c_hp_fixup_muteled_inverted,
},
[ALC288_FIXUP_SURFACE_SWAP_DACS] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc288_fixup_surface_swap_dacs,
@ -6932,6 +6995,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0c1e, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
SND_PCI_QUIRK(0x1028, 0x0c28, "Dell Inspiron 16 Plus 7630", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
SND_PCI_QUIRK(0x1028, 0x0c4d, "Dell", ALC287_FIXUP_CS35L41_I2C_4),
SND_PCI_QUIRK(0x1028, 0x0c90, "Alienware x16 R2", ALC289_FIXUP_DUAL_SPK),
SND_PCI_QUIRK(0x1028, 0x0c94, "Dell Polaris 3 metal", ALC295_FIXUP_DELL_TAS2781_I2C),
SND_PCI_QUIRK(0x1028, 0x0c96, "Dell Polaris 2in1", ALC295_FIXUP_DELL_TAS2781_I2C),
SND_PCI_QUIRK(0x1028, 0x0cbd, "Dell Oasis 13 CS MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
@ -6943,7 +7007,11 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0cc3, "Dell Oasis 14 Low Weight MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1028, 0x0cc4, "Dell Oasis 16 MTL-H/U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1028, 0x0cc5, "Dell Oasis 14", ALC289_FIXUP_RTK_AMP_DUAL_SPK),
SND_PCI_QUIRK(0x1028, 0x0e6b, "Dell Pro QCM1255", ALC236_FIXUP_DELL_HP_POP_NOISE),
SND_PCI_QUIRK(0x1028, 0x0d56, "Dell Pro Tower QCT1255", ALC236_FIXUP_DELL_HP_POP_NOISE),
SND_PCI_QUIRK(0x1028, 0x0d58, "Dell Pro Micro QCM1255", ALC236_FIXUP_DELL_HP_POP_NOISE),
SND_PCI_QUIRK(0x1028, 0x0d5a, "Dell Pro Slim QCS1255", ALC236_FIXUP_DELL_HP_POP_NOISE),
SND_PCI_QUIRK(0x1028, 0x0e6b, "Dell Pro Tower QCT1255", ALC236_FIXUP_DELL_HP_POP_NOISE),
SND_PCI_QUIRK(0x1028, 0x0e6c, "Dell Pro Slim QCS1255", ALC236_FIXUP_DELL_HP_POP_NOISE),
SND_PCI_QUIRK(0x1028, 0x0e6d, "Dell Pro Micro QCM1255", ALC236_FIXUP_DELL_HP_POP_NOISE),
SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
@ -7017,6 +7085,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3),
HDA_CODEC_QUIRK(0x103c, 0x8486, "HP Pavilion x360", ALC295_FIXUP_HP_PAVILION_X360),
SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x103c, 0x84a6, "HP 250 G7 Notebook PC", ALC269_FIXUP_HP_LINE1_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x84ae, "HP 15-db0403ng", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
@ -7172,6 +7241,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8aa8, "HP EliteBook 640 G9 (MB 8AA6)", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8aab, "HP EliteBook 650 G9 (MB 8AA9)", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8ab8, "HP EliteBook 830 G8 Notebook PC (MB 8AB8)", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8ab9, "HP EliteBook 840 G8 (MB 8AB8)", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
@ -7382,6 +7452,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8f42, "HP ZBook 8 G2a 14W", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8f57, "HP Trekker G7JC", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8f62, "HP ZBook 8 G2a 16W", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8f94, "HP ZBook 8 G2a 14", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED_INVERTED),
SND_PCI_QUIRK(0x103c, 0x8f95, "HP ZBook 8 G2a 16", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED_INVERTED),
SND_PCI_QUIRK(0x1043, 0x1024, "ASUS Zephyrus G14 2025", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1032, "ASUS VivoBook X513EA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1034, "ASUS GU605C", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
@ -7588,6 +7660,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x144d, 0xc1a6, "Samsung Galaxy Book Pro 360 (NP930QBD)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP),
HDA_CODEC_QUIRK(0x144d, 0xc824, "Samsung ELECTRONICS (750XBE/730XBE)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc876, "Samsung 730QED (NP730QED-KA2US)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
@ -7953,6 +8026,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x2782, 0x1705, "MEDION E15433", ALC269VC_FIXUP_INFINIX_Y4_MAX),
SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
SND_PCI_QUIRK(0x2782, 0x4900, "MEDION E15443", ALC233_FIXUP_MEDION_MTL_SPK),
SND_PCI_QUIRK(0x2782, 0xa212, "Lunnen Ground 14", ALC269VC_FIXUP_LUNNEN_GROUND_14),
SND_PCI_QUIRK(0x7017, 0x2014, "Star Labs StarFighter", ALC233_FIXUP_STARLABS_STARFIGHTER),
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED),

View File

@ -1434,10 +1434,19 @@ static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle
guid_parse(CS35L41_UUID, &guid);
if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) {
ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL);
ret = acpi_evaluate_dsm_typed(handle, &guid, 0,
CS35L41_DSM_GET_MUTE, NULL,
ACPI_TYPE_BUFFER);
if (!ret)
return -EINVAL;
if (!ret->buffer.length || !ret->buffer.pointer) {
ACPI_FREE(ret);
return -EINVAL;
}
mute = *ret->buffer.pointer;
ACPI_FREE(ret);
dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute);
}

View File

@ -354,6 +354,7 @@ static int tas2563_save_calibration(struct tas2781_hda *h)
if (ret < 0 || ret >= sizeof(var8) - 1) {
dev_err(p->dev, "%s: Read %s failed\n",
__func__, var8);
cd->total_sz = 0;
return -EINVAL;
}
/*
@ -371,6 +372,7 @@ static int tas2563_save_calibration(struct tas2781_hda *h)
dev_warn(p->dev,
"Dev %d: Caldat[%d] read failed %ld\n",
i, j, status);
cd->total_sz = 0;
return -EINVAL;
}
bedata = cpu_to_be32(*(uint32_t *)&data[offset]);
@ -382,6 +384,7 @@ static int tas2563_save_calibration(struct tas2781_hda *h)
if (cd->total_sz != offset) {
dev_err(p->dev, "%s: tot_size(%lu) and offset(%u) mismatch\n",
__func__, cd->total_sz, offset);
cd->total_sz = 0;
return -EINVAL;
}

View File

@ -44,6 +44,18 @@ static const struct dmi_system_id acp70_acpi_flag_override_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "83W5"),
},
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC"),
DMI_MATCH(DMI_PRODUCT_NAME, "TUF Gaming A14 FA401EA"),
},
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC"),
DMI_MATCH(DMI_PRODUCT_NAME, "Vivobook 18 M1807GA"),
},
},
{}
};

View File

@ -521,6 +521,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Vector A16 HX A8WHG"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vector A16 HX A8WIG"),
}
},
{
.driver_data = &acp6x_card,
.matches = {

View File

@ -17,11 +17,17 @@ static const struct snd_soc_dapm_widget bt_sco_widgets[] = {
SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0,
SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("BT_SCO_RX_WB", "WB Playback", 0,
SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("BT_SCO_TX_WB", "WB Capture", 0,
SND_SOC_NOPM, 0, 0),
};
static const struct snd_soc_dapm_route bt_sco_routes[] = {
{ "BT_SCO_TX", NULL, "RX" },
{ "TX", NULL, "BT_SCO_RX" },
{ "BT_SCO_TX_WB", NULL, "RX" },
{ "TX", NULL, "BT_SCO_RX_WB" },
};
static struct snd_soc_dai_driver bt_sco_dai[] = {
@ -45,14 +51,14 @@ static struct snd_soc_dai_driver bt_sco_dai[] = {
{
.name = "bt-sco-pcm-wb",
.playback = {
.stream_name = "Playback",
.stream_name = "WB Playback",
.channels_min = 1,
.channels_max = 1,
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = {
.stream_name = "Capture",
.stream_name = "WB Capture",
.channels_min = 1,
.channels_max = 1,
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,

View File

@ -55,9 +55,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client)
if (ret != 0)
return ret;
ret = cs35l56_init(cs35l56);
if (ret == 0)
ret = cs35l56_irq_request(&cs35l56->base, client->irq);
ret = cs35l56_irq_request(&cs35l56->base, client->irq);
if (ret < 0)
cs35l56_remove(cs35l56);

View File

@ -44,9 +44,7 @@ static int cs35l56_spi_probe(struct spi_device *spi)
if (ret != 0)
return ret;
ret = cs35l56_init(cs35l56);
if (ret == 0)
ret = cs35l56_irq_request(&cs35l56->base, spi->irq);
ret = cs35l56_irq_request(&cs35l56->base, spi->irq);
if (ret < 0)
cs35l56_remove(cs35l56);

View File

@ -2008,6 +2008,16 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
goto err;
}
/*
* On SoundWire the cs35l56_init() cannot be run until after the
* device has been enumerated by the SoundWire core.
*/
if (!cs35l56->sdw_peripheral) {
ret = cs35l56_init(cs35l56);
if (ret)
goto err_remove_wm_adsp;
}
ret = snd_soc_register_component(cs35l56->base.dev,
&soc_component_dev_cs35l56,
cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
@ -2022,6 +2032,11 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
wm_adsp2_remove(&cs35l56->dsp);
err:
if (pm_runtime_enabled(cs35l56->base.dev)) {
pm_runtime_dont_use_autosuspend(cs35l56->base.dev);
pm_runtime_disable(cs35l56->base.dev);
}
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
@ -2108,7 +2123,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56)
return dev_err_probe(cs35l56->base.dev, ret, "Failed to write ASP1_CONTROL3\n");
cs35l56->base.init_done = true;
complete(&cs35l56->init_completion);
complete_all(&cs35l56->init_completion);
return 0;
}

View File

@ -607,6 +607,7 @@ static int fs210x_init_chip(struct fs210x_priv *fs210x)
regcache_cache_bypass(fs210x->regmap, false);
if (!ret) {
regcache_cache_only(fs210x->regmap, false);
regcache_mark_dirty(fs210x->regmap);
regcache_sync(fs210x->regmap);
fs210x->is_inited = true;

View File

@ -12,6 +12,7 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/limits.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
@ -1100,13 +1101,42 @@ static int tasdevice_load_block_kernel(
return 0;
}
static int tasdevice_fw_strnlen(const struct firmware *fmw, int offset)
{
const u8 *start;
const u8 *nul;
size_t remaining;
size_t len;
if (offset < 0 || offset >= fmw->size)
return -EINVAL;
start = fmw->data + offset;
remaining = fmw->size - offset;
nul = memchr(start, '\0', remaining);
if (!nul)
return -EINVAL;
len = nul - start;
if (len > INT_MAX)
return -EOVERFLOW;
return len;
}
static int fw_parse_variable_hdr(struct tasdevice_priv
*tas_priv, struct tasdevice_dspfw_hdr *fw_hdr,
const struct firmware *fmw, int offset)
{
const unsigned char *buf = fmw->data;
int len = strlen((char *)&buf[offset]);
int len;
len = tasdevice_fw_strnlen(fmw, offset);
if (len < 0) {
dev_err(tas_priv->dev, "%s: Description error\n", __func__);
offset = len;
goto out;
}
len++;
if (offset + len + 8 > fmw->size) {
@ -1238,7 +1268,12 @@ static int fw_parse_data(struct tasdevice_fw *tas_fmw,
memcpy(img_data->name, &data[offset], 64);
offset += 64;
n = strlen((char *)&data[offset]);
n = tasdevice_fw_strnlen(fmw, offset);
if (n < 0) {
dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
offset = n;
goto out;
}
n++;
if (offset + n + 2 > fmw->size) {
dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
@ -1309,7 +1344,12 @@ static int fw_parse_program_data(struct tasdevice_priv *tas_priv,
}
offset += 64;
n = strlen((char *)&buf[offset]);
n = tasdevice_fw_strnlen(fmw, offset);
if (n < 0) {
dev_err(tas_priv->dev, "Description err\n");
offset = n;
goto out;
}
/* skip '\0' and 5 unused bytes */
n += 6;
if (offset + n > fmw->size) {
@ -1372,7 +1412,12 @@ static int fw_parse_configuration_data(
memcpy(config->name, &data[offset], 64);
offset += 64;
n = strlen((char *)&data[offset]);
n = tasdevice_fw_strnlen(fmw, offset);
if (n < 0) {
dev_err(tas_priv->dev, "Description err\n");
offset = n;
goto out;
}
n += 15;
if (offset + n > fmw->size) {
dev_err(tas_priv->dev, "Description err\n");
@ -2134,7 +2179,8 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv,
{
struct tasdevice_calibration *calibration;
unsigned char *data = (unsigned char *)fmw->data;
unsigned int i, n;
unsigned int i;
int n;
if (offset + 2 > fmw->size) {
dev_err(tas_priv->dev, "%s: Calibrations error\n", __func__);
@ -2166,7 +2212,12 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv,
calibration = &(tas_fmw->calibrations[i]);
offset += 64;
n = strlen((char *)&data[offset]);
n = tasdevice_fw_strnlen(fmw, offset);
if (n < 0) {
dev_err(tas_priv->dev, "Description err\n");
offset = n;
goto out;
}
/* skip '\0' and 2 unused bytes */
n += 3;
if (offset + n > fmw->size) {

View File

@ -808,6 +808,8 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
unsigned int ofs = sai->soc_data->reg_offset;
int adir = tx ? RX : TX;
int dir = tx ? TX : RX;
/* Clear xMR to avoid channel swap with mclk_with_tere enabled case */
regmap_write(sai->regmap, FSL_SAI_xMR(tx), 0);
@ -815,10 +817,29 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
FSL_SAI_CR3_TRCE_MASK, 0);
if (!sai->is_consumer_mode[tx] &&
sai->mclk_streams & BIT(substream->stream)) {
clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]);
sai->mclk_streams &= ~BIT(substream->stream);
if (!sai->is_consumer_mode[tx]) {
bool adir_active = !!(sai->mclk_streams & BIT(!substream->stream));
/*
* If opposite stream provides clocks for synchronous mode and
* it is inactive, Clear BYP and BCI
*/
if (fsl_sai_dir_is_synced(sai, adir) && !adir_active)
regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs),
FSL_SAI_CR2_BCI | FSL_SAI_CR2_BYP, 0);
/*
* Clear BYP and BCI of current stream if either of:
* 1. current stream doesn't provide clocks for synchronous mode
* 2. current stream provides clocks for synchronous mode but no
* more stream is active.
*/
if (!fsl_sai_dir_is_synced(sai, dir) || !adir_active)
regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
FSL_SAI_CR2_BCI | FSL_SAI_CR2_BYP, 0);
if (sai->mclk_streams & BIT(substream->stream)) {
clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]);
sai->mclk_streams &= ~BIT(substream->stream);
}
}
return 0;

View File

@ -496,11 +496,15 @@ static void imx_aif_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_dai *codec_dai;
int i;
for_each_rtd_cpu_dais(rtd, i, cpu_dai)
snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT);
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
if (!snd_soc_dai_active(cpu_dai))
snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT);
}
for_each_rtd_codec_dais(rtd, i, codec_dai)
snd_soc_dai_set_sysclk(codec_dai, 0, 0, SND_SOC_CLOCK_IN);
for_each_rtd_codec_dais(rtd, i, codec_dai) {
if (!snd_soc_dai_active(codec_dai))
snd_soc_dai_set_sysclk(codec_dai, 0, 0, SND_SOC_CLOCK_IN);
}
}
static const struct snd_soc_ops imx_aif_ops = {

View File

@ -849,6 +849,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
};
static const struct snd_pci_quirk sof_sdw_ssid_quirk_table[] = {
SND_PCI_QUIRK(0x1028, 0x0e53, "Dell XPS WCL", SOC_SDW_SIDECAR_AMPS),
SND_PCI_QUIRK(0x1028, 0x0e54, "Dell XPS PTL", SOC_SDW_SIDECAR_AMPS),
SND_PCI_QUIRK(0x1043, 0x1e13, "ASUS Zenbook S14", SOC_SDW_CODEC_MIC),
SND_PCI_QUIRK(0x1043, 0x1f43, "ASUS Zenbook S16", SOC_SDW_CODEC_MIC),
SND_PCI_QUIRK(0x17aa, 0x2347, "Lenovo P16", SOC_SDW_CODEC_MIC),

View File

@ -2237,6 +2237,7 @@ static const struct sun4i_codec_quirks sun50i_h616_codec_quirks = {
.reg_dac_fifoc = REG_FIELD(SUN50I_H616_CODEC_DAC_FIFOC, 0, 31),
.reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
.has_reset = true,
.playback_only = true,
.dma_max_burst = SUN4I_DMA_MAX_BURST,
};

View File

@ -2346,6 +2346,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */
QUIRK_FLAG_FIXED_RATE),
DEVICE_FLG(0x0ecb, 0x2125, /* JBL Quantum650 Wireless */
QUIRK_FLAG_FIXED_RATE),
DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
QUIRK_FLAG_FIXED_RATE),
DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */