History

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

Pull sound fixes from Takashi Iwai: "The majority of changes here are small device-specific fixes for ASoC SOF / Intel and usual HD-audio quirks. The only significant high LOC is found in the Cirrus firmware driver, but all those are for hardening against malicious firmware blobs, and they look fine for taking as a last minute fix, too" * tag 'sound-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: hda/realtek: Enable Mute LED on HP 250 G7 firmware: cs_dsp: Use strnlen() on name fields in V1 wmfw files ALSA: hda/realtek: Limit mic boost on VAIO PRO PX ALSA: hda: cs35l41: Fix swapped l/r audio channels for Lenovo ThinBook 13x Gen4 ASoC: SOF: Intel: hda-pcm: Limit the maximum number of periods by MAX_BDL_ENTRIES ASoC: rt711-sdw: add missing readable registers ASoC: SOF: Intel: hda: fix null deref on system suspend entry ALSA: hda/realtek: add quirk for Clevo V5[46]0TU firmware: cs_dsp: Prevent buffer overrun when processing V2 alg headers firmware: cs_dsp: Validate payload length before processing block firmware: cs_dsp: Return error if block header overflows file firmware: cs_dsp: Fix overflow checking of wmfw header

Linus Torvalds committed 2 years ago

Commit 9b481042 parents 5d4c851 f19e1026 files · +182 −73Browse files

Unified · Split

6 files
  1. drivers/firmware/cirrus/cs_dsp.c +162 −65
  2. sound/pci/hda/cs35l41_hda_property.c +2 −2
  3. sound/pci/hda/patch_realtek.c +4 −0
  4. sound/soc/codecs/rt711-sdw.c +2 −0
  5. sound/soc/sof/intel/hda-dai.c +6 −6
  6. sound/soc/sof/intel/hda-pcm.c +6 −0
drivers/firmware/cirrus/cs_dsp.c+162−65
@@ -1107,9 +1107,16 @@ struct cs_dsp_coeff_parsed_coeff { · 1106 unmodified lines
11071107 int len;
11081108 };
11091109
1110−static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
1110+static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, unsigned int avail,
1111+ const u8 **str)
11111112 {
1112− int length;
1113+ int length, total_field_len;
1114+
1115+ /* String fields are at least one __le32 */
1116+ if (sizeof(__le32) > avail) {
1117+ *pos = NULL;
1118+ return 0;
1119+ }
11131120
11141121 switch (bytes) {
11151122 case 1:
@@ -1122,10 +1129,16 @@ static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str) · 6 unmodified lines
11221129 return 0;
11231130 }
11241131
1132+ total_field_len = ((length + bytes) + 3) & ~0x03;
1133+ if ((unsigned int)total_field_len > avail) {
1134+ *pos = NULL;
1135+ return 0;
1136+ }
1137+
11251138 if (str)
11261139 *str = *pos + bytes;
11271140
1128− *pos += ((length + bytes) + 3) & ~0x03;
1141+ *pos += total_field_len;
11291142
11301143 return length;
11311144 }
@@ -1150,71 +1163,134 @@ static int cs_dsp_coeff_parse_int(int bytes, const u8 **pos) · 18 unmodified lines
11501163 return val;
11511164 }
11521165
1153−static inline void cs_dsp_coeff_parse_alg(struct cs_dsp *dsp, const u8 **data,
1154− struct cs_dsp_coeff_parsed_alg *blk)
1166+static int cs_dsp_coeff_parse_alg(struct cs_dsp *dsp,
1167+ const struct wmfw_region *region,
1168+ struct cs_dsp_coeff_parsed_alg *blk)
11551169 {
11561170 const struct wmfw_adsp_alg_data *raw;
1171+ unsigned int data_len = le32_to_cpu(region->len);
1172+ unsigned int pos;
1173+ const u8 *tmp;
1174+
1175+ raw = (const struct wmfw_adsp_alg_data *)region->data;
11571176
11581177 switch (dsp->fw_ver) {
11591178 case 0:
11601179 case 1:
1161− raw = (const struct wmfw_adsp_alg_data *)*data;
1162− *data = raw->data;
1180+ if (sizeof(*raw) > data_len)
1181+ return -EOVERFLOW;
11631182
11641183 blk->id = le32_to_cpu(raw->id);
11651184 blk->name = raw->name;
1166− blk->name_len = strlen(raw->name);
1185+ blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
11671186 blk->ncoeff = le32_to_cpu(raw->ncoeff);
1187+
1188+ pos = sizeof(*raw);
11681189 break;
11691190 default:
1170− blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), data);
1171− blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), data,
1191+ if (sizeof(raw->id) > data_len)
1192+ return -EOVERFLOW;
1193+
1194+ tmp = region->data;
1195+ blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), &tmp);
1196+ pos = tmp - region->data;
1197+
1198+ tmp = &region->data[pos];
1199+ blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
11721200 &blk->name);
1173− cs_dsp_coeff_parse_string(sizeof(u16), data, NULL);
1174− blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), data);
1201+ if (!tmp)
1202+ return -EOVERFLOW;
1203+
1204+ pos = tmp - region->data;
1205+ cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
1206+ if (!tmp)
1207+ return -EOVERFLOW;
1208+
1209+ pos = tmp - region->data;
1210+ if (sizeof(raw->ncoeff) > (data_len - pos))
1211+ return -EOVERFLOW;
1212+
1213+ blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), &tmp);
1214+ pos += sizeof(raw->ncoeff);
11751215 break;
11761216 }
11771217
1218+ if ((int)blk->ncoeff < 0)
1219+ return -EOVERFLOW;
1220+
11781221 cs_dsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
11791222 cs_dsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
11801223 cs_dsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);
1224+
1225+ return pos;
11811226 }
11821227
1183−static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
1184− struct cs_dsp_coeff_parsed_coeff *blk)
1228+static int cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp,
1229+ const struct wmfw_region *region,
1230+ unsigned int pos,
1231+ struct cs_dsp_coeff_parsed_coeff *blk)
11851232 {
11861233 const struct wmfw_adsp_coeff_data *raw;
1234+ unsigned int data_len = le32_to_cpu(region->len);
1235+ unsigned int blk_len, blk_end_pos;
11871236 const u8 *tmp;
1188− int length;
1237+
1238+ raw = (const struct wmfw_adsp_coeff_data *)&region->data[pos];
1239+ if (sizeof(raw->hdr) > (data_len - pos))
1240+ return -EOVERFLOW;
1241+
1242+ blk_len = le32_to_cpu(raw->hdr.size);
1243+ if (blk_len > S32_MAX)
1244+ return -EOVERFLOW;
1245+
1246+ if (blk_len > (data_len - pos - sizeof(raw->hdr)))
1247+ return -EOVERFLOW;
1248+
1249+ blk_end_pos = pos + sizeof(raw->hdr) + blk_len;
1250+
1251+ blk->offset = le16_to_cpu(raw->hdr.offset);
1252+ blk->mem_type = le16_to_cpu(raw->hdr.type);
11891253
11901254 switch (dsp->fw_ver) {
11911255 case 0:
11921256 case 1:
1193− raw = (const struct wmfw_adsp_coeff_data *)*data;
1194− *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
1257+ if (sizeof(*raw) > (data_len - pos))
1258+ return -EOVERFLOW;
11951259
1196− blk->offset = le16_to_cpu(raw->hdr.offset);
1197− blk->mem_type = le16_to_cpu(raw->hdr.type);
11981260 blk->name = raw->name;
1199− blk->name_len = strlen(raw->name);
1261+ blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
12001262 blk->ctl_type = le16_to_cpu(raw->ctl_type);
12011263 blk->flags = le16_to_cpu(raw->flags);
12021264 blk->len = le32_to_cpu(raw->len);
12031265 break;
12041266 default:
1205− tmp = *data;
1206− blk->offset = cs_dsp_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
1207− blk->mem_type = cs_dsp_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
1208− length = cs_dsp_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
1209− blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp,
1267+ pos += sizeof(raw->hdr);
1268+ tmp = &region->data[pos];
1269+ blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
12101270 &blk->name);
1211− cs_dsp_coeff_parse_string(sizeof(u8), &tmp, NULL);
1212− cs_dsp_coeff_parse_string(sizeof(u16), &tmp, NULL);
1271+ if (!tmp)
1272+ return -EOVERFLOW;
1273+
1274+ pos = tmp - region->data;
1275+ cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos, NULL);
1276+ if (!tmp)
1277+ return -EOVERFLOW;
1278+
1279+ pos = tmp - region->data;
1280+ cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
1281+ if (!tmp)
1282+ return -EOVERFLOW;
1283+
1284+ pos = tmp - region->data;
1285+ if (sizeof(raw->ctl_type) + sizeof(raw->flags) + sizeof(raw->len) >
1286+ (data_len - pos))
1287+ return -EOVERFLOW;
1288+
12131289 blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
1290+ pos += sizeof(raw->ctl_type);
12141291 blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp);
1292+ pos += sizeof(raw->flags);
12151293 blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp);
1216−
1217− *data = *data + sizeof(raw->hdr) + length;
12181294 break;
12191295 }
12201296
@@ -1224,6 +1300,8 @@ static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data, · 3 unmodified lines
12241300 cs_dsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
12251301 cs_dsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
12261302 cs_dsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);
1303+
1304+ return blk_end_pos;
12271305 }
12281306
12291307 static int cs_dsp_check_coeff_flags(struct cs_dsp *dsp,
@@ -1247,12 +1325,16 @@ static int cs_dsp_parse_coeff(struct cs_dsp *dsp, · 17 unmodified lines
12471325 struct cs_dsp_alg_region alg_region = {};
12481326 struct cs_dsp_coeff_parsed_alg alg_blk;
12491327 struct cs_dsp_coeff_parsed_coeff coeff_blk;
1250− const u8 *data = region->data;
1251− int i, ret;
1328+ int i, pos, ret;
1329+
1330+ pos = cs_dsp_coeff_parse_alg(dsp, region, &alg_blk);
1331+ if (pos < 0)
1332+ return pos;
12521333
1253− cs_dsp_coeff_parse_alg(dsp, &data, &alg_blk);
12541334 for (i = 0; i < alg_blk.ncoeff; i++) {
1255− cs_dsp_coeff_parse_coeff(dsp, &data, &coeff_blk);
1335+ pos = cs_dsp_coeff_parse_coeff(dsp, region, pos, &coeff_blk);
1336+ if (pos < 0)
1337+ return pos;
12561338
12571339 switch (coeff_blk.ctl_type) {
12581340 case WMFW_CTL_TYPE_BYTES:
@@ -1321,6 +1403,10 @@ static unsigned int cs_dsp_adsp1_parse_sizes(struct cs_dsp *dsp, · 62 unmodified lines
13211403 const struct wmfw_adsp1_sizes *adsp1_sizes;
13221404
13231405 adsp1_sizes = (void *)&firmware->data[pos];
1406+ if (sizeof(*adsp1_sizes) > firmware->size - pos) {
1407+ cs_dsp_err(dsp, "%s: file truncated\n", file);
1408+ return 0;
1409+ }
13241410
13251411 cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
13261412 le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm),
@@ -1337,6 +1423,10 @@ static unsigned int cs_dsp_adsp2_parse_sizes(struct cs_dsp *dsp, · 10 unmodified lines
13371423 const struct wmfw_adsp2_sizes *adsp2_sizes;
13381424
13391425 adsp2_sizes = (void *)&firmware->data[pos];
1426+ if (sizeof(*adsp2_sizes) > firmware->size - pos) {
1427+ cs_dsp_err(dsp, "%s: file truncated\n", file);
1428+ return 0;
1429+ }
13401430
13411431 cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
13421432 le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym),
@@ -1376,7 +1466,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, · 33 unmodified lines
13761466 struct regmap *regmap = dsp->regmap;
13771467 unsigned int pos = 0;
13781468 const struct wmfw_header *header;
1379− const struct wmfw_adsp1_sizes *adsp1_sizes;
13801469 const struct wmfw_footer *footer;
13811470 const struct wmfw_region *region;
13821471 const struct cs_dsp_region *mem;
@@ -1392,10 +1481,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, · 9 unmodified lines
13921481
13931482 ret = -EINVAL;
13941483
1395− pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
1396− if (pos >= firmware->size) {
1397− cs_dsp_err(dsp, "%s: file too short, %zu bytes\n",
1398− file, firmware->size);
1484+ if (sizeof(*header) >= firmware->size) {
1485+ ret = -EOVERFLOW;
13991486 goto out_fw;
14001487 }
14011488
@@ -1423,22 +1510,36 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, · 21 unmodified lines
14231510
14241511 pos = sizeof(*header);
14251512 pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
1513+ if ((pos == 0) || (sizeof(*footer) > firmware->size - pos)) {
1514+ ret = -EOVERFLOW;
1515+ goto out_fw;
1516+ }
14261517
14271518 footer = (void *)&firmware->data[pos];
14281519 pos += sizeof(*footer);
14291520
14301521 if (le32_to_cpu(header->len) != pos) {
1431− cs_dsp_err(dsp, "%s: unexpected header length %d\n",
1432− file, le32_to_cpu(header->len));
1522+ ret = -EOVERFLOW;
14331523 goto out_fw;
14341524 }
14351525
14361526 cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file,
14371527 le64_to_cpu(footer->timestamp));
14381528
1439− while (pos < firmware->size &&
1440− sizeof(*region) < firmware->size - pos) {
1529+ while (pos < firmware->size) {
1530+ /* Is there enough data for a complete block header? */
1531+ if (sizeof(*region) > firmware->size - pos) {
1532+ ret = -EOVERFLOW;
1533+ goto out_fw;
1534+ }
1535+
14411536 region = (void *)&(firmware->data[pos]);
1537+
1538+ if (le32_to_cpu(region->len) > firmware->size - pos - sizeof(*region)) {
1539+ ret = -EOVERFLOW;
1540+ goto out_fw;
1541+ }
1542+
14421543 region_name = "Unknown";
14431544 reg = 0;
14441545 text = NULL;
@@ -1495,16 +1596,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, · 50 unmodified lines
14951596 regions, le32_to_cpu(region->len), offset,
14961597 region_name);
14971598
1498− if (le32_to_cpu(region->len) >
1499− firmware->size - pos - sizeof(*region)) {
1500− cs_dsp_err(dsp,
1501− "%s.%d: %s region len %d bytes exceeds file length %zu\n",
1502− file, regions, region_name,
1503− le32_to_cpu(region->len), firmware->size);
1504− ret = -EINVAL;
1505− goto out_fw;
1506− }
1507−
15081599 if (text) {
15091600 memcpy(text, region->data, le32_to_cpu(region->len));
15101601 cs_dsp_info(dsp, "%s: %s\n", file, text);
@@ -1555,6 +1646,9 @@ out_fw: · 44 unmodified lines
15551646 cs_dsp_buf_free(&buf_list);
15561647 kfree(text);
15571648
1649+ if (ret == -EOVERFLOW)
1650+ cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
1651+
15581652 return ret;
15591653 }
15601654
@@ -2122,10 +2216,20 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware · 561 unmodified lines
21222216 pos = le32_to_cpu(hdr->len);
21232217
21242218 blocks = 0;
2125− while (pos < firmware->size &&
2126− sizeof(*blk) < firmware->size - pos) {
2219+ while (pos < firmware->size) {
2220+ /* Is there enough data for a complete block header? */
2221+ if (sizeof(*blk) > firmware->size - pos) {
2222+ ret = -EOVERFLOW;
2223+ goto out_fw;
2224+ }
2225+
21272226 blk = (void *)(&firmware->data[pos]);
21282227
2228+ if (le32_to_cpu(blk->len) > firmware->size - pos - sizeof(*blk)) {
2229+ ret = -EOVERFLOW;
2230+ goto out_fw;
2231+ }
2232+
21292233 type = le16_to_cpu(blk->type);
21302234 offset = le16_to_cpu(blk->offset);
21312235 version = le32_to_cpu(blk->ver) >> 8;
@@ -2222,17 +2326,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware · 90 unmodified lines
22222326 }
22232327
22242328 if (reg) {
2225− if (le32_to_cpu(blk->len) >
2226− firmware->size - pos - sizeof(*blk)) {
2227− cs_dsp_err(dsp,
2228− "%s.%d: %s region len %d bytes exceeds file length %zu\n",
2229− file, blocks, region_name,
2230− le32_to_cpu(blk->len),
2231− firmware->size);
2232− ret = -EINVAL;
2233− goto out_fw;
2234− }
2235−
22362329 buf = cs_dsp_buf_alloc(blk->data,
22372330 le32_to_cpu(blk->len),
22382331 &buf_list);
@@ -2272,6 +2365,10 @@ out_fw: · 33 unmodified lines
22722365 regmap_async_complete(regmap);
22732366 cs_dsp_buf_free(&buf_list);
22742367 kfree(text);
2368+
2369+ if (ret == -EOVERFLOW)
2370+ cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
2371+
22752372 return ret;
22762373 }
22772374
sound/pci/hda/cs35l41_hda_property.c+2−2
@@ -128,8 +128,8 @@ static const struct cs35l41_config cs35l41_config_table[] = { · 127 unmodified lines
128128 { "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
129129 { "17AA38B6", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
130130 { "17AA38B7", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
131− { "17AA38C7", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 2, -1, 1000, 4500, 24 },
132− { "17AA38C8", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 2, -1, 1000, 4500, 24 },
131+ { "17AA38C7", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 },
132+ { "17AA38C8", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 },
133133 { "17AA38F9", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
134134 { "17AA38FA", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
135135 {}
sound/pci/hda/patch_realtek.c+4−0
@@ -10053,6 +10053,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 10052 unmodified lines
1005310053 SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
1005410054 SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3),
1005510055 SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
10056+ SND_PCI_QUIRK(0x103c, 0x84a6, "HP 250 G7 Notebook PC", ALC269_FIXUP_HP_LINE1_MIC1_LED),
1005610057 SND_PCI_QUIRK(0x103c, 0x84ae, "HP 15-db0403ng", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
1005710058 SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
1005810059 SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
@@ -10383,6 +10384,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 324 unmodified lines
1038310384 SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
1038410385 SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE),
1038510386 SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
10387+ SND_PCI_QUIRK(0x10ec, 0x11bc, "VAIO VJFE-IL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
1038610388 SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
1038710389 SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
1038810390 SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
@@ -10480,6 +10482,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 91 unmodified lines
1048010482 SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL50NU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
1048110483 SND_PCI_QUIRK(0x1558, 0xa650, "Clevo NP[567]0SN[CD]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
1048210484 SND_PCI_QUIRK(0x1558, 0xa671, "Clevo NP70SN[CDE]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
10485+ SND_PCI_QUIRK(0x1558, 0xa763, "Clevo V54x_6x_TU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
1048310486 SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
1048410487 SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
1048510488 SND_PCI_QUIRK(0x1558, 0xb022, "Clevo NH77D[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -10655,6 +10658,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 169 unmodified lines
1065510658 SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
1065610659 SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC),
1065710660 SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
10661+ SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
1065810662 SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
1065910663 SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
1066010664 SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
sound/soc/codecs/rt711-sdw.c+2−0
@@ -38,7 +38,9 @@ static bool rt711_readable_register(struct device *dev, unsigned int reg) · 37 unmodified lines
3838 case 0x8300 ... 0x83ff:
3939 case 0x9c00 ... 0x9cff:
4040 case 0xb900 ... 0xb9ff:
41+ case 0x752008:
4142 case 0x752009:
43+ case 0x75200b:
4244 case 0x752011:
4345 case 0x75201a:
4446 case 0x752045:
sound/soc/sof/intel/hda-dai.c+6−6
@@ -617,12 +617,6 @@ static int hda_dai_suspend(struct hdac_bus *bus) · 616 unmodified lines
617617 sdai = swidget->private;
618618 ops = sdai->platform_private;
619619
620− ret = hda_link_dma_cleanup(hext_stream->link_substream,
621− hext_stream,
622− cpu_dai);
623− if (ret < 0)
624− return ret;
625−
626620 /* for consistency with TRIGGER_SUSPEND */
627621 if (ops->post_trigger) {
628622 ret = ops->post_trigger(sdev, cpu_dai,
@@ -631,6 +625,12 @@ static int hda_dai_suspend(struct hdac_bus *bus) · 2 unmodified lines
631625 if (ret < 0)
632626 return ret;
633627 }
628+
629+ ret = hda_link_dma_cleanup(hext_stream->link_substream,
630+ hext_stream,
631+ cpu_dai);
632+ if (ret < 0)
633+ return ret;
634634 }
635635 }
636636
sound/soc/sof/intel/hda-pcm.c+6−0
@@ -258,6 +258,12 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, · 257 unmodified lines
258258 snd_pcm_hw_constraint_integer(substream->runtime,
259259 SNDRV_PCM_HW_PARAM_PERIODS);
260260
261+ /* Limit the maximum number of periods to not exceed the BDL entries count */
262+ if (runtime->hw.periods_max > HDA_DSP_MAX_BDL_ENTRIES)
263+ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
264+ runtime->hw.periods_min,
265+ HDA_DSP_MAX_BDL_ENTRIES);
266+
261267 /* Only S16 and S32 supported by HDA hardware when used without DSP */
262268 if (sdev->dspless_mode_selected)
263269 snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT,