Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: cs_dsp: Some small coding improvements

Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>:

Commit series that makes some small improvements to code and the
kernel log messages.

+239 -130
+187 -112
drivers/firmware/cirrus/cs_dsp.c
··· 12 12 #include <linux/ctype.h> 13 13 #include <linux/debugfs.h> 14 14 #include <linux/delay.h> 15 + #include <linux/minmax.h> 15 16 #include <linux/module.h> 16 17 #include <linux/moduleparam.h> 17 18 #include <linux/seq_file.h> ··· 1051 1050 1052 1051 ctl->fw_name = dsp->fw_name; 1053 1052 ctl->alg_region = *alg_region; 1054 - if (subname && dsp->fw_ver >= 2) { 1053 + if (subname && dsp->wmfw_ver >= 2) { 1055 1054 ctl->subname_len = subname_len; 1056 1055 ctl->subname = kasprintf(GFP_KERNEL, "%.*s", subname_len, subname); 1057 1056 if (!ctl->subname) { ··· 1111 1110 int len; 1112 1111 }; 1113 1112 1114 - static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str) 1113 + static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, unsigned int avail, 1114 + const u8 **str) 1115 1115 { 1116 - int length; 1116 + int length, total_field_len; 1117 + 1118 + /* String fields are at least one __le32 */ 1119 + if (sizeof(__le32) > avail) { 1120 + *pos = NULL; 1121 + return 0; 1122 + } 1117 1123 1118 1124 switch (bytes) { 1119 1125 case 1: ··· 1133 1125 return 0; 1134 1126 } 1135 1127 1128 + total_field_len = ((length + bytes) + 3) & ~0x03; 1129 + if ((unsigned int)total_field_len > avail) { 1130 + *pos = NULL; 1131 + return 0; 1132 + } 1133 + 1136 1134 if (str) 1137 1135 *str = *pos + bytes; 1138 1136 1139 - *pos += ((length + bytes) + 3) & ~0x03; 1137 + *pos += total_field_len; 1140 1138 1141 1139 return length; 1142 1140 } ··· 1167 1153 return val; 1168 1154 } 1169 1155 1170 - static inline void cs_dsp_coeff_parse_alg(struct cs_dsp *dsp, const u8 **data, 1171 - struct cs_dsp_coeff_parsed_alg *blk) 1156 + static int cs_dsp_coeff_parse_alg(struct cs_dsp *dsp, 1157 + const struct wmfw_region *region, 1158 + struct cs_dsp_coeff_parsed_alg *blk) 1172 1159 { 1173 1160 const struct wmfw_adsp_alg_data *raw; 1161 + unsigned int data_len = le32_to_cpu(region->len); 1162 + unsigned int pos; 1163 + const u8 *tmp; 1174 1164 1175 - switch (dsp->fw_ver) { 1165 + raw = (const struct wmfw_adsp_alg_data *)region->data; 1166 + 1167 + switch (dsp->wmfw_ver) { 1176 1168 case 0: 1177 1169 case 1: 1178 - raw = (const struct wmfw_adsp_alg_data *)*data; 1179 - *data = raw->data; 1170 + if (sizeof(*raw) > data_len) 1171 + return -EOVERFLOW; 1180 1172 1181 1173 blk->id = le32_to_cpu(raw->id); 1182 1174 blk->name = raw->name; 1183 - blk->name_len = strlen(raw->name); 1175 + blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name)); 1184 1176 blk->ncoeff = le32_to_cpu(raw->ncoeff); 1177 + 1178 + pos = sizeof(*raw); 1185 1179 break; 1186 1180 default: 1187 - blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), data); 1188 - blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), data, 1181 + if (sizeof(raw->id) > data_len) 1182 + return -EOVERFLOW; 1183 + 1184 + tmp = region->data; 1185 + blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), &tmp); 1186 + pos = tmp - region->data; 1187 + 1188 + tmp = &region->data[pos]; 1189 + blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos, 1189 1190 &blk->name); 1190 - cs_dsp_coeff_parse_string(sizeof(u16), data, NULL); 1191 - blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), data); 1191 + if (!tmp) 1192 + return -EOVERFLOW; 1193 + 1194 + pos = tmp - region->data; 1195 + cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL); 1196 + if (!tmp) 1197 + return -EOVERFLOW; 1198 + 1199 + pos = tmp - region->data; 1200 + if (sizeof(raw->ncoeff) > (data_len - pos)) 1201 + return -EOVERFLOW; 1202 + 1203 + blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), &tmp); 1204 + pos += sizeof(raw->ncoeff); 1192 1205 break; 1193 1206 } 1207 + 1208 + if ((int)blk->ncoeff < 0) 1209 + return -EOVERFLOW; 1194 1210 1195 1211 cs_dsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id); 1196 1212 cs_dsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name); 1197 1213 cs_dsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff); 1214 + 1215 + return pos; 1198 1216 } 1199 1217 1200 - static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data, 1201 - struct cs_dsp_coeff_parsed_coeff *blk) 1218 + static int cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, 1219 + const struct wmfw_region *region, 1220 + unsigned int pos, 1221 + struct cs_dsp_coeff_parsed_coeff *blk) 1202 1222 { 1203 1223 const struct wmfw_adsp_coeff_data *raw; 1224 + unsigned int data_len = le32_to_cpu(region->len); 1225 + unsigned int blk_len, blk_end_pos; 1204 1226 const u8 *tmp; 1205 - int length; 1206 1227 1207 - switch (dsp->fw_ver) { 1228 + raw = (const struct wmfw_adsp_coeff_data *)&region->data[pos]; 1229 + if (sizeof(raw->hdr) > (data_len - pos)) 1230 + return -EOVERFLOW; 1231 + 1232 + blk_len = le32_to_cpu(raw->hdr.size); 1233 + if (blk_len > S32_MAX) 1234 + return -EOVERFLOW; 1235 + 1236 + if (blk_len > (data_len - pos - sizeof(raw->hdr))) 1237 + return -EOVERFLOW; 1238 + 1239 + blk_end_pos = pos + sizeof(raw->hdr) + blk_len; 1240 + 1241 + blk->offset = le16_to_cpu(raw->hdr.offset); 1242 + blk->mem_type = le16_to_cpu(raw->hdr.type); 1243 + 1244 + switch (dsp->wmfw_ver) { 1208 1245 case 0: 1209 1246 case 1: 1210 - raw = (const struct wmfw_adsp_coeff_data *)*data; 1211 - *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size); 1247 + if (sizeof(*raw) > (data_len - pos)) 1248 + return -EOVERFLOW; 1212 1249 1213 - blk->offset = le16_to_cpu(raw->hdr.offset); 1214 - blk->mem_type = le16_to_cpu(raw->hdr.type); 1215 1250 blk->name = raw->name; 1216 - blk->name_len = strlen(raw->name); 1251 + blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name)); 1217 1252 blk->ctl_type = le16_to_cpu(raw->ctl_type); 1218 1253 blk->flags = le16_to_cpu(raw->flags); 1219 1254 blk->len = le32_to_cpu(raw->len); 1220 1255 break; 1221 1256 default: 1222 - tmp = *data; 1223 - blk->offset = cs_dsp_coeff_parse_int(sizeof(raw->hdr.offset), &tmp); 1224 - blk->mem_type = cs_dsp_coeff_parse_int(sizeof(raw->hdr.type), &tmp); 1225 - length = cs_dsp_coeff_parse_int(sizeof(raw->hdr.size), &tmp); 1226 - blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, 1257 + pos += sizeof(raw->hdr); 1258 + tmp = &region->data[pos]; 1259 + blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos, 1227 1260 &blk->name); 1228 - cs_dsp_coeff_parse_string(sizeof(u8), &tmp, NULL); 1229 - cs_dsp_coeff_parse_string(sizeof(u16), &tmp, NULL); 1230 - blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp); 1231 - blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp); 1232 - blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp); 1261 + if (!tmp) 1262 + return -EOVERFLOW; 1233 1263 1234 - *data = *data + sizeof(raw->hdr) + length; 1264 + pos = tmp - region->data; 1265 + cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos, NULL); 1266 + if (!tmp) 1267 + return -EOVERFLOW; 1268 + 1269 + pos = tmp - region->data; 1270 + cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL); 1271 + if (!tmp) 1272 + return -EOVERFLOW; 1273 + 1274 + pos = tmp - region->data; 1275 + if (sizeof(raw->ctl_type) + sizeof(raw->flags) + sizeof(raw->len) > 1276 + (data_len - pos)) 1277 + return -EOVERFLOW; 1278 + 1279 + blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp); 1280 + pos += sizeof(raw->ctl_type); 1281 + blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp); 1282 + pos += sizeof(raw->flags); 1283 + blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp); 1235 1284 break; 1236 1285 } 1237 1286 ··· 1304 1227 cs_dsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags); 1305 1228 cs_dsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type); 1306 1229 cs_dsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len); 1230 + 1231 + return blk_end_pos; 1307 1232 } 1308 1233 1309 1234 static int cs_dsp_check_coeff_flags(struct cs_dsp *dsp, ··· 1329 1250 struct cs_dsp_alg_region alg_region = {}; 1330 1251 struct cs_dsp_coeff_parsed_alg alg_blk; 1331 1252 struct cs_dsp_coeff_parsed_coeff coeff_blk; 1332 - const u8 *data = region->data; 1333 - int i, ret; 1253 + int i, pos, ret; 1334 1254 1335 - cs_dsp_coeff_parse_alg(dsp, &data, &alg_blk); 1255 + pos = cs_dsp_coeff_parse_alg(dsp, region, &alg_blk); 1256 + if (pos < 0) 1257 + return pos; 1258 + 1336 1259 for (i = 0; i < alg_blk.ncoeff; i++) { 1337 - cs_dsp_coeff_parse_coeff(dsp, &data, &coeff_blk); 1260 + pos = cs_dsp_coeff_parse_coeff(dsp, region, pos, &coeff_blk); 1261 + if (pos < 0) 1262 + return pos; 1338 1263 1339 1264 switch (coeff_blk.ctl_type) { 1340 1265 case WMFW_CTL_TYPE_BYTES: ··· 1407 1324 const struct wmfw_adsp1_sizes *adsp1_sizes; 1408 1325 1409 1326 adsp1_sizes = (void *)&firmware->data[pos]; 1327 + if (sizeof(*adsp1_sizes) > firmware->size - pos) { 1328 + cs_dsp_err(dsp, "%s: file truncated\n", file); 1329 + return 0; 1330 + } 1410 1331 1411 1332 cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file, 1412 1333 le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm), ··· 1427 1340 const struct wmfw_adsp2_sizes *adsp2_sizes; 1428 1341 1429 1342 adsp2_sizes = (void *)&firmware->data[pos]; 1343 + if (sizeof(*adsp2_sizes) > firmware->size - pos) { 1344 + cs_dsp_err(dsp, "%s: file truncated\n", file); 1345 + return 0; 1346 + } 1430 1347 1431 1348 cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file, 1432 1349 le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym), ··· 1470 1379 struct regmap *regmap = dsp->regmap; 1471 1380 unsigned int pos = 0; 1472 1381 const struct wmfw_header *header; 1473 - const struct wmfw_adsp1_sizes *adsp1_sizes; 1474 1382 const struct wmfw_footer *footer; 1475 1383 const struct wmfw_region *region; 1476 1384 const struct cs_dsp_region *mem; 1477 1385 const char *region_name; 1478 - char *text = NULL; 1479 1386 struct cs_dsp_buf *buf; 1480 1387 unsigned int reg; 1481 1388 int regions = 0; ··· 1484 1395 1485 1396 ret = -EINVAL; 1486 1397 1487 - pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); 1488 - if (pos >= firmware->size) { 1489 - cs_dsp_err(dsp, "%s: file too short, %zu bytes\n", 1490 - file, firmware->size); 1398 + if (sizeof(*header) >= firmware->size) { 1399 + ret = -EOVERFLOW; 1491 1400 goto out_fw; 1492 1401 } 1493 1402 ··· 1502 1415 goto out_fw; 1503 1416 } 1504 1417 1505 - cs_dsp_info(dsp, "Firmware version: %d\n", header->ver); 1506 - dsp->fw_ver = header->ver; 1418 + dsp->wmfw_ver = header->ver; 1507 1419 1508 1420 if (header->core != dsp->type) { 1509 1421 cs_dsp_err(dsp, "%s: invalid core %d != %d\n", ··· 1512 1426 1513 1427 pos = sizeof(*header); 1514 1428 pos = dsp->ops->parse_sizes(dsp, file, pos, firmware); 1429 + if ((pos == 0) || (sizeof(*footer) > firmware->size - pos)) { 1430 + ret = -EOVERFLOW; 1431 + goto out_fw; 1432 + } 1515 1433 1516 1434 footer = (void *)&firmware->data[pos]; 1517 1435 pos += sizeof(*footer); 1518 1436 1519 1437 if (le32_to_cpu(header->len) != pos) { 1520 - cs_dsp_err(dsp, "%s: unexpected header length %d\n", 1521 - file, le32_to_cpu(header->len)); 1438 + ret = -EOVERFLOW; 1522 1439 goto out_fw; 1523 1440 } 1524 1441 1525 - cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file, 1526 - le64_to_cpu(footer->timestamp)); 1442 + cs_dsp_info(dsp, "%s: format %d timestamp %#llx\n", file, header->ver, 1443 + le64_to_cpu(footer->timestamp)); 1527 1444 1528 - while (pos < firmware->size && 1529 - sizeof(*region) < firmware->size - pos) { 1445 + while (pos < firmware->size) { 1446 + /* Is there enough data for a complete block header? */ 1447 + if (sizeof(*region) > firmware->size - pos) { 1448 + ret = -EOVERFLOW; 1449 + goto out_fw; 1450 + } 1451 + 1530 1452 region = (void *)&(firmware->data[pos]); 1453 + 1454 + if (le32_to_cpu(region->len) > firmware->size - pos - sizeof(*region)) { 1455 + ret = -EOVERFLOW; 1456 + goto out_fw; 1457 + } 1458 + 1531 1459 region_name = "Unknown"; 1532 1460 reg = 0; 1533 - text = NULL; 1534 1461 offset = le32_to_cpu(region->offset) & 0xffffff; 1535 1462 type = be32_to_cpu(region->type) & 0xff; 1536 1463 1537 1464 switch (type) { 1465 + case WMFW_INFO_TEXT: 1538 1466 case WMFW_NAME_TEXT: 1539 - region_name = "Firmware name"; 1540 - text = kzalloc(le32_to_cpu(region->len) + 1, 1541 - GFP_KERNEL); 1467 + region_name = "Info/Name"; 1468 + cs_dsp_info(dsp, "%s: %.*s\n", file, 1469 + min(le32_to_cpu(region->len), 100), region->data); 1542 1470 break; 1543 1471 case WMFW_ALGORITHM_DATA: 1544 1472 region_name = "Algorithm"; 1545 1473 ret = cs_dsp_parse_coeff(dsp, region); 1546 1474 if (ret != 0) 1547 1475 goto out_fw; 1548 - break; 1549 - case WMFW_INFO_TEXT: 1550 - region_name = "Information"; 1551 - text = kzalloc(le32_to_cpu(region->len) + 1, 1552 - GFP_KERNEL); 1553 1476 break; 1554 1477 case WMFW_ABSOLUTE: 1555 1478 region_name = "Absolute"; ··· 1592 1497 cs_dsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file, 1593 1498 regions, le32_to_cpu(region->len), offset, 1594 1499 region_name); 1595 - 1596 - if (le32_to_cpu(region->len) > 1597 - firmware->size - pos - sizeof(*region)) { 1598 - cs_dsp_err(dsp, 1599 - "%s.%d: %s region len %d bytes exceeds file length %zu\n", 1600 - file, regions, region_name, 1601 - le32_to_cpu(region->len), firmware->size); 1602 - ret = -EINVAL; 1603 - goto out_fw; 1604 - } 1605 - 1606 - if (text) { 1607 - memcpy(text, region->data, le32_to_cpu(region->len)); 1608 - cs_dsp_info(dsp, "%s: %s\n", file, text); 1609 - kfree(text); 1610 - text = NULL; 1611 - } 1612 1500 1613 1501 if (reg) { 1614 1502 buf = cs_dsp_buf_alloc(region->data, ··· 1634 1556 out_fw: 1635 1557 regmap_async_complete(regmap); 1636 1558 cs_dsp_buf_free(&buf_list); 1637 - kfree(text); 1559 + 1560 + if (ret == -EOVERFLOW) 1561 + cs_dsp_err(dsp, "%s: file content overflows file data\n", file); 1638 1562 1639 1563 return ret; 1640 1564 } ··· 1782 1702 1783 1703 list_add_tail(&alg_region->list, &dsp->alg_regions); 1784 1704 1785 - if (dsp->fw_ver > 0) 1705 + if (dsp->wmfw_ver > 0) 1786 1706 cs_dsp_ctl_fixup_base(dsp, alg_region); 1787 1707 1788 1708 return alg_region; ··· 1905 1825 ret = PTR_ERR(alg_region); 1906 1826 goto out; 1907 1827 } 1908 - if (dsp->fw_ver == 0) { 1828 + if (dsp->wmfw_ver == 0) { 1909 1829 if (i + 1 < n_algs) { 1910 1830 len = be32_to_cpu(adsp1_alg[i + 1].dm); 1911 1831 len -= be32_to_cpu(adsp1_alg[i].dm); ··· 1927 1847 ret = PTR_ERR(alg_region); 1928 1848 goto out; 1929 1849 } 1930 - if (dsp->fw_ver == 0) { 1850 + if (dsp->wmfw_ver == 0) { 1931 1851 if (i + 1 < n_algs) { 1932 1852 len = be32_to_cpu(adsp1_alg[i + 1].zm); 1933 1853 len -= be32_to_cpu(adsp1_alg[i].zm); ··· 2018 1938 ret = PTR_ERR(alg_region); 2019 1939 goto out; 2020 1940 } 2021 - if (dsp->fw_ver == 0) { 1941 + if (dsp->wmfw_ver == 0) { 2022 1942 if (i + 1 < n_algs) { 2023 1943 len = be32_to_cpu(adsp2_alg[i + 1].xm); 2024 1944 len -= be32_to_cpu(adsp2_alg[i].xm); ··· 2040 1960 ret = PTR_ERR(alg_region); 2041 1961 goto out; 2042 1962 } 2043 - if (dsp->fw_ver == 0) { 1963 + if (dsp->wmfw_ver == 0) { 2044 1964 if (i + 1 < n_algs) { 2045 1965 len = be32_to_cpu(adsp2_alg[i + 1].ym); 2046 1966 len -= be32_to_cpu(adsp2_alg[i].ym); ··· 2062 1982 ret = PTR_ERR(alg_region); 2063 1983 goto out; 2064 1984 } 2065 - if (dsp->fw_ver == 0) { 1985 + if (dsp->wmfw_ver == 0) { 2066 1986 if (i + 1 < n_algs) { 2067 1987 len = be32_to_cpu(adsp2_alg[i + 1].zm); 2068 1988 len -= be32_to_cpu(adsp2_alg[i].zm); ··· 2166 2086 struct cs_dsp_alg_region *alg_region; 2167 2087 const char *region_name; 2168 2088 int ret, pos, blocks, type, offset, reg, version; 2169 - char *text = NULL; 2170 2089 struct cs_dsp_buf *buf; 2171 2090 2172 2091 if (!firmware) ··· 2204 2125 pos = le32_to_cpu(hdr->len); 2205 2126 2206 2127 blocks = 0; 2207 - while (pos < firmware->size && 2208 - sizeof(*blk) < firmware->size - pos) { 2128 + while (pos < firmware->size) { 2129 + /* Is there enough data for a complete block header? */ 2130 + if (sizeof(*blk) > firmware->size - pos) { 2131 + ret = -EOVERFLOW; 2132 + goto out_fw; 2133 + } 2134 + 2209 2135 blk = (void *)(&firmware->data[pos]); 2136 + 2137 + if (le32_to_cpu(blk->len) > firmware->size - pos - sizeof(*blk)) { 2138 + ret = -EOVERFLOW; 2139 + goto out_fw; 2140 + } 2210 2141 2211 2142 type = le16_to_cpu(blk->type); 2212 2143 offset = le16_to_cpu(blk->offset); ··· 2234 2145 region_name = "Unknown"; 2235 2146 switch (type) { 2236 2147 case (WMFW_NAME_TEXT << 8): 2237 - text = kzalloc(le32_to_cpu(blk->len) + 1, GFP_KERNEL); 2148 + cs_dsp_info(dsp, "%s: %.*s\n", dsp->fw_name, 2149 + min(le32_to_cpu(blk->len), 100), blk->data); 2238 2150 break; 2239 2151 case (WMFW_INFO_TEXT << 8): 2240 2152 case (WMFW_METADATA << 8): ··· 2307 2217 break; 2308 2218 } 2309 2219 2310 - if (text) { 2311 - memcpy(text, blk->data, le32_to_cpu(blk->len)); 2312 - cs_dsp_info(dsp, "%s: %s\n", dsp->fw_name, text); 2313 - kfree(text); 2314 - text = NULL; 2315 - } 2316 - 2317 2220 if (reg) { 2318 - if (le32_to_cpu(blk->len) > 2319 - firmware->size - pos - sizeof(*blk)) { 2320 - cs_dsp_err(dsp, 2321 - "%s.%d: %s region len %d bytes exceeds file length %zu\n", 2322 - file, blocks, region_name, 2323 - le32_to_cpu(blk->len), 2324 - firmware->size); 2325 - ret = -EINVAL; 2326 - goto out_fw; 2327 - } 2328 - 2329 2221 buf = cs_dsp_buf_alloc(blk->data, 2330 2222 le32_to_cpu(blk->len), 2331 2223 &buf_list); ··· 2346 2274 out_fw: 2347 2275 regmap_async_complete(regmap); 2348 2276 cs_dsp_buf_free(&buf_list); 2349 - kfree(text); 2277 + 2278 + if (ret == -EOVERFLOW) 2279 + cs_dsp_err(dsp, "%s: file content overflows file data\n", file); 2280 + 2350 2281 return ret; 2351 2282 } 2352 2283 ··· 2412 2337 * Return: Zero for success, a negative number on error. 2413 2338 */ 2414 2339 int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, 2415 - const struct firmware *wmfw_firmware, char *wmfw_filename, 2416 - const struct firmware *coeff_firmware, char *coeff_filename, 2340 + const struct firmware *wmfw_firmware, const char *wmfw_filename, 2341 + const struct firmware *coeff_firmware, const char *coeff_filename, 2417 2342 const char *fw_name) 2418 2343 { 2419 2344 unsigned int val; ··· 2706 2631 * Return: Zero for success, a negative number on error. 2707 2632 */ 2708 2633 int cs_dsp_power_up(struct cs_dsp *dsp, 2709 - const struct firmware *wmfw_firmware, char *wmfw_filename, 2710 - const struct firmware *coeff_firmware, char *coeff_filename, 2634 + const struct firmware *wmfw_firmware, const char *wmfw_filename, 2635 + const struct firmware *coeff_firmware, const char *coeff_filename, 2711 2636 const char *fw_name) 2712 2637 { 2713 2638 int ret;
+5 -5
include/linux/firmware/cirrus/cs_dsp.h
··· 167 167 const struct cs_dsp_region *mem; 168 168 int num_mems; 169 169 170 - int fw_ver; 170 + int wmfw_ver; 171 171 172 172 bool booted; 173 173 bool running; ··· 213 213 int cs_dsp_halo_init(struct cs_dsp *dsp); 214 214 215 215 int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, 216 - const struct firmware *wmfw_firmware, char *wmfw_filename, 217 - const struct firmware *coeff_firmware, char *coeff_filename, 216 + const struct firmware *wmfw_firmware, const char *wmfw_filename, 217 + const struct firmware *coeff_firmware, const char *coeff_filename, 218 218 const char *fw_name); 219 219 void cs_dsp_adsp1_power_down(struct cs_dsp *dsp); 220 220 int cs_dsp_power_up(struct cs_dsp *dsp, 221 - const struct firmware *wmfw_firmware, char *wmfw_filename, 222 - const struct firmware *coeff_firmware, char *coeff_filename, 221 + const struct firmware *wmfw_firmware, const char *wmfw_filename, 222 + const struct firmware *coeff_firmware, const char *coeff_filename, 223 223 const char *fw_name); 224 224 void cs_dsp_power_down(struct cs_dsp *dsp); 225 225 int cs_dsp_run(struct cs_dsp *dsp);
+7
sound/soc/amd/yc/acp6x-mach.c
··· 283 283 DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA"), 284 284 } 285 285 }, 286 + { 287 + .driver_data = &acp6x_card, 288 + .matches = { 289 + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), 290 + DMI_MATCH(DMI_PRODUCT_NAME, "M5602RA"), 291 + } 292 + }, 286 293 { 287 294 .driver_data = &acp6x_card, 288 295 .matches = {
+18 -6
sound/soc/codecs/rt5645.c
··· 81 81 static const struct reg_sequence rt5650_init_list[] = { 82 82 {0xf6, 0x0100}, 83 83 {RT5645_PWR_ANLG1, 0x02}, 84 - {RT5645_IL_CMD3, 0x0018}, 84 + {RT5645_IL_CMD3, 0x6728}, 85 85 }; 86 86 87 87 static const struct reg_default rt5645_reg[] = { ··· 3130 3130 bool enable) 3131 3131 { 3132 3132 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 3133 + int ret; 3133 3134 3134 3135 if (enable) { 3135 3136 snd_soc_dapm_force_enable_pin(dapm, "ADC L power"); 3136 3137 snd_soc_dapm_force_enable_pin(dapm, "ADC R power"); 3137 3138 snd_soc_dapm_sync(dapm); 3138 3139 3140 + snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 3141 + RT5645_EN_4BTN_IL_MASK | RT5645_RST_4BTN_IL_MASK, 3142 + RT5645_EN_4BTN_IL_EN | RT5645_RST_4BTN_IL_RST); 3143 + usleep_range(10000, 15000); 3144 + snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 3145 + RT5645_EN_4BTN_IL_MASK | RT5645_RST_4BTN_IL_MASK, 3146 + RT5645_EN_4BTN_IL_EN | RT5645_RST_4BTN_IL_NORM); 3147 + msleep(50); 3148 + ret = snd_soc_component_read(component, RT5645_INT_IRQ_ST); 3149 + pr_debug("%s read %x = %x\n", __func__, RT5645_INT_IRQ_ST, 3150 + snd_soc_component_read(component, RT5645_INT_IRQ_ST)); 3151 + snd_soc_component_write(component, RT5645_INT_IRQ_ST, ret); 3152 + ret = snd_soc_component_read(component, RT5650_4BTN_IL_CMD1); 3153 + pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1, 3154 + snd_soc_component_read(component, RT5650_4BTN_IL_CMD1)); 3155 + snd_soc_component_write(component, RT5650_4BTN_IL_CMD1, ret); 3139 3156 snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD1, 0x3, 0x3); 3140 3157 snd_soc_component_update_bits(component, 3141 3158 RT5645_INT_IRQ_ST, 0x8, 0x8); 3142 - snd_soc_component_update_bits(component, 3143 - RT5650_4BTN_IL_CMD2, 0x8000, 0x8000); 3144 - snd_soc_component_read(component, RT5650_4BTN_IL_CMD1); 3145 - pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1, 3146 - snd_soc_component_read(component, RT5650_4BTN_IL_CMD1)); 3147 3159 } else { 3148 3160 snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 0x8000, 0x0); 3149 3161 snd_soc_component_update_bits(component, RT5645_INT_IRQ_ST, 0x8, 0x0);
+6
sound/soc/codecs/rt5645.h
··· 2011 2011 #define RT5645_ZCD_HP_DIS (0x0 << 15) 2012 2012 #define RT5645_ZCD_HP_EN (0x1 << 15) 2013 2013 2014 + /* Buttons Inline Command Function 2 (0xe0) */ 2015 + #define RT5645_EN_4BTN_IL_MASK (0x1 << 15) 2016 + #define RT5645_EN_4BTN_IL_EN (0x1 << 15) 2017 + #define RT5645_RST_4BTN_IL_MASK (0x1 << 14) 2018 + #define RT5645_RST_4BTN_IL_RST (0x0 << 14) 2019 + #define RT5645_RST_4BTN_IL_NORM (0x1 << 14) 2014 2020 2015 2021 /* Codec Private Register definition */ 2016 2022 /* DAC ADC Digital Volume (0x00) */
+2
sound/soc/codecs/rt711-sdw.c
··· 38 38 case 0x8300 ... 0x83ff: 39 39 case 0x9c00 ... 0x9cff: 40 40 case 0xb900 ... 0xb9ff: 41 + case 0x752008: 41 42 case 0x752009: 43 + case 0x75200b: 42 44 case 0x752011: 43 45 case 0x75201a: 44 46 case 0x752045:
+1 -1
sound/soc/codecs/wm_adsp.c
··· 601 601 return -EINVAL; 602 602 } 603 603 604 - switch (cs_dsp->fw_ver) { 604 + switch (cs_dsp->wmfw_ver) { 605 605 case 0: 606 606 case 1: 607 607 ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+1
sound/soc/mediatek/mt8195/mt8195-mt6359.c
··· 827 827 828 828 SND_SOC_DAILINK_DEFS(ETDM1_OUT_BE, 829 829 DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_OUT")), 830 + DAILINK_COMP_ARRAY(COMP_EMPTY()), 830 831 DAILINK_COMP_ARRAY(COMP_EMPTY())); 831 832 832 833 SND_SOC_DAILINK_DEFS(ETDM2_OUT_BE,
+6 -6
sound/soc/sof/intel/hda-dai.c
··· 617 617 sdai = swidget->private; 618 618 ops = sdai->platform_private; 619 619 620 - ret = hda_link_dma_cleanup(hext_stream->link_substream, 621 - hext_stream, 622 - cpu_dai); 623 - if (ret < 0) 624 - return ret; 625 - 626 620 /* for consistency with TRIGGER_SUSPEND */ 627 621 if (ops->post_trigger) { 628 622 ret = ops->post_trigger(sdev, cpu_dai, ··· 625 631 if (ret < 0) 626 632 return ret; 627 633 } 634 + 635 + ret = hda_link_dma_cleanup(hext_stream->link_substream, 636 + hext_stream, 637 + cpu_dai); 638 + if (ret < 0) 639 + return ret; 628 640 } 629 641 } 630 642
+6
sound/soc/sof/intel/hda-pcm.c
··· 258 258 snd_pcm_hw_constraint_integer(substream->runtime, 259 259 SNDRV_PCM_HW_PARAM_PERIODS); 260 260 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 + 261 267 /* Only S16 and S32 supported by HDA hardware when used without DSP */ 262 268 if (sdev->dspless_mode_selected) 263 269 snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT,