mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 09:20:13 -04:00
ALSA: hda/realtek: add missing error checks for COEF index reads in alc269
alc_read_coef_idx() and alc_read_coefex_idx() can return -1 on error via snd_hda_codec_read(). Several codec initialization and shutdown functions save these return values and later write them back to hardware registers without checking for errors, potentially corrupting COEF register state on a read failure. Add error checks in: - alc282_init() and alc282_shutup(): check coef78 before write-back - alc285_hp_init(): check coef38/coef0d/coef36 before update, check val before write-back, and break polling loop on error - alc294_hp_init(): break polling loop on read error Signed-off-by: Bob Song <songxiebing@kylinos.cn> Link: https://patch.msgid.link/20260730015302.253008-1-songxiebing@kylinos.cn Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
@@ -296,7 +296,8 @@ static void alc282_init(struct hda_codec *codec)
|
||||
msleep(100);
|
||||
|
||||
/* Headphone capless set to normal mode */
|
||||
alc_write_coef_idx(codec, 0x78, coef78);
|
||||
if (coef78 != -1)
|
||||
alc_write_coef_idx(codec, 0x78, coef78);
|
||||
}
|
||||
|
||||
static void alc282_shutup(struct hda_codec *codec)
|
||||
@@ -333,7 +334,8 @@ static void alc282_shutup(struct hda_codec *codec)
|
||||
|
||||
alc_auto_setup_eapd(codec, false);
|
||||
alc_shutup_pins(codec);
|
||||
alc_write_coef_idx(codec, 0x78, coef78);
|
||||
if (coef78 != -1)
|
||||
alc_write_coef_idx(codec, 0x78, coef78);
|
||||
}
|
||||
|
||||
static const struct coef_fw alc283_coefs[] = {
|
||||
@@ -585,15 +587,19 @@ static void alc285_hp_init(struct hda_codec *codec)
|
||||
|
||||
alc_write_coefex_idx(codec, 0x58, 0x00, 0xf888); /* HP depop procedure start */
|
||||
val = alc_read_coefex_idx(codec, 0x58, 0x00);
|
||||
for (i = 0; i < 20 && val & 0x8000; i++) {
|
||||
for (i = 0; i < 20 && val != -1 && val & 0x8000; i++) {
|
||||
msleep(50);
|
||||
val = alc_read_coefex_idx(codec, 0x58, 0x00);
|
||||
} /* Wait for depop procedure finish */
|
||||
|
||||
alc_write_coefex_idx(codec, 0x58, 0x00, val); /* write back the result */
|
||||
alc_update_coef_idx(codec, 0x38, 1<<4, coef38);
|
||||
alc_update_coef_idx(codec, 0x0d, 0x110, coef0d);
|
||||
alc_update_coef_idx(codec, 0x36, 3<<13, coef36);
|
||||
if (val != -1)
|
||||
alc_write_coefex_idx(codec, 0x58, 0x00, val); /* write back the result */
|
||||
if (coef38 != -1)
|
||||
alc_update_coef_idx(codec, 0x38, 1<<4, coef38);
|
||||
if (coef0d != -1)
|
||||
alc_update_coef_idx(codec, 0x0d, 0x110, coef0d);
|
||||
if (coef36 != -1)
|
||||
alc_update_coef_idx(codec, 0x36, 3<<13, coef36);
|
||||
|
||||
msleep(50);
|
||||
alc_update_coef_idx(codec, 0x4a, 1<<15, 0);
|
||||
@@ -858,7 +864,7 @@ static void alc294_hp_init(struct hda_codec *codec)
|
||||
|
||||
/* Wait for depop procedure finish */
|
||||
val = alc_read_coefex_idx(codec, 0x58, 0x01);
|
||||
for (i = 0; i < 20 && val & 0x0080; i++) {
|
||||
for (i = 0; i < 20 && val != -1 && val & 0x0080; i++) {
|
||||
msleep(50);
|
||||
val = alc_read_coefex_idx(codec, 0x58, 0x01);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user