mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 14:13:53 +00:00
sound fixes for 6.10-final
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. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmaQAxwOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE9AUA//ZxtSF9W8prfSVHWJt7vmCnsPfmYr+xC+I5H1 Lys8i/eE+VCz+1s8esgwaatvLTQOBAWupnSpItLk4rVymzTIDih/FJGfQkxEQPj+ bEWXep67COCatq7YqwXcHPvnjNTC1x3KQeqYeyL/NXcIj891SBw8Ao2CEx4L8O4w w6BWD95KhjdXAhc49U+1F89sDF+EG96uMBAcDWLtiteo38exsH87Fd+Q3/ZaPJ9Q 9cRful99yWijgKmpsazwNaWFJgc7ScyXiE2eCinS3etRYTUW7jTHlHxMTWrRrkLj L3jNzhEuq5TUNXECd74yghpuq/TWqLkJ8lp7HBs87ZgK5cz7avE+Fb/6EC4oQ6sQ 48XlL4j5E3gme0X9Mdq/LmuefxWUGQGQYkJDixaI6hUgvhd8b/pJEvtefjTmkwIG EqHUtJ4tsAsnmF2xu7w6jG/Ng4Oo3W8NpexBcIkTvOIm7k9C95lQ0ctBgG9H+Khi YPq7V36LfaFfG8fneHjqpUlDOVWYtL0mfqkfB6Vt3BSqxtJrPqOXC0nruC5LD+rW tnWlAbMP55+q0QD3h8gp1+auF/LbYxcIX3kXT/TuBsrMchpPxrg/mb4x00vludYn vBL/IB+ZgbQzxDI38sP2NhTG/RKrN75rePqR6BbIIX1otkCnSqJ406qzVhImD6yF HxsqOV4= =xfjV -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
9b48104b2c
@ -1107,9 +1107,16 @@ struct cs_dsp_coeff_parsed_coeff {
|
||||
int len;
|
||||
};
|
||||
|
||||
static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
|
||||
static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, unsigned int avail,
|
||||
const u8 **str)
|
||||
{
|
||||
int length;
|
||||
int length, total_field_len;
|
||||
|
||||
/* String fields are at least one __le32 */
|
||||
if (sizeof(__le32) > avail) {
|
||||
*pos = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (bytes) {
|
||||
case 1:
|
||||
@ -1122,10 +1129,16 @@ static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
total_field_len = ((length + bytes) + 3) & ~0x03;
|
||||
if ((unsigned int)total_field_len > avail) {
|
||||
*pos = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (str)
|
||||
*str = *pos + bytes;
|
||||
|
||||
*pos += ((length + bytes) + 3) & ~0x03;
|
||||
*pos += total_field_len;
|
||||
|
||||
return length;
|
||||
}
|
||||
@ -1150,71 +1163,134 @@ static int cs_dsp_coeff_parse_int(int bytes, const u8 **pos)
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void cs_dsp_coeff_parse_alg(struct cs_dsp *dsp, const u8 **data,
|
||||
struct cs_dsp_coeff_parsed_alg *blk)
|
||||
static int cs_dsp_coeff_parse_alg(struct cs_dsp *dsp,
|
||||
const struct wmfw_region *region,
|
||||
struct cs_dsp_coeff_parsed_alg *blk)
|
||||
{
|
||||
const struct wmfw_adsp_alg_data *raw;
|
||||
unsigned int data_len = le32_to_cpu(region->len);
|
||||
unsigned int pos;
|
||||
const u8 *tmp;
|
||||
|
||||
raw = (const struct wmfw_adsp_alg_data *)region->data;
|
||||
|
||||
switch (dsp->fw_ver) {
|
||||
case 0:
|
||||
case 1:
|
||||
raw = (const struct wmfw_adsp_alg_data *)*data;
|
||||
*data = raw->data;
|
||||
if (sizeof(*raw) > data_len)
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk->id = le32_to_cpu(raw->id);
|
||||
blk->name = raw->name;
|
||||
blk->name_len = strlen(raw->name);
|
||||
blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
|
||||
blk->ncoeff = le32_to_cpu(raw->ncoeff);
|
||||
|
||||
pos = sizeof(*raw);
|
||||
break;
|
||||
default:
|
||||
blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), data);
|
||||
blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), data,
|
||||
if (sizeof(raw->id) > data_len)
|
||||
return -EOVERFLOW;
|
||||
|
||||
tmp = region->data;
|
||||
blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), &tmp);
|
||||
pos = tmp - region->data;
|
||||
|
||||
tmp = ®ion->data[pos];
|
||||
blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
|
||||
&blk->name);
|
||||
cs_dsp_coeff_parse_string(sizeof(u16), data, NULL);
|
||||
blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), data);
|
||||
if (!tmp)
|
||||
return -EOVERFLOW;
|
||||
|
||||
pos = tmp - region->data;
|
||||
cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
|
||||
if (!tmp)
|
||||
return -EOVERFLOW;
|
||||
|
||||
pos = tmp - region->data;
|
||||
if (sizeof(raw->ncoeff) > (data_len - pos))
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), &tmp);
|
||||
pos += sizeof(raw->ncoeff);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((int)blk->ncoeff < 0)
|
||||
return -EOVERFLOW;
|
||||
|
||||
cs_dsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
|
||||
cs_dsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
|
||||
cs_dsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
|
||||
struct cs_dsp_coeff_parsed_coeff *blk)
|
||||
static int cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp,
|
||||
const struct wmfw_region *region,
|
||||
unsigned int pos,
|
||||
struct cs_dsp_coeff_parsed_coeff *blk)
|
||||
{
|
||||
const struct wmfw_adsp_coeff_data *raw;
|
||||
unsigned int data_len = le32_to_cpu(region->len);
|
||||
unsigned int blk_len, blk_end_pos;
|
||||
const u8 *tmp;
|
||||
int length;
|
||||
|
||||
raw = (const struct wmfw_adsp_coeff_data *)®ion->data[pos];
|
||||
if (sizeof(raw->hdr) > (data_len - pos))
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk_len = le32_to_cpu(raw->hdr.size);
|
||||
if (blk_len > S32_MAX)
|
||||
return -EOVERFLOW;
|
||||
|
||||
if (blk_len > (data_len - pos - sizeof(raw->hdr)))
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk_end_pos = pos + sizeof(raw->hdr) + blk_len;
|
||||
|
||||
blk->offset = le16_to_cpu(raw->hdr.offset);
|
||||
blk->mem_type = le16_to_cpu(raw->hdr.type);
|
||||
|
||||
switch (dsp->fw_ver) {
|
||||
case 0:
|
||||
case 1:
|
||||
raw = (const struct wmfw_adsp_coeff_data *)*data;
|
||||
*data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
|
||||
if (sizeof(*raw) > (data_len - pos))
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk->offset = le16_to_cpu(raw->hdr.offset);
|
||||
blk->mem_type = le16_to_cpu(raw->hdr.type);
|
||||
blk->name = raw->name;
|
||||
blk->name_len = strlen(raw->name);
|
||||
blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
|
||||
blk->ctl_type = le16_to_cpu(raw->ctl_type);
|
||||
blk->flags = le16_to_cpu(raw->flags);
|
||||
blk->len = le32_to_cpu(raw->len);
|
||||
break;
|
||||
default:
|
||||
tmp = *data;
|
||||
blk->offset = cs_dsp_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
|
||||
blk->mem_type = cs_dsp_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
|
||||
length = cs_dsp_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
|
||||
blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp,
|
||||
pos += sizeof(raw->hdr);
|
||||
tmp = ®ion->data[pos];
|
||||
blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
|
||||
&blk->name);
|
||||
cs_dsp_coeff_parse_string(sizeof(u8), &tmp, NULL);
|
||||
cs_dsp_coeff_parse_string(sizeof(u16), &tmp, NULL);
|
||||
blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
|
||||
blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp);
|
||||
blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp);
|
||||
if (!tmp)
|
||||
return -EOVERFLOW;
|
||||
|
||||
*data = *data + sizeof(raw->hdr) + length;
|
||||
pos = tmp - region->data;
|
||||
cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos, NULL);
|
||||
if (!tmp)
|
||||
return -EOVERFLOW;
|
||||
|
||||
pos = tmp - region->data;
|
||||
cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
|
||||
if (!tmp)
|
||||
return -EOVERFLOW;
|
||||
|
||||
pos = tmp - region->data;
|
||||
if (sizeof(raw->ctl_type) + sizeof(raw->flags) + sizeof(raw->len) >
|
||||
(data_len - pos))
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
|
||||
pos += sizeof(raw->ctl_type);
|
||||
blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp);
|
||||
pos += sizeof(raw->flags);
|
||||
blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1224,6 +1300,8 @@ static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
|
||||
cs_dsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
|
||||
cs_dsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
|
||||
cs_dsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);
|
||||
|
||||
return blk_end_pos;
|
||||
}
|
||||
|
||||
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,
|
||||
struct cs_dsp_alg_region alg_region = {};
|
||||
struct cs_dsp_coeff_parsed_alg alg_blk;
|
||||
struct cs_dsp_coeff_parsed_coeff coeff_blk;
|
||||
const u8 *data = region->data;
|
||||
int i, ret;
|
||||
int i, pos, ret;
|
||||
|
||||
pos = cs_dsp_coeff_parse_alg(dsp, region, &alg_blk);
|
||||
if (pos < 0)
|
||||
return pos;
|
||||
|
||||
cs_dsp_coeff_parse_alg(dsp, &data, &alg_blk);
|
||||
for (i = 0; i < alg_blk.ncoeff; i++) {
|
||||
cs_dsp_coeff_parse_coeff(dsp, &data, &coeff_blk);
|
||||
pos = cs_dsp_coeff_parse_coeff(dsp, region, pos, &coeff_blk);
|
||||
if (pos < 0)
|
||||
return pos;
|
||||
|
||||
switch (coeff_blk.ctl_type) {
|
||||
case WMFW_CTL_TYPE_BYTES:
|
||||
@ -1321,6 +1403,10 @@ static unsigned int cs_dsp_adsp1_parse_sizes(struct cs_dsp *dsp,
|
||||
const struct wmfw_adsp1_sizes *adsp1_sizes;
|
||||
|
||||
adsp1_sizes = (void *)&firmware->data[pos];
|
||||
if (sizeof(*adsp1_sizes) > firmware->size - pos) {
|
||||
cs_dsp_err(dsp, "%s: file truncated\n", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
|
||||
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,
|
||||
const struct wmfw_adsp2_sizes *adsp2_sizes;
|
||||
|
||||
adsp2_sizes = (void *)&firmware->data[pos];
|
||||
if (sizeof(*adsp2_sizes) > firmware->size - pos) {
|
||||
cs_dsp_err(dsp, "%s: file truncated\n", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
|
||||
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,
|
||||
struct regmap *regmap = dsp->regmap;
|
||||
unsigned int pos = 0;
|
||||
const struct wmfw_header *header;
|
||||
const struct wmfw_adsp1_sizes *adsp1_sizes;
|
||||
const struct wmfw_footer *footer;
|
||||
const struct wmfw_region *region;
|
||||
const struct cs_dsp_region *mem;
|
||||
@ -1392,10 +1481,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
|
||||
ret = -EINVAL;
|
||||
|
||||
pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
|
||||
if (pos >= firmware->size) {
|
||||
cs_dsp_err(dsp, "%s: file too short, %zu bytes\n",
|
||||
file, firmware->size);
|
||||
if (sizeof(*header) >= firmware->size) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
@ -1423,22 +1510,36 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
|
||||
pos = sizeof(*header);
|
||||
pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
|
||||
if ((pos == 0) || (sizeof(*footer) > firmware->size - pos)) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
footer = (void *)&firmware->data[pos];
|
||||
pos += sizeof(*footer);
|
||||
|
||||
if (le32_to_cpu(header->len) != pos) {
|
||||
cs_dsp_err(dsp, "%s: unexpected header length %d\n",
|
||||
file, le32_to_cpu(header->len));
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file,
|
||||
le64_to_cpu(footer->timestamp));
|
||||
|
||||
while (pos < firmware->size &&
|
||||
sizeof(*region) < firmware->size - pos) {
|
||||
while (pos < firmware->size) {
|
||||
/* Is there enough data for a complete block header? */
|
||||
if (sizeof(*region) > firmware->size - pos) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
region = (void *)&(firmware->data[pos]);
|
||||
|
||||
if (le32_to_cpu(region->len) > firmware->size - pos - sizeof(*region)) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
region_name = "Unknown";
|
||||
reg = 0;
|
||||
text = NULL;
|
||||
@ -1495,16 +1596,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
regions, le32_to_cpu(region->len), offset,
|
||||
region_name);
|
||||
|
||||
if (le32_to_cpu(region->len) >
|
||||
firmware->size - pos - sizeof(*region)) {
|
||||
cs_dsp_err(dsp,
|
||||
"%s.%d: %s region len %d bytes exceeds file length %zu\n",
|
||||
file, regions, region_name,
|
||||
le32_to_cpu(region->len), firmware->size);
|
||||
ret = -EINVAL;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
if (text) {
|
||||
memcpy(text, region->data, le32_to_cpu(region->len));
|
||||
cs_dsp_info(dsp, "%s: %s\n", file, text);
|
||||
@ -1555,6 +1646,9 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
cs_dsp_buf_free(&buf_list);
|
||||
kfree(text);
|
||||
|
||||
if (ret == -EOVERFLOW)
|
||||
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2122,10 +2216,20 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
||||
pos = le32_to_cpu(hdr->len);
|
||||
|
||||
blocks = 0;
|
||||
while (pos < firmware->size &&
|
||||
sizeof(*blk) < firmware->size - pos) {
|
||||
while (pos < firmware->size) {
|
||||
/* Is there enough data for a complete block header? */
|
||||
if (sizeof(*blk) > firmware->size - pos) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
blk = (void *)(&firmware->data[pos]);
|
||||
|
||||
if (le32_to_cpu(blk->len) > firmware->size - pos - sizeof(*blk)) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
type = le16_to_cpu(blk->type);
|
||||
offset = le16_to_cpu(blk->offset);
|
||||
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
|
||||
}
|
||||
|
||||
if (reg) {
|
||||
if (le32_to_cpu(blk->len) >
|
||||
firmware->size - pos - sizeof(*blk)) {
|
||||
cs_dsp_err(dsp,
|
||||
"%s.%d: %s region len %d bytes exceeds file length %zu\n",
|
||||
file, blocks, region_name,
|
||||
le32_to_cpu(blk->len),
|
||||
firmware->size);
|
||||
ret = -EINVAL;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
buf = cs_dsp_buf_alloc(blk->data,
|
||||
le32_to_cpu(blk->len),
|
||||
&buf_list);
|
||||
@ -2272,6 +2365,10 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
||||
regmap_async_complete(regmap);
|
||||
cs_dsp_buf_free(&buf_list);
|
||||
kfree(text);
|
||||
|
||||
if (ret == -EOVERFLOW)
|
||||
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -128,8 +128,8 @@ static const struct cs35l41_config cs35l41_config_table[] = {
|
||||
{ "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
|
||||
{ "17AA38B6", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
|
||||
{ "17AA38B7", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
|
||||
{ "17AA38C7", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 2, -1, 1000, 4500, 24 },
|
||||
{ "17AA38C8", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 2, -1, 1000, 4500, 24 },
|
||||
{ "17AA38C7", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 },
|
||||
{ "17AA38C8", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 },
|
||||
{ "17AA38F9", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
|
||||
{ "17AA38FA", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
|
||||
{}
|
||||
|
@ -10053,6 +10053,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
@ -10383,6 +10384,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
|
||||
SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE),
|
||||
SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x10ec, 0x11bc, "VAIO VJFE-IL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
|
||||
SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
|
||||
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[] = {
|
||||
SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL50NU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xa650, "Clevo NP[567]0SN[CD]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xa671, "Clevo NP70SN[CDE]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xa763, "Clevo V54x_6x_TU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
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[] = {
|
||||
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
|
||||
SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
|
||||
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
|
||||
|
@ -38,7 +38,9 @@ static bool rt711_readable_register(struct device *dev, unsigned int reg)
|
||||
case 0x8300 ... 0x83ff:
|
||||
case 0x9c00 ... 0x9cff:
|
||||
case 0xb900 ... 0xb9ff:
|
||||
case 0x752008:
|
||||
case 0x752009:
|
||||
case 0x75200b:
|
||||
case 0x752011:
|
||||
case 0x75201a:
|
||||
case 0x752045:
|
||||
|
@ -617,12 +617,6 @@ static int hda_dai_suspend(struct hdac_bus *bus)
|
||||
sdai = swidget->private;
|
||||
ops = sdai->platform_private;
|
||||
|
||||
ret = hda_link_dma_cleanup(hext_stream->link_substream,
|
||||
hext_stream,
|
||||
cpu_dai);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* for consistency with TRIGGER_SUSPEND */
|
||||
if (ops->post_trigger) {
|
||||
ret = ops->post_trigger(sdev, cpu_dai,
|
||||
@ -631,6 +625,12 @@ static int hda_dai_suspend(struct hdac_bus *bus)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hda_link_dma_cleanup(hext_stream->link_substream,
|
||||
hext_stream,
|
||||
cpu_dai);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,6 +258,12 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
|
||||
snd_pcm_hw_constraint_integer(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
|
||||
/* Limit the maximum number of periods to not exceed the BDL entries count */
|
||||
if (runtime->hw.periods_max > HDA_DSP_MAX_BDL_ENTRIES)
|
||||
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
|
||||
runtime->hw.periods_min,
|
||||
HDA_DSP_MAX_BDL_ENTRIES);
|
||||
|
||||
/* Only S16 and S32 supported by HDA hardware when used without DSP */
|
||||
if (sdev->dspless_mode_selected)
|
||||
snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
|
Loading…
Reference in New Issue
Block a user