Loading drivers/firmware/cirrus/cs_dsp.c +185 −110 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ #include <linux/ctype.h> #include <linux/debugfs.h> #include <linux/delay.h> #include <linux/minmax.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/seq_file.h> Loading Loading @@ -1050,7 +1051,7 @@ static int cs_dsp_create_control(struct cs_dsp *dsp, ctl->fw_name = dsp->fw_name; ctl->alg_region = *alg_region; if (subname && dsp->fw_ver >= 2) { if (subname && dsp->wmfw_ver >= 2) { ctl->subname_len = subname_len; ctl->subname = kasprintf(GFP_KERNEL, "%.*s", subname_len, subname); if (!ctl->subname) { Loading Loading @@ -1110,9 +1111,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: Loading @@ -1125,10 +1133,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; } Loading @@ -1153,71 +1167,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, 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) { switch (dsp->wmfw_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, 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; 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); 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->wmfw_ver) { case 0: case 1: if (sizeof(*raw) > (data_len - pos)) return -EOVERFLOW; 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); if (!tmp) return -EOVERFLOW; 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); *data = *data + sizeof(raw->hdr) + length; break; } Loading @@ -1227,6 +1304,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, Loading @@ -1250,12 +1329,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: Loading Loading @@ -1324,6 +1407,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), Loading @@ -1340,6 +1427,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), Loading Loading @@ -1379,12 +1470,10 @@ 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; const char *region_name; char *text = NULL; struct cs_dsp_buf *buf; unsigned int reg; int regions = 0; Loading @@ -1395,10 +1484,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; } Loading @@ -1415,8 +1502,7 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, goto out_fw; } cs_dsp_info(dsp, "Firmware version: %d\n", header->ver); dsp->fw_ver = header->ver; dsp->wmfw_ver = header->ver; if (header->core != dsp->type) { cs_dsp_err(dsp, "%s: invalid core %d != %d\n", Loading @@ -1426,33 +1512,47 @@ 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, cs_dsp_info(dsp, "%s: format %d timestamp %#llx\n", file, header->ver, 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; offset = le32_to_cpu(region->offset) & 0xffffff; type = be32_to_cpu(region->type) & 0xff; switch (type) { case WMFW_INFO_TEXT: case WMFW_NAME_TEXT: region_name = "Firmware name"; text = kzalloc(le32_to_cpu(region->len) + 1, GFP_KERNEL); region_name = "Info/Name"; cs_dsp_info(dsp, "%s: %.*s\n", file, min(le32_to_cpu(region->len), 100), region->data); break; case WMFW_ALGORITHM_DATA: region_name = "Algorithm"; Loading @@ -1460,11 +1560,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, if (ret != 0) goto out_fw; break; case WMFW_INFO_TEXT: region_name = "Information"; text = kzalloc(le32_to_cpu(region->len) + 1, GFP_KERNEL); break; case WMFW_ABSOLUTE: region_name = "Absolute"; reg = offset; Loading Loading @@ -1498,23 +1593,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); kfree(text); text = NULL; } if (reg) { buf = cs_dsp_buf_alloc(region->data, le32_to_cpu(region->len), Loading Loading @@ -1556,7 +1634,9 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, out_fw: 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; } Loading Loading @@ -1702,7 +1782,7 @@ static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp, list_add_tail(&alg_region->list, &dsp->alg_regions); if (dsp->fw_ver > 0) if (dsp->wmfw_ver > 0) cs_dsp_ctl_fixup_base(dsp, alg_region); return alg_region; Loading Loading @@ -1825,7 +1905,7 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp) ret = PTR_ERR(alg_region); goto out; } if (dsp->fw_ver == 0) { if (dsp->wmfw_ver == 0) { if (i + 1 < n_algs) { len = be32_to_cpu(adsp1_alg[i + 1].dm); len -= be32_to_cpu(adsp1_alg[i].dm); Loading @@ -1847,7 +1927,7 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp) ret = PTR_ERR(alg_region); goto out; } if (dsp->fw_ver == 0) { if (dsp->wmfw_ver == 0) { if (i + 1 < n_algs) { len = be32_to_cpu(adsp1_alg[i + 1].zm); len -= be32_to_cpu(adsp1_alg[i].zm); Loading Loading @@ -1938,7 +2018,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp) ret = PTR_ERR(alg_region); goto out; } if (dsp->fw_ver == 0) { if (dsp->wmfw_ver == 0) { if (i + 1 < n_algs) { len = be32_to_cpu(adsp2_alg[i + 1].xm); len -= be32_to_cpu(adsp2_alg[i].xm); Loading @@ -1960,7 +2040,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp) ret = PTR_ERR(alg_region); goto out; } if (dsp->fw_ver == 0) { if (dsp->wmfw_ver == 0) { if (i + 1 < n_algs) { len = be32_to_cpu(adsp2_alg[i + 1].ym); len -= be32_to_cpu(adsp2_alg[i].ym); Loading @@ -1982,7 +2062,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp) ret = PTR_ERR(alg_region); goto out; } if (dsp->fw_ver == 0) { if (dsp->wmfw_ver == 0) { if (i + 1 < n_algs) { len = be32_to_cpu(adsp2_alg[i + 1].zm); len -= be32_to_cpu(adsp2_alg[i].zm); Loading Loading @@ -2086,7 +2166,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware struct cs_dsp_alg_region *alg_region; const char *region_name; int ret, pos, blocks, type, offset, reg, version; char *text = NULL; struct cs_dsp_buf *buf; if (!firmware) Loading Loading @@ -2125,10 +2204,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; Loading @@ -2145,7 +2234,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware region_name = "Unknown"; switch (type) { case (WMFW_NAME_TEXT << 8): text = kzalloc(le32_to_cpu(blk->len) + 1, GFP_KERNEL); cs_dsp_info(dsp, "%s: %.*s\n", dsp->fw_name, min(le32_to_cpu(blk->len), 100), blk->data); break; case (WMFW_INFO_TEXT << 8): case (WMFW_METADATA << 8): Loading Loading @@ -2217,25 +2307,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware break; } if (text) { memcpy(text, blk->data, le32_to_cpu(blk->len)); cs_dsp_info(dsp, "%s: %s\n", dsp->fw_name, text); kfree(text); text = NULL; } 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); Loading Loading @@ -2274,7 +2346,10 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware out_fw: 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; } Loading Loading @@ -2337,8 +2412,8 @@ EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_init, FW_CS_DSP); * Return: Zero for success, a negative number on error. */ int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, const struct firmware *wmfw_firmware, char *wmfw_filename, const struct firmware *coeff_firmware, char *coeff_filename, const struct firmware *wmfw_firmware, const char *wmfw_filename, const struct firmware *coeff_firmware, const char *coeff_filename, const char *fw_name) { unsigned int val; Loading Loading @@ -2631,8 +2706,8 @@ static void cs_dsp_halo_stop_watchdog(struct cs_dsp *dsp) * Return: Zero for success, a negative number on error. */ int cs_dsp_power_up(struct cs_dsp *dsp, const struct firmware *wmfw_firmware, char *wmfw_filename, const struct firmware *coeff_firmware, char *coeff_filename, const struct firmware *wmfw_firmware, const char *wmfw_filename, const struct firmware *coeff_firmware, const char *coeff_filename, const char *fw_name) { int ret; Loading include/linux/firmware/cirrus/cs_dsp.h +5 −5 Original line number Diff line number Diff line Loading @@ -167,7 +167,7 @@ struct cs_dsp { const struct cs_dsp_region *mem; int num_mems; int fw_ver; int wmfw_ver; bool booted; bool running; Loading Loading @@ -213,13 +213,13 @@ int cs_dsp_adsp2_init(struct cs_dsp *dsp); int cs_dsp_halo_init(struct cs_dsp *dsp); int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, const struct firmware *wmfw_firmware, char *wmfw_filename, const struct firmware *coeff_firmware, char *coeff_filename, const struct firmware *wmfw_firmware, const char *wmfw_filename, const struct firmware *coeff_firmware, const char *coeff_filename, const char *fw_name); void cs_dsp_adsp1_power_down(struct cs_dsp *dsp); int cs_dsp_power_up(struct cs_dsp *dsp, const struct firmware *wmfw_firmware, char *wmfw_filename, const struct firmware *coeff_firmware, char *coeff_filename, const struct firmware *wmfw_firmware, const char *wmfw_filename, const struct firmware *coeff_firmware, const char *coeff_filename, const char *fw_name); void cs_dsp_power_down(struct cs_dsp *dsp); int cs_dsp_run(struct cs_dsp *dsp); Loading sound/soc/amd/yc/acp6x-mach.c +7 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA"), } }, { .driver_data = &acp6x_card, .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "M5602RA"), } }, { .driver_data = &acp6x_card, .matches = { Loading sound/soc/codecs/rt5645.c +18 −6 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ static const struct reg_sequence init_list[] = { static const struct reg_sequence rt5650_init_list[] = { {0xf6, 0x0100}, {RT5645_PWR_ANLG1, 0x02}, {RT5645_IL_CMD3, 0x0018}, {RT5645_IL_CMD3, 0x6728}, }; static const struct reg_default rt5645_reg[] = { Loading Loading @@ -3130,20 +3130,32 @@ static void rt5645_enable_push_button_irq(struct snd_soc_component *component, bool enable) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); int ret; if (enable) { snd_soc_dapm_force_enable_pin(dapm, "ADC L power"); snd_soc_dapm_force_enable_pin(dapm, "ADC R power"); snd_soc_dapm_sync(dapm); snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, RT5645_EN_4BTN_IL_MASK | RT5645_RST_4BTN_IL_MASK, RT5645_EN_4BTN_IL_EN | RT5645_RST_4BTN_IL_RST); usleep_range(10000, 15000); snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, RT5645_EN_4BTN_IL_MASK | RT5645_RST_4BTN_IL_MASK, RT5645_EN_4BTN_IL_EN | RT5645_RST_4BTN_IL_NORM); msleep(50); ret = snd_soc_component_read(component, RT5645_INT_IRQ_ST); pr_debug("%s read %x = %x\n", __func__, RT5645_INT_IRQ_ST, snd_soc_component_read(component, RT5645_INT_IRQ_ST)); snd_soc_component_write(component, RT5645_INT_IRQ_ST, ret); ret = snd_soc_component_read(component, RT5650_4BTN_IL_CMD1); pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1, snd_soc_component_read(component, RT5650_4BTN_IL_CMD1)); snd_soc_component_write(component, RT5650_4BTN_IL_CMD1, ret); snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD1, 0x3, 0x3); snd_soc_component_update_bits(component, RT5645_INT_IRQ_ST, 0x8, 0x8); snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 0x8000, 0x8000); snd_soc_component_read(component, RT5650_4BTN_IL_CMD1); pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1, snd_soc_component_read(component, RT5650_4BTN_IL_CMD1)); } else { snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 0x8000, 0x0); snd_soc_component_update_bits(component, RT5645_INT_IRQ_ST, 0x8, 0x0); Loading sound/soc/codecs/rt5645.h +6 −0 Original line number Diff line number Diff line Loading @@ -2011,6 +2011,12 @@ #define RT5645_ZCD_HP_DIS (0x0 << 15) #define RT5645_ZCD_HP_EN (0x1 << 15) /* Buttons Inline Command Function 2 (0xe0) */ #define RT5645_EN_4BTN_IL_MASK (0x1 << 15) #define RT5645_EN_4BTN_IL_EN (0x1 << 15) #define RT5645_RST_4BTN_IL_MASK (0x1 << 14) #define RT5645_RST_4BTN_IL_RST (0x0 << 14) #define RT5645_RST_4BTN_IL_NORM (0x1 << 14) /* Codec Private Register definition */ /* DAC ADC Digital Volume (0x00) */ Loading Loading
drivers/firmware/cirrus/cs_dsp.c +185 −110 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ #include <linux/ctype.h> #include <linux/debugfs.h> #include <linux/delay.h> #include <linux/minmax.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/seq_file.h> Loading Loading @@ -1050,7 +1051,7 @@ static int cs_dsp_create_control(struct cs_dsp *dsp, ctl->fw_name = dsp->fw_name; ctl->alg_region = *alg_region; if (subname && dsp->fw_ver >= 2) { if (subname && dsp->wmfw_ver >= 2) { ctl->subname_len = subname_len; ctl->subname = kasprintf(GFP_KERNEL, "%.*s", subname_len, subname); if (!ctl->subname) { Loading Loading @@ -1110,9 +1111,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: Loading @@ -1125,10 +1133,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; } Loading @@ -1153,71 +1167,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, 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) { switch (dsp->wmfw_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, 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; 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); 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->wmfw_ver) { case 0: case 1: if (sizeof(*raw) > (data_len - pos)) return -EOVERFLOW; 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); if (!tmp) return -EOVERFLOW; 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); *data = *data + sizeof(raw->hdr) + length; break; } Loading @@ -1227,6 +1304,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, Loading @@ -1250,12 +1329,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: Loading Loading @@ -1324,6 +1407,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), Loading @@ -1340,6 +1427,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), Loading Loading @@ -1379,12 +1470,10 @@ 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; const char *region_name; char *text = NULL; struct cs_dsp_buf *buf; unsigned int reg; int regions = 0; Loading @@ -1395,10 +1484,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; } Loading @@ -1415,8 +1502,7 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, goto out_fw; } cs_dsp_info(dsp, "Firmware version: %d\n", header->ver); dsp->fw_ver = header->ver; dsp->wmfw_ver = header->ver; if (header->core != dsp->type) { cs_dsp_err(dsp, "%s: invalid core %d != %d\n", Loading @@ -1426,33 +1512,47 @@ 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, cs_dsp_info(dsp, "%s: format %d timestamp %#llx\n", file, header->ver, 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; offset = le32_to_cpu(region->offset) & 0xffffff; type = be32_to_cpu(region->type) & 0xff; switch (type) { case WMFW_INFO_TEXT: case WMFW_NAME_TEXT: region_name = "Firmware name"; text = kzalloc(le32_to_cpu(region->len) + 1, GFP_KERNEL); region_name = "Info/Name"; cs_dsp_info(dsp, "%s: %.*s\n", file, min(le32_to_cpu(region->len), 100), region->data); break; case WMFW_ALGORITHM_DATA: region_name = "Algorithm"; Loading @@ -1460,11 +1560,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, if (ret != 0) goto out_fw; break; case WMFW_INFO_TEXT: region_name = "Information"; text = kzalloc(le32_to_cpu(region->len) + 1, GFP_KERNEL); break; case WMFW_ABSOLUTE: region_name = "Absolute"; reg = offset; Loading Loading @@ -1498,23 +1593,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); kfree(text); text = NULL; } if (reg) { buf = cs_dsp_buf_alloc(region->data, le32_to_cpu(region->len), Loading Loading @@ -1556,7 +1634,9 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, out_fw: 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; } Loading Loading @@ -1702,7 +1782,7 @@ static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp, list_add_tail(&alg_region->list, &dsp->alg_regions); if (dsp->fw_ver > 0) if (dsp->wmfw_ver > 0) cs_dsp_ctl_fixup_base(dsp, alg_region); return alg_region; Loading Loading @@ -1825,7 +1905,7 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp) ret = PTR_ERR(alg_region); goto out; } if (dsp->fw_ver == 0) { if (dsp->wmfw_ver == 0) { if (i + 1 < n_algs) { len = be32_to_cpu(adsp1_alg[i + 1].dm); len -= be32_to_cpu(adsp1_alg[i].dm); Loading @@ -1847,7 +1927,7 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp) ret = PTR_ERR(alg_region); goto out; } if (dsp->fw_ver == 0) { if (dsp->wmfw_ver == 0) { if (i + 1 < n_algs) { len = be32_to_cpu(adsp1_alg[i + 1].zm); len -= be32_to_cpu(adsp1_alg[i].zm); Loading Loading @@ -1938,7 +2018,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp) ret = PTR_ERR(alg_region); goto out; } if (dsp->fw_ver == 0) { if (dsp->wmfw_ver == 0) { if (i + 1 < n_algs) { len = be32_to_cpu(adsp2_alg[i + 1].xm); len -= be32_to_cpu(adsp2_alg[i].xm); Loading @@ -1960,7 +2040,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp) ret = PTR_ERR(alg_region); goto out; } if (dsp->fw_ver == 0) { if (dsp->wmfw_ver == 0) { if (i + 1 < n_algs) { len = be32_to_cpu(adsp2_alg[i + 1].ym); len -= be32_to_cpu(adsp2_alg[i].ym); Loading @@ -1982,7 +2062,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp) ret = PTR_ERR(alg_region); goto out; } if (dsp->fw_ver == 0) { if (dsp->wmfw_ver == 0) { if (i + 1 < n_algs) { len = be32_to_cpu(adsp2_alg[i + 1].zm); len -= be32_to_cpu(adsp2_alg[i].zm); Loading Loading @@ -2086,7 +2166,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware struct cs_dsp_alg_region *alg_region; const char *region_name; int ret, pos, blocks, type, offset, reg, version; char *text = NULL; struct cs_dsp_buf *buf; if (!firmware) Loading Loading @@ -2125,10 +2204,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; Loading @@ -2145,7 +2234,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware region_name = "Unknown"; switch (type) { case (WMFW_NAME_TEXT << 8): text = kzalloc(le32_to_cpu(blk->len) + 1, GFP_KERNEL); cs_dsp_info(dsp, "%s: %.*s\n", dsp->fw_name, min(le32_to_cpu(blk->len), 100), blk->data); break; case (WMFW_INFO_TEXT << 8): case (WMFW_METADATA << 8): Loading Loading @@ -2217,25 +2307,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware break; } if (text) { memcpy(text, blk->data, le32_to_cpu(blk->len)); cs_dsp_info(dsp, "%s: %s\n", dsp->fw_name, text); kfree(text); text = NULL; } 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); Loading Loading @@ -2274,7 +2346,10 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware out_fw: 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; } Loading Loading @@ -2337,8 +2412,8 @@ EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_init, FW_CS_DSP); * Return: Zero for success, a negative number on error. */ int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, const struct firmware *wmfw_firmware, char *wmfw_filename, const struct firmware *coeff_firmware, char *coeff_filename, const struct firmware *wmfw_firmware, const char *wmfw_filename, const struct firmware *coeff_firmware, const char *coeff_filename, const char *fw_name) { unsigned int val; Loading Loading @@ -2631,8 +2706,8 @@ static void cs_dsp_halo_stop_watchdog(struct cs_dsp *dsp) * Return: Zero for success, a negative number on error. */ int cs_dsp_power_up(struct cs_dsp *dsp, const struct firmware *wmfw_firmware, char *wmfw_filename, const struct firmware *coeff_firmware, char *coeff_filename, const struct firmware *wmfw_firmware, const char *wmfw_filename, const struct firmware *coeff_firmware, const char *coeff_filename, const char *fw_name) { int ret; Loading
include/linux/firmware/cirrus/cs_dsp.h +5 −5 Original line number Diff line number Diff line Loading @@ -167,7 +167,7 @@ struct cs_dsp { const struct cs_dsp_region *mem; int num_mems; int fw_ver; int wmfw_ver; bool booted; bool running; Loading Loading @@ -213,13 +213,13 @@ int cs_dsp_adsp2_init(struct cs_dsp *dsp); int cs_dsp_halo_init(struct cs_dsp *dsp); int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, const struct firmware *wmfw_firmware, char *wmfw_filename, const struct firmware *coeff_firmware, char *coeff_filename, const struct firmware *wmfw_firmware, const char *wmfw_filename, const struct firmware *coeff_firmware, const char *coeff_filename, const char *fw_name); void cs_dsp_adsp1_power_down(struct cs_dsp *dsp); int cs_dsp_power_up(struct cs_dsp *dsp, const struct firmware *wmfw_firmware, char *wmfw_filename, const struct firmware *coeff_firmware, char *coeff_filename, const struct firmware *wmfw_firmware, const char *wmfw_filename, const struct firmware *coeff_firmware, const char *coeff_filename, const char *fw_name); void cs_dsp_power_down(struct cs_dsp *dsp); int cs_dsp_run(struct cs_dsp *dsp); Loading
sound/soc/amd/yc/acp6x-mach.c +7 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA"), } }, { .driver_data = &acp6x_card, .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "M5602RA"), } }, { .driver_data = &acp6x_card, .matches = { Loading
sound/soc/codecs/rt5645.c +18 −6 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ static const struct reg_sequence init_list[] = { static const struct reg_sequence rt5650_init_list[] = { {0xf6, 0x0100}, {RT5645_PWR_ANLG1, 0x02}, {RT5645_IL_CMD3, 0x0018}, {RT5645_IL_CMD3, 0x6728}, }; static const struct reg_default rt5645_reg[] = { Loading Loading @@ -3130,20 +3130,32 @@ static void rt5645_enable_push_button_irq(struct snd_soc_component *component, bool enable) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); int ret; if (enable) { snd_soc_dapm_force_enable_pin(dapm, "ADC L power"); snd_soc_dapm_force_enable_pin(dapm, "ADC R power"); snd_soc_dapm_sync(dapm); snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, RT5645_EN_4BTN_IL_MASK | RT5645_RST_4BTN_IL_MASK, RT5645_EN_4BTN_IL_EN | RT5645_RST_4BTN_IL_RST); usleep_range(10000, 15000); snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, RT5645_EN_4BTN_IL_MASK | RT5645_RST_4BTN_IL_MASK, RT5645_EN_4BTN_IL_EN | RT5645_RST_4BTN_IL_NORM); msleep(50); ret = snd_soc_component_read(component, RT5645_INT_IRQ_ST); pr_debug("%s read %x = %x\n", __func__, RT5645_INT_IRQ_ST, snd_soc_component_read(component, RT5645_INT_IRQ_ST)); snd_soc_component_write(component, RT5645_INT_IRQ_ST, ret); ret = snd_soc_component_read(component, RT5650_4BTN_IL_CMD1); pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1, snd_soc_component_read(component, RT5650_4BTN_IL_CMD1)); snd_soc_component_write(component, RT5650_4BTN_IL_CMD1, ret); snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD1, 0x3, 0x3); snd_soc_component_update_bits(component, RT5645_INT_IRQ_ST, 0x8, 0x8); snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 0x8000, 0x8000); snd_soc_component_read(component, RT5650_4BTN_IL_CMD1); pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1, snd_soc_component_read(component, RT5650_4BTN_IL_CMD1)); } else { snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 0x8000, 0x0); snd_soc_component_update_bits(component, RT5645_INT_IRQ_ST, 0x8, 0x0); Loading
sound/soc/codecs/rt5645.h +6 −0 Original line number Diff line number Diff line Loading @@ -2011,6 +2011,12 @@ #define RT5645_ZCD_HP_DIS (0x0 << 15) #define RT5645_ZCD_HP_EN (0x1 << 15) /* Buttons Inline Command Function 2 (0xe0) */ #define RT5645_EN_4BTN_IL_MASK (0x1 << 15) #define RT5645_EN_4BTN_IL_EN (0x1 << 15) #define RT5645_RST_4BTN_IL_MASK (0x1 << 14) #define RT5645_RST_4BTN_IL_RST (0x0 << 14) #define RT5645_RST_4BTN_IL_NORM (0x1 << 14) /* Codec Private Register definition */ /* DAC ADC Digital Volume (0x00) */ Loading