• Home
  • Raw
  • Download

Lines Matching +full:spk +full:- +full:shutdown

1 // SPDX-License-Identifier: GPL-2.0-only
3 * wm_adsp.c -- Wolfson ADSP support
36 dev_crit(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
38 dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
40 dev_warn(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
42 dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
44 dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
47 adsp_err(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
50 adsp_dbg(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
88 #define ADSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
89 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
90 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
323 buf->buf = vmalloc(len); in wm_adsp_buf_alloc()
324 if (!buf->buf) { in wm_adsp_buf_alloc()
328 memcpy(buf->buf, src, len); in wm_adsp_buf_alloc()
331 list_add_tail(&buf->list, list); in wm_adsp_buf_alloc()
342 list_del(&buf->list); in wm_adsp_buf_free()
343 vfree(buf->buf); in wm_adsp_buf_free()
424 __be32 irq_count; /* bits 1-31 count IRQ assertions */
572 [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" },
575 [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" },
577 [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" },
592 [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
593 [WM_ADSP_FW_SPK_CALI] = { .file = "spk-cali" },
594 [WM_ADSP_FW_SPK_DIAG] = { .file = "spk-diag" },
654 kfree(dsp->wmfw_file_name); in wm_adsp_debugfs_save_wmfwname()
655 dsp->wmfw_file_name = tmp; in wm_adsp_debugfs_save_wmfwname()
662 kfree(dsp->bin_file_name); in wm_adsp_debugfs_save_binname()
663 dsp->bin_file_name = tmp; in wm_adsp_debugfs_save_binname()
668 kfree(dsp->wmfw_file_name); in wm_adsp_debugfs_clear()
669 kfree(dsp->bin_file_name); in wm_adsp_debugfs_clear()
670 dsp->wmfw_file_name = NULL; in wm_adsp_debugfs_clear()
671 dsp->bin_file_name = NULL; in wm_adsp_debugfs_clear()
678 struct wm_adsp *dsp = file->private_data; in wm_adsp_debugfs_wmfw_read()
681 mutex_lock(&dsp->pwr_lock); in wm_adsp_debugfs_wmfw_read()
683 if (!dsp->wmfw_file_name || !dsp->booted) in wm_adsp_debugfs_wmfw_read()
687 dsp->wmfw_file_name, in wm_adsp_debugfs_wmfw_read()
688 strlen(dsp->wmfw_file_name)); in wm_adsp_debugfs_wmfw_read()
690 mutex_unlock(&dsp->pwr_lock); in wm_adsp_debugfs_wmfw_read()
698 struct wm_adsp *dsp = file->private_data; in wm_adsp_debugfs_bin_read()
701 mutex_lock(&dsp->pwr_lock); in wm_adsp_debugfs_bin_read()
703 if (!dsp->bin_file_name || !dsp->booted) in wm_adsp_debugfs_bin_read()
707 dsp->bin_file_name, in wm_adsp_debugfs_bin_read()
708 strlen(dsp->bin_file_name)); in wm_adsp_debugfs_bin_read()
710 mutex_unlock(&dsp->pwr_lock); in wm_adsp_debugfs_bin_read()
740 root = debugfs_create_dir(dsp->name, component->debugfs_root); in wm_adsp2_init_debugfs()
742 debugfs_create_bool("booted", 0444, root, &dsp->booted); in wm_adsp2_init_debugfs()
743 debugfs_create_bool("running", 0444, root, &dsp->running); in wm_adsp2_init_debugfs()
744 debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id); in wm_adsp2_init_debugfs()
745 debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version); in wm_adsp2_init_debugfs()
751 dsp->debugfs_root = root; in wm_adsp2_init_debugfs()
757 debugfs_remove_recursive(dsp->debugfs_root); in wm_adsp2_cleanup_debugfs()
788 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; in wm_adsp_fw_get()
791 ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw; in wm_adsp_fw_get()
801 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; in wm_adsp_fw_put()
805 if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw) in wm_adsp_fw_put()
808 if (ucontrol->value.enumerated.item[0] >= WM_ADSP_NUM_FW) in wm_adsp_fw_put()
809 return -EINVAL; in wm_adsp_fw_put()
811 mutex_lock(&dsp[e->shift_l].pwr_lock); in wm_adsp_fw_put()
813 if (dsp[e->shift_l].booted || !list_empty(&dsp[e->shift_l].compr_list)) in wm_adsp_fw_put()
814 ret = -EBUSY; in wm_adsp_fw_put()
816 dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0]; in wm_adsp_fw_put()
818 mutex_unlock(&dsp[e->shift_l].pwr_lock); in wm_adsp_fw_put()
840 for (i = 0; i < dsp->num_mems; i++) in wm_adsp_find_region()
841 if (dsp->mem[i].type == type) in wm_adsp_find_region()
842 return &dsp->mem[i]; in wm_adsp_find_region()
850 switch (mem->type) { in wm_adsp_region_to_reg()
852 return mem->base + (offset * 3); in wm_adsp_region_to_reg()
857 return mem->base + (offset * 2); in wm_adsp_region_to_reg()
867 switch (mem->type) { in wm_halo_region_to_reg()
870 return mem->base + (offset * 4); in wm_halo_region_to_reg()
873 return (mem->base + (offset * 3)) & ~0x3; in wm_halo_region_to_reg()
875 return mem->base + (offset * 5); in wm_halo_region_to_reg()
889 ret = regmap_read(dsp->regmap, dsp->base + offs[i], &offs[i]); in wm_adsp_read_fw_status()
939 const struct wm_adsp_alg_region *alg_region = &ctl->alg_region; in wm_coeff_base_reg()
940 struct wm_adsp *dsp = ctl->dsp; in wm_coeff_base_reg()
943 mem = wm_adsp_find_region(dsp, alg_region->type); in wm_coeff_base_reg()
946 alg_region->type); in wm_coeff_base_reg()
947 return -EINVAL; in wm_coeff_base_reg()
950 *reg = dsp->ops->region_to_reg(mem, ctl->alg_region.base + ctl->offset); in wm_coeff_base_reg()
959 (struct soc_bytes_ext *)kctl->private_value; in wm_coeff_info()
962 switch (ctl->type) { in wm_coeff_info()
964 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in wm_coeff_info()
965 uinfo->value.integer.min = WM_ADSP_ACKED_CTL_MIN_VALUE; in wm_coeff_info()
966 uinfo->value.integer.max = WM_ADSP_ACKED_CTL_MAX_VALUE; in wm_coeff_info()
967 uinfo->value.integer.step = 1; in wm_coeff_info()
968 uinfo->count = 1; in wm_coeff_info()
971 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; in wm_coeff_info()
972 uinfo->count = ctl->len; in wm_coeff_info()
982 struct wm_adsp *dsp = ctl->dsp; in wm_coeff_write_acked_control()
992 event_id, ctl->alg_region.alg, in wm_coeff_write_acked_control()
993 wm_adsp_mem_region_name(ctl->alg_region.type), ctl->offset); in wm_coeff_write_acked_control()
995 ret = regmap_raw_write(dsp->regmap, reg, &val, sizeof(val)); in wm_coeff_write_acked_control()
1009 case 0 ... WM_ADSP_ACKED_CTL_N_QUICKPOLLS - 1: in wm_coeff_write_acked_control()
1019 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); in wm_coeff_write_acked_control()
1032 reg, ctl->alg_region.alg, in wm_coeff_write_acked_control()
1033 wm_adsp_mem_region_name(ctl->alg_region.type), in wm_coeff_write_acked_control()
1034 ctl->offset); in wm_coeff_write_acked_control()
1036 return -ETIMEDOUT; in wm_coeff_write_acked_control()
1042 struct wm_adsp *dsp = ctl->dsp; in wm_coeff_write_ctrl_raw()
1053 return -ENOMEM; in wm_coeff_write_ctrl_raw()
1055 ret = regmap_raw_write(dsp->regmap, reg, scratch, in wm_coeff_write_ctrl_raw()
1075 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) in wm_coeff_write_ctrl()
1076 ret = -EPERM; in wm_coeff_write_ctrl()
1077 else if (buf != ctl->cache) in wm_coeff_write_ctrl()
1078 memcpy(ctl->cache, buf, len); in wm_coeff_write_ctrl()
1080 ctl->set = 1; in wm_coeff_write_ctrl()
1081 if (ctl->enabled && ctl->dsp->running) in wm_coeff_write_ctrl()
1091 (struct soc_bytes_ext *)kctl->private_value; in wm_coeff_put()
1093 char *p = ucontrol->value.bytes.data; in wm_coeff_put()
1096 mutex_lock(&ctl->dsp->pwr_lock); in wm_coeff_put()
1097 ret = wm_coeff_write_ctrl(ctl, p, ctl->len); in wm_coeff_put()
1098 mutex_unlock(&ctl->dsp->pwr_lock); in wm_coeff_put()
1107 (struct soc_bytes_ext *)kctl->private_value; in wm_coeff_tlv_put()
1111 mutex_lock(&ctl->dsp->pwr_lock); in wm_coeff_tlv_put()
1113 if (copy_from_user(ctl->cache, bytes, size)) in wm_coeff_tlv_put()
1114 ret = -EFAULT; in wm_coeff_tlv_put()
1116 ret = wm_coeff_write_ctrl(ctl, ctl->cache, size); in wm_coeff_tlv_put()
1118 mutex_unlock(&ctl->dsp->pwr_lock); in wm_coeff_tlv_put()
1127 (struct soc_bytes_ext *)kctl->private_value; in wm_coeff_put_acked()
1129 unsigned int val = ucontrol->value.integer.value[0]; in wm_coeff_put_acked()
1135 mutex_lock(&ctl->dsp->pwr_lock); in wm_coeff_put_acked()
1137 if (ctl->enabled && ctl->dsp->running) in wm_coeff_put_acked()
1140 ret = -EPERM; in wm_coeff_put_acked()
1142 mutex_unlock(&ctl->dsp->pwr_lock); in wm_coeff_put_acked()
1150 struct wm_adsp *dsp = ctl->dsp; in wm_coeff_read_ctrl_raw()
1161 return -ENOMEM; in wm_coeff_read_ctrl_raw()
1163 ret = regmap_raw_read(dsp->regmap, reg, scratch, len); in wm_coeff_read_ctrl_raw()
1182 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { in wm_coeff_read_ctrl()
1183 if (ctl->enabled && ctl->dsp->running) in wm_coeff_read_ctrl()
1186 return -EPERM; in wm_coeff_read_ctrl()
1188 if (!ctl->flags && ctl->enabled && ctl->dsp->running) in wm_coeff_read_ctrl()
1189 ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len); in wm_coeff_read_ctrl()
1191 if (buf != ctl->cache) in wm_coeff_read_ctrl()
1192 memcpy(buf, ctl->cache, len); in wm_coeff_read_ctrl()
1202 (struct soc_bytes_ext *)kctl->private_value; in wm_coeff_get()
1204 char *p = ucontrol->value.bytes.data; in wm_coeff_get()
1207 mutex_lock(&ctl->dsp->pwr_lock); in wm_coeff_get()
1208 ret = wm_coeff_read_ctrl(ctl, p, ctl->len); in wm_coeff_get()
1209 mutex_unlock(&ctl->dsp->pwr_lock); in wm_coeff_get()
1218 (struct soc_bytes_ext *)kctl->private_value; in wm_coeff_tlv_get()
1222 mutex_lock(&ctl->dsp->pwr_lock); in wm_coeff_tlv_get()
1224 ret = wm_coeff_read_ctrl(ctl, ctl->cache, size); in wm_coeff_tlv_get()
1226 if (!ret && copy_to_user(bytes, ctl->cache, size)) in wm_coeff_tlv_get()
1227 ret = -EFAULT; in wm_coeff_tlv_get()
1229 mutex_unlock(&ctl->dsp->pwr_lock); in wm_coeff_tlv_get()
1239 * user-side assumptions that all controls are readable and that a in wm_coeff_get_acked()
1244 ucontrol->value.integer.value[0] = 0; in wm_coeff_get_acked()
1291 if (!ctl || !ctl->name) in wmfw_add_ctl()
1292 return -EINVAL; in wmfw_add_ctl()
1296 return -ENOMEM; in wmfw_add_ctl()
1298 kcontrol->name = ctl->name; in wmfw_add_ctl()
1299 kcontrol->info = wm_coeff_info; in wmfw_add_ctl()
1300 kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER; in wmfw_add_ctl()
1301 kcontrol->tlv.c = snd_soc_bytes_tlv_callback; in wmfw_add_ctl()
1302 kcontrol->private_value = (unsigned long)&ctl->bytes_ext; in wmfw_add_ctl()
1303 kcontrol->access = wmfw_convert_flags(ctl->flags, ctl->len); in wmfw_add_ctl()
1305 switch (ctl->type) { in wmfw_add_ctl()
1307 kcontrol->get = wm_coeff_get_acked; in wmfw_add_ctl()
1308 kcontrol->put = wm_coeff_put_acked; in wmfw_add_ctl()
1311 if (kcontrol->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { in wmfw_add_ctl()
1312 ctl->bytes_ext.max = ctl->len; in wmfw_add_ctl()
1313 ctl->bytes_ext.get = wm_coeff_tlv_get; in wmfw_add_ctl()
1314 ctl->bytes_ext.put = wm_coeff_tlv_put; in wmfw_add_ctl()
1316 kcontrol->get = wm_coeff_get; in wmfw_add_ctl()
1317 kcontrol->put = wm_coeff_put; in wmfw_add_ctl()
1322 ret = snd_soc_add_component_controls(dsp->component, kcontrol, 1); in wmfw_add_ctl()
1340 list_for_each_entry(ctl, &dsp->ctl_list, list) { in wm_coeff_init_control_caches()
1341 if (!ctl->enabled || ctl->set) in wm_coeff_init_control_caches()
1343 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) in wm_coeff_init_control_caches()
1348 * For non-readable controls the cache was zero-filled when in wm_coeff_init_control_caches()
1351 if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) { in wm_coeff_init_control_caches()
1352 ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len); in wm_coeff_init_control_caches()
1366 list_for_each_entry(ctl, &dsp->ctl_list, list) { in wm_coeff_sync_controls()
1367 if (!ctl->enabled) in wm_coeff_sync_controls()
1369 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) { in wm_coeff_sync_controls()
1370 ret = wm_coeff_write_ctrl_raw(ctl, ctl->cache, in wm_coeff_sync_controls()
1371 ctl->len); in wm_coeff_sync_controls()
1386 list_for_each_entry(ctl, &dsp->ctl_list, list) { in wm_adsp_signal_event_controls()
1387 if (ctl->type != WMFW_CTL_TYPE_HOSTEVENT) in wm_adsp_signal_event_controls()
1390 if (!ctl->enabled) in wm_adsp_signal_event_controls()
1397 event, ctl->alg_region.alg, ret); in wm_adsp_signal_event_controls()
1407 wmfw_add_ctl(ctl_work->dsp, ctl_work->ctl); in wm_adsp_ctl_work()
1413 kfree(ctl->cache); in wm_adsp_free_ctl_blk()
1414 kfree(ctl->name); in wm_adsp_free_ctl_blk()
1415 kfree(ctl->subname); in wm_adsp_free_ctl_blk()
1431 region_name = wm_adsp_mem_region_name(alg_region->type); in wm_adsp_create_control()
1433 adsp_err(dsp, "Unknown region type: %d\n", alg_region->type); in wm_adsp_create_control()
1434 return -EINVAL; in wm_adsp_create_control()
1437 switch (dsp->fw_ver) { in wm_adsp_create_control()
1441 dsp->name, region_name, alg_region->alg); in wm_adsp_create_control()
1446 "%s%c %.12s %x", dsp->name, *region_name, in wm_adsp_create_control()
1447 wm_adsp_fw_text[dsp->fw], alg_region->alg); in wm_adsp_create_control()
1451 "%s %.12s %x", dsp->name, in wm_adsp_create_control()
1452 wm_adsp_fw_text[dsp->fw], alg_region->alg); in wm_adsp_create_control()
1457 int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2; in wm_adsp_create_control()
1460 if (dsp->component->name_prefix) in wm_adsp_create_control()
1461 avail -= strlen(dsp->component->name_prefix) + 1; in wm_adsp_create_control()
1465 skip = subname_len - avail; in wm_adsp_create_control()
1467 snprintf(name + ret, SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret, in wm_adsp_create_control()
1468 " %.*s", subname_len - skip, subname + skip); in wm_adsp_create_control()
1471 list_for_each_entry(ctl, &dsp->ctl_list, list) { in wm_adsp_create_control()
1472 if (!strcmp(ctl->name, name)) { in wm_adsp_create_control()
1473 if (!ctl->enabled) in wm_adsp_create_control()
1474 ctl->enabled = 1; in wm_adsp_create_control()
1481 return -ENOMEM; in wm_adsp_create_control()
1482 ctl->fw_name = wm_adsp_fw_text[dsp->fw]; in wm_adsp_create_control()
1483 ctl->alg_region = *alg_region; in wm_adsp_create_control()
1484 ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL); in wm_adsp_create_control()
1485 if (!ctl->name) { in wm_adsp_create_control()
1486 ret = -ENOMEM; in wm_adsp_create_control()
1490 ctl->subname_len = subname_len; in wm_adsp_create_control()
1491 ctl->subname = kmemdup(subname, in wm_adsp_create_control()
1493 if (!ctl->subname) { in wm_adsp_create_control()
1494 ret = -ENOMEM; in wm_adsp_create_control()
1498 ctl->enabled = 1; in wm_adsp_create_control()
1499 ctl->set = 0; in wm_adsp_create_control()
1500 ctl->ops.xget = wm_coeff_get; in wm_adsp_create_control()
1501 ctl->ops.xput = wm_coeff_put; in wm_adsp_create_control()
1502 ctl->dsp = dsp; in wm_adsp_create_control()
1504 ctl->flags = flags; in wm_adsp_create_control()
1505 ctl->type = type; in wm_adsp_create_control()
1506 ctl->offset = offset; in wm_adsp_create_control()
1507 ctl->len = len; in wm_adsp_create_control()
1508 ctl->cache = kzalloc(ctl->len, GFP_KERNEL); in wm_adsp_create_control()
1509 if (!ctl->cache) { in wm_adsp_create_control()
1510 ret = -ENOMEM; in wm_adsp_create_control()
1514 list_add(&ctl->list, &dsp->ctl_list); in wm_adsp_create_control()
1521 ret = -ENOMEM; in wm_adsp_create_control()
1525 ctl_work->dsp = dsp; in wm_adsp_create_control()
1526 ctl_work->ctl = ctl; in wm_adsp_create_control()
1527 INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); in wm_adsp_create_control()
1528 schedule_work(&ctl_work->work); in wm_adsp_create_control()
1533 list_del(&ctl->list); in wm_adsp_create_control()
1534 kfree(ctl->cache); in wm_adsp_create_control()
1536 kfree(ctl->subname); in wm_adsp_create_control()
1538 kfree(ctl->name); in wm_adsp_create_control()
1610 switch (dsp->fw_ver) { in wm_coeff_parse_alg()
1614 *data = raw->data; in wm_coeff_parse_alg()
1616 blk->id = le32_to_cpu(raw->id); in wm_coeff_parse_alg()
1617 blk->name = raw->name; in wm_coeff_parse_alg()
1618 blk->name_len = strlen(raw->name); in wm_coeff_parse_alg()
1619 blk->ncoeff = le32_to_cpu(raw->ncoeff); in wm_coeff_parse_alg()
1622 blk->id = wm_coeff_parse_int(sizeof(raw->id), data); in wm_coeff_parse_alg()
1623 blk->name_len = wm_coeff_parse_string(sizeof(u8), data, in wm_coeff_parse_alg()
1624 &blk->name); in wm_coeff_parse_alg()
1626 blk->ncoeff = wm_coeff_parse_int(sizeof(raw->ncoeff), data); in wm_coeff_parse_alg()
1630 adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id); in wm_coeff_parse_alg()
1631 adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name); in wm_coeff_parse_alg()
1632 adsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff); in wm_coeff_parse_alg()
1642 switch (dsp->fw_ver) { in wm_coeff_parse_coeff()
1646 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size); in wm_coeff_parse_coeff()
1648 blk->offset = le16_to_cpu(raw->hdr.offset); in wm_coeff_parse_coeff()
1649 blk->mem_type = le16_to_cpu(raw->hdr.type); in wm_coeff_parse_coeff()
1650 blk->name = raw->name; in wm_coeff_parse_coeff()
1651 blk->name_len = strlen(raw->name); in wm_coeff_parse_coeff()
1652 blk->ctl_type = le16_to_cpu(raw->ctl_type); in wm_coeff_parse_coeff()
1653 blk->flags = le16_to_cpu(raw->flags); in wm_coeff_parse_coeff()
1654 blk->len = le32_to_cpu(raw->len); in wm_coeff_parse_coeff()
1658 blk->offset = wm_coeff_parse_int(sizeof(raw->hdr.offset), &tmp); in wm_coeff_parse_coeff()
1659 blk->mem_type = wm_coeff_parse_int(sizeof(raw->hdr.type), &tmp); in wm_coeff_parse_coeff()
1660 length = wm_coeff_parse_int(sizeof(raw->hdr.size), &tmp); in wm_coeff_parse_coeff()
1661 blk->name_len = wm_coeff_parse_string(sizeof(u8), &tmp, in wm_coeff_parse_coeff()
1662 &blk->name); in wm_coeff_parse_coeff()
1665 blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp); in wm_coeff_parse_coeff()
1666 blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp); in wm_coeff_parse_coeff()
1667 blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp); in wm_coeff_parse_coeff()
1669 *data = *data + sizeof(raw->hdr) + length; in wm_coeff_parse_coeff()
1673 adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type); in wm_coeff_parse_coeff()
1674 adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset); in wm_coeff_parse_coeff()
1675 adsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name); in wm_coeff_parse_coeff()
1676 adsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags); in wm_coeff_parse_coeff()
1677 adsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type); in wm_coeff_parse_coeff()
1678 adsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len); in wm_coeff_parse_coeff()
1686 if ((coeff_blk->flags & f_illegal) || in wm_adsp_check_coeff_flags()
1687 ((coeff_blk->flags & f_required) != f_required)) { in wm_adsp_check_coeff_flags()
1689 coeff_blk->flags, coeff_blk->ctl_type); in wm_adsp_check_coeff_flags()
1690 return -EINVAL; in wm_adsp_check_coeff_flags()
1702 const u8 *data = region->data; in wm_adsp_parse_coeff()
1722 return -EINVAL; in wm_adsp_parse_coeff()
1732 return -EINVAL; in wm_adsp_parse_coeff()
1741 return -EINVAL; in wm_adsp_parse_coeff()
1746 return -EINVAL; in wm_adsp_parse_coeff()
1774 adsp1_sizes = (void *)&firmware->data[pos]; in wm_adsp1_parse_sizes()
1777 le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm), in wm_adsp1_parse_sizes()
1778 le32_to_cpu(adsp1_sizes->zm)); in wm_adsp1_parse_sizes()
1790 adsp2_sizes = (void *)&firmware->data[pos]; in wm_adsp2_parse_sizes()
1793 le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym), in wm_adsp2_parse_sizes()
1794 le32_to_cpu(adsp2_sizes->pm), le32_to_cpu(adsp2_sizes->zm)); in wm_adsp2_parse_sizes()
1827 struct regmap *regmap = dsp->regmap; in wm_adsp_load()
1843 return -ENOMEM; in wm_adsp_load()
1845 snprintf(file, PAGE_SIZE, "%s-%s-%s.wmfw", dsp->part, dsp->fwf_name, in wm_adsp_load()
1846 wm_adsp_fw[dsp->fw].file); in wm_adsp_load()
1847 file[PAGE_SIZE - 1] = '\0'; in wm_adsp_load()
1849 ret = request_firmware(&firmware, file, dsp->dev); in wm_adsp_load()
1854 ret = -EINVAL; in wm_adsp_load()
1857 if (pos >= firmware->size) { in wm_adsp_load()
1859 file, firmware->size); in wm_adsp_load()
1863 header = (void *)&firmware->data[0]; in wm_adsp_load()
1865 if (memcmp(&header->magic[0], "WMFW", 4) != 0) { in wm_adsp_load()
1870 if (!dsp->ops->validate_version(dsp, header->ver)) { in wm_adsp_load()
1872 file, header->ver); in wm_adsp_load()
1876 adsp_info(dsp, "Firmware version: %d\n", header->ver); in wm_adsp_load()
1877 dsp->fw_ver = header->ver; in wm_adsp_load()
1879 if (header->core != dsp->type) { in wm_adsp_load()
1881 file, header->core, dsp->type); in wm_adsp_load()
1886 pos = dsp->ops->parse_sizes(dsp, file, pos, firmware); in wm_adsp_load()
1888 footer = (void *)&firmware->data[pos]; in wm_adsp_load()
1891 if (le32_to_cpu(header->len) != pos) { in wm_adsp_load()
1893 file, le32_to_cpu(header->len)); in wm_adsp_load()
1898 le64_to_cpu(footer->timestamp)); in wm_adsp_load()
1900 while (pos < firmware->size && in wm_adsp_load()
1901 sizeof(*region) < firmware->size - pos) { in wm_adsp_load()
1902 region = (void *)&(firmware->data[pos]); in wm_adsp_load()
1906 offset = le32_to_cpu(region->offset) & 0xffffff; in wm_adsp_load()
1907 type = be32_to_cpu(region->type) & 0xff; in wm_adsp_load()
1912 text = kzalloc(le32_to_cpu(region->len) + 1, in wm_adsp_load()
1923 text = kzalloc(le32_to_cpu(region->len) + 1, in wm_adsp_load()
1941 ret = -EINVAL; in wm_adsp_load()
1946 reg = dsp->ops->region_to_reg(mem, offset); in wm_adsp_load()
1956 regions, le32_to_cpu(region->len), offset, in wm_adsp_load()
1959 if (le32_to_cpu(region->len) > in wm_adsp_load()
1960 firmware->size - pos - sizeof(*region)) { in wm_adsp_load()
1964 le32_to_cpu(region->len), firmware->size); in wm_adsp_load()
1965 ret = -EINVAL; in wm_adsp_load()
1970 memcpy(text, region->data, le32_to_cpu(region->len)); in wm_adsp_load()
1977 buf = wm_adsp_buf_alloc(region->data, in wm_adsp_load()
1978 le32_to_cpu(region->len), in wm_adsp_load()
1982 ret = -ENOMEM; in wm_adsp_load()
1986 ret = regmap_raw_write_async(regmap, reg, buf->buf, in wm_adsp_load()
1987 le32_to_cpu(region->len)); in wm_adsp_load()
1992 le32_to_cpu(region->len), offset, in wm_adsp_load()
1998 pos += le32_to_cpu(region->len) + sizeof(*region); in wm_adsp_load()
2008 if (pos > firmware->size) in wm_adsp_load()
2010 file, regions, pos - firmware->size); in wm_adsp_load()
2034 const char *fw_txt = wm_adsp_fw_text[dsp->fw]; in wm_adsp_get_ctl()
2036 list_for_each_entry(pos, &dsp->ctl_list, list) { in wm_adsp_get_ctl()
2037 if (!pos->subname) in wm_adsp_get_ctl()
2039 if (strncmp(pos->subname, name, pos->subname_len) == 0 && in wm_adsp_get_ctl()
2040 strncmp(pos->fw_name, fw_txt, in wm_adsp_get_ctl()
2042 pos->alg_region.alg == alg && in wm_adsp_get_ctl()
2043 pos->alg_region.type == type) { in wm_adsp_get_ctl()
2062 return -EINVAL; in wm_adsp_write_ctl()
2064 if (len > ctl->len) in wm_adsp_write_ctl()
2065 return -EINVAL; in wm_adsp_write_ctl()
2071 if (ctl->flags & WMFW_CTL_FLAG_SYS) in wm_adsp_write_ctl()
2074 if (dsp->component->name_prefix) in wm_adsp_write_ctl()
2076 dsp->component->name_prefix, ctl->name); in wm_adsp_write_ctl()
2079 ctl->name); in wm_adsp_write_ctl()
2081 kcontrol = snd_soc_card_get_kcontrol(dsp->component->card, ctl_name); in wm_adsp_write_ctl()
2084 return -EINVAL; in wm_adsp_write_ctl()
2087 snd_ctl_notify(dsp->component->card->snd_card, in wm_adsp_write_ctl()
2088 SNDRV_CTL_EVENT_MASK_VALUE, &kcontrol->id); in wm_adsp_write_ctl()
2101 return -EINVAL; in wm_adsp_read_ctl()
2103 if (len > ctl->len) in wm_adsp_read_ctl()
2104 return -EINVAL; in wm_adsp_read_ctl()
2115 list_for_each_entry(ctl, &dsp->ctl_list, list) { in wm_adsp_ctl_fixup_base()
2116 if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] && in wm_adsp_ctl_fixup_base()
2117 alg_region->alg == ctl->alg_region.alg && in wm_adsp_ctl_fixup_base()
2118 alg_region->type == ctl->alg_region.type) { in wm_adsp_ctl_fixup_base()
2119 ctl->alg_region.base = alg_region->base; in wm_adsp_ctl_fixup_base()
2135 return ERR_PTR(-EINVAL); in wm_adsp_read_algs()
2140 return ERR_PTR(-EINVAL); in wm_adsp_read_algs()
2144 reg = dsp->ops->region_to_reg(mem, pos + len); in wm_adsp_read_algs()
2146 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); in wm_adsp_read_algs()
2162 return ERR_PTR(-ENOMEM); in wm_adsp_read_algs()
2164 reg = dsp->ops->region_to_reg(mem, pos); in wm_adsp_read_algs()
2166 ret = regmap_raw_read(dsp->regmap, reg, alg, len); in wm_adsp_read_algs()
2181 list_for_each_entry(alg_region, &dsp->alg_regions, list) { in wm_adsp_find_alg_region()
2182 if (id == alg_region->alg && type == alg_region->type) in wm_adsp_find_alg_region()
2197 return ERR_PTR(-ENOMEM); in wm_adsp_create_region()
2199 alg_region->type = type; in wm_adsp_create_region()
2200 alg_region->alg = be32_to_cpu(id); in wm_adsp_create_region()
2201 alg_region->base = be32_to_cpu(base); in wm_adsp_create_region()
2203 list_add_tail(&alg_region->list, &dsp->alg_regions); in wm_adsp_create_region()
2205 if (dsp->fw_ver > 0) in wm_adsp_create_region()
2215 while (!list_empty(&dsp->alg_regions)) { in wm_adsp_free_alg_regions()
2216 alg_region = list_first_entry(&dsp->alg_regions, in wm_adsp_free_alg_regions()
2219 list_del(&alg_region->list); in wm_adsp_free_alg_regions()
2227 dsp->fw_id = be32_to_cpu(fw->id); in wmfw_parse_id_header()
2228 dsp->fw_id_version = be32_to_cpu(fw->ver); in wmfw_parse_id_header()
2231 dsp->fw_id, (dsp->fw_id_version & 0xff0000) >> 16, in wmfw_parse_id_header()
2232 (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff, in wmfw_parse_id_header()
2239 dsp->fw_id = be32_to_cpu(fw->id); in wmfw_v3_parse_id_header()
2240 dsp->fw_id_version = be32_to_cpu(fw->ver); in wmfw_v3_parse_id_header()
2241 dsp->fw_vendor_id = be32_to_cpu(fw->vendor_id); in wmfw_v3_parse_id_header()
2244 dsp->fw_id, dsp->fw_vendor_id, in wmfw_v3_parse_id_header()
2245 (dsp->fw_id_version & 0xff0000) >> 16, in wmfw_v3_parse_id_header()
2246 (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff, in wmfw_v3_parse_id_header()
2277 return -EINVAL; in wm_adsp1_setup_algs()
2279 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id, in wm_adsp1_setup_algs()
2325 if (dsp->fw_ver == 0) { in wm_adsp1_setup_algs()
2328 len -= be32_to_cpu(adsp1_alg[i].dm); in wm_adsp1_setup_algs()
2346 if (dsp->fw_ver == 0) { in wm_adsp1_setup_algs()
2349 len -= be32_to_cpu(adsp1_alg[i].zm); in wm_adsp1_setup_algs()
2378 return -EINVAL; in wm_adsp2_setup_algs()
2380 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id, in wm_adsp2_setup_algs()
2433 if (dsp->fw_ver == 0) { in wm_adsp2_setup_algs()
2436 len -= be32_to_cpu(adsp2_alg[i].xm); in wm_adsp2_setup_algs()
2454 if (dsp->fw_ver == 0) { in wm_adsp2_setup_algs()
2457 len -= be32_to_cpu(adsp2_alg[i].ym); in wm_adsp2_setup_algs()
2475 if (dsp->fw_ver == 0) { in wm_adsp2_setup_algs()
2478 len -= be32_to_cpu(adsp2_alg[i].zm); in wm_adsp2_setup_algs()
2518 return -EINVAL; in wm_halo_setup_algs()
2520 ret = regmap_raw_read(dsp->regmap, mem->base, &halo_id, in wm_halo_setup_algs()
2570 struct regmap *regmap = dsp->regmap; in wm_adsp_load_coeff()
2583 return -ENOMEM; in wm_adsp_load_coeff()
2585 snprintf(file, PAGE_SIZE, "%s-%s-%s.bin", dsp->part, dsp->fwf_name, in wm_adsp_load_coeff()
2586 wm_adsp_fw[dsp->fw].file); in wm_adsp_load_coeff()
2587 file[PAGE_SIZE - 1] = '\0'; in wm_adsp_load_coeff()
2589 ret = request_firmware(&firmware, file, dsp->dev); in wm_adsp_load_coeff()
2595 ret = -EINVAL; in wm_adsp_load_coeff()
2597 if (sizeof(*hdr) >= firmware->size) { in wm_adsp_load_coeff()
2599 file, firmware->size); in wm_adsp_load_coeff()
2603 hdr = (void *)&firmware->data[0]; in wm_adsp_load_coeff()
2604 if (memcmp(hdr->magic, "WMDR", 4) != 0) { in wm_adsp_load_coeff()
2609 switch (be32_to_cpu(hdr->rev) & 0xff) { in wm_adsp_load_coeff()
2614 file, be32_to_cpu(hdr->rev) & 0xff); in wm_adsp_load_coeff()
2615 ret = -EINVAL; in wm_adsp_load_coeff()
2620 (le32_to_cpu(hdr->ver) >> 16) & 0xff, in wm_adsp_load_coeff()
2621 (le32_to_cpu(hdr->ver) >> 8) & 0xff, in wm_adsp_load_coeff()
2622 le32_to_cpu(hdr->ver) & 0xff); in wm_adsp_load_coeff()
2624 pos = le32_to_cpu(hdr->len); in wm_adsp_load_coeff()
2627 while (pos < firmware->size && in wm_adsp_load_coeff()
2628 sizeof(*blk) < firmware->size - pos) { in wm_adsp_load_coeff()
2629 blk = (void *)(&firmware->data[pos]); in wm_adsp_load_coeff()
2631 type = le16_to_cpu(blk->type); in wm_adsp_load_coeff()
2632 offset = le16_to_cpu(blk->offset); in wm_adsp_load_coeff()
2635 file, blocks, le32_to_cpu(blk->id), in wm_adsp_load_coeff()
2636 (le32_to_cpu(blk->ver) >> 16) & 0xff, in wm_adsp_load_coeff()
2637 (le32_to_cpu(blk->ver) >> 8) & 0xff, in wm_adsp_load_coeff()
2638 le32_to_cpu(blk->ver) & 0xff); in wm_adsp_load_coeff()
2640 file, blocks, le32_to_cpu(blk->len), offset, type); in wm_adsp_load_coeff()
2654 if (le32_to_cpu(blk->id) == dsp->fw_id && in wm_adsp_load_coeff()
2662 reg = dsp->ops->region_to_reg(mem, 0); in wm_adsp_load_coeff()
2678 file, blocks, le32_to_cpu(blk->len), in wm_adsp_load_coeff()
2679 type, le32_to_cpu(blk->id)); in wm_adsp_load_coeff()
2688 le32_to_cpu(blk->id)); in wm_adsp_load_coeff()
2690 reg = alg_region->base; in wm_adsp_load_coeff()
2691 reg = dsp->ops->region_to_reg(mem, reg); in wm_adsp_load_coeff()
2695 type, le32_to_cpu(blk->id)); in wm_adsp_load_coeff()
2706 if (le32_to_cpu(blk->len) > in wm_adsp_load_coeff()
2707 firmware->size - pos - sizeof(*blk)) { in wm_adsp_load_coeff()
2711 le32_to_cpu(blk->len), in wm_adsp_load_coeff()
2712 firmware->size); in wm_adsp_load_coeff()
2713 ret = -EINVAL; in wm_adsp_load_coeff()
2717 buf = wm_adsp_buf_alloc(blk->data, in wm_adsp_load_coeff()
2718 le32_to_cpu(blk->len), in wm_adsp_load_coeff()
2722 ret = -ENOMEM; in wm_adsp_load_coeff()
2727 file, blocks, le32_to_cpu(blk->len), in wm_adsp_load_coeff()
2729 ret = regmap_raw_write_async(regmap, reg, buf->buf, in wm_adsp_load_coeff()
2730 le32_to_cpu(blk->len)); in wm_adsp_load_coeff()
2738 pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03; in wm_adsp_load_coeff()
2746 if (pos > firmware->size) in wm_adsp_load_coeff()
2748 file, blocks, pos - firmware->size); in wm_adsp_load_coeff()
2765 if (!dsp->name) { in wm_adsp_create_name()
2766 dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d", in wm_adsp_create_name()
2767 dsp->num); in wm_adsp_create_name()
2768 if (!dsp->name) in wm_adsp_create_name()
2769 return -ENOMEM; in wm_adsp_create_name()
2772 if (!dsp->fwf_name) { in wm_adsp_create_name()
2773 p = devm_kstrdup(dsp->dev, dsp->name, GFP_KERNEL); in wm_adsp_create_name()
2775 return -ENOMEM; in wm_adsp_create_name()
2777 dsp->fwf_name = p; in wm_adsp_create_name()
2793 INIT_LIST_HEAD(&dsp->alg_regions); in wm_adsp_common_init()
2794 INIT_LIST_HEAD(&dsp->ctl_list); in wm_adsp_common_init()
2795 INIT_LIST_HEAD(&dsp->compr_list); in wm_adsp_common_init()
2796 INIT_LIST_HEAD(&dsp->buffer_list); in wm_adsp_common_init()
2798 mutex_init(&dsp->pwr_lock); in wm_adsp_common_init()
2805 dsp->ops = &wm_adsp1_ops; in wm_adsp1_init()
2815 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); in wm_adsp1_event()
2817 struct wm_adsp *dsp = &dsps[w->shift]; in wm_adsp1_event()
2822 dsp->component = component; in wm_adsp1_event()
2824 mutex_lock(&dsp->pwr_lock); in wm_adsp1_event()
2828 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, in wm_adsp1_event()
2835 if (dsp->sysclk_reg) { in wm_adsp1_event()
2836 ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val); in wm_adsp1_event()
2843 val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift; in wm_adsp1_event()
2845 ret = regmap_update_bits(dsp->regmap, in wm_adsp1_event()
2846 dsp->base + ADSP1_CONTROL_31, in wm_adsp1_event()
2877 dsp->booted = true; in wm_adsp1_event()
2880 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, in wm_adsp1_event()
2884 dsp->running = true; in wm_adsp1_event()
2888 dsp->running = false; in wm_adsp1_event()
2889 dsp->booted = false; in wm_adsp1_event()
2892 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, in wm_adsp1_event()
2895 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19, in wm_adsp1_event()
2898 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, in wm_adsp1_event()
2901 list_for_each_entry(ctl, &dsp->ctl_list, list) in wm_adsp1_event()
2902 ctl->enabled = 0; in wm_adsp1_event()
2912 mutex_unlock(&dsp->pwr_lock); in wm_adsp1_event()
2917 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, in wm_adsp1_event()
2920 mutex_unlock(&dsp->pwr_lock); in wm_adsp1_event()
2933 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val); in wm_adsp2v2_enable_core()
2945 return -EBUSY; in wm_adsp2v2_enable_core()
2957 ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL, in wm_adsp2_enable_core()
2967 struct regmap *regmap = dsp->regmap; in wm_adsp2_lock()
2974 lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0; in wm_adsp2_lock()
2997 return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in wm_adsp2_enable_memory()
3003 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in wm_adsp2_disable_memory()
3009 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); in wm_adsp2_disable_core()
3010 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0); in wm_adsp2_disable_core()
3011 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0); in wm_adsp2_disable_core()
3013 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in wm_adsp2_disable_core()
3019 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); in wm_adsp2v2_disable_core()
3020 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0); in wm_adsp2v2_disable_core()
3021 regmap_write(dsp->regmap, dsp->base + ADSP2V2_WDMA_CONFIG_2, 0); in wm_adsp2v2_disable_core()
3031 mutex_lock(&dsp->pwr_lock); in wm_adsp_boot_work()
3033 if (dsp->ops->enable_memory) { in wm_adsp_boot_work()
3034 ret = dsp->ops->enable_memory(dsp); in wm_adsp_boot_work()
3039 if (dsp->ops->enable_core) { in wm_adsp_boot_work()
3040 ret = dsp->ops->enable_core(dsp); in wm_adsp_boot_work()
3049 ret = dsp->ops->setup_algs(dsp); in wm_adsp_boot_work()
3062 if (dsp->ops->disable_core) in wm_adsp_boot_work()
3063 dsp->ops->disable_core(dsp); in wm_adsp_boot_work()
3065 dsp->booted = true; in wm_adsp_boot_work()
3067 mutex_unlock(&dsp->pwr_lock); in wm_adsp_boot_work()
3072 if (dsp->ops->disable_core) in wm_adsp_boot_work()
3073 dsp->ops->disable_core(dsp); in wm_adsp_boot_work()
3075 if (dsp->ops->disable_memory) in wm_adsp_boot_work()
3076 dsp->ops->disable_memory(dsp); in wm_adsp_boot_work()
3078 mutex_unlock(&dsp->pwr_lock); in wm_adsp_boot_work()
3084 { dsp->base + HALO_MPU_LOCK_CONFIG, 0x5555 }, in wm_halo_configure_mpu()
3085 { dsp->base + HALO_MPU_LOCK_CONFIG, 0xAAAA }, in wm_halo_configure_mpu()
3086 { dsp->base + HALO_MPU_XMEM_ACCESS_0, 0xFFFFFFFF }, in wm_halo_configure_mpu()
3087 { dsp->base + HALO_MPU_YMEM_ACCESS_0, 0xFFFFFFFF }, in wm_halo_configure_mpu()
3088 { dsp->base + HALO_MPU_WINDOW_ACCESS_0, lock_regions }, in wm_halo_configure_mpu()
3089 { dsp->base + HALO_MPU_XREG_ACCESS_0, lock_regions }, in wm_halo_configure_mpu()
3090 { dsp->base + HALO_MPU_YREG_ACCESS_0, lock_regions }, in wm_halo_configure_mpu()
3091 { dsp->base + HALO_MPU_XMEM_ACCESS_1, 0xFFFFFFFF }, in wm_halo_configure_mpu()
3092 { dsp->base + HALO_MPU_YMEM_ACCESS_1, 0xFFFFFFFF }, in wm_halo_configure_mpu()
3093 { dsp->base + HALO_MPU_WINDOW_ACCESS_1, lock_regions }, in wm_halo_configure_mpu()
3094 { dsp->base + HALO_MPU_XREG_ACCESS_1, lock_regions }, in wm_halo_configure_mpu()
3095 { dsp->base + HALO_MPU_YREG_ACCESS_1, lock_regions }, in wm_halo_configure_mpu()
3096 { dsp->base + HALO_MPU_XMEM_ACCESS_2, 0xFFFFFFFF }, in wm_halo_configure_mpu()
3097 { dsp->base + HALO_MPU_YMEM_ACCESS_2, 0xFFFFFFFF }, in wm_halo_configure_mpu()
3098 { dsp->base + HALO_MPU_WINDOW_ACCESS_2, lock_regions }, in wm_halo_configure_mpu()
3099 { dsp->base + HALO_MPU_XREG_ACCESS_2, lock_regions }, in wm_halo_configure_mpu()
3100 { dsp->base + HALO_MPU_YREG_ACCESS_2, lock_regions }, in wm_halo_configure_mpu()
3101 { dsp->base + HALO_MPU_XMEM_ACCESS_3, 0xFFFFFFFF }, in wm_halo_configure_mpu()
3102 { dsp->base + HALO_MPU_YMEM_ACCESS_3, 0xFFFFFFFF }, in wm_halo_configure_mpu()
3103 { dsp->base + HALO_MPU_WINDOW_ACCESS_3, lock_regions }, in wm_halo_configure_mpu()
3104 { dsp->base + HALO_MPU_XREG_ACCESS_3, lock_regions }, in wm_halo_configure_mpu()
3105 { dsp->base + HALO_MPU_YREG_ACCESS_3, lock_regions }, in wm_halo_configure_mpu()
3106 { dsp->base + HALO_MPU_LOCK_CONFIG, 0 }, in wm_halo_configure_mpu()
3109 return regmap_multi_reg_write(dsp->regmap, config, ARRAY_SIZE(config)); in wm_halo_configure_mpu()
3114 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); in wm_adsp2_set_dspclk()
3116 struct wm_adsp *dsp = &dsps[w->shift]; in wm_adsp2_set_dspclk()
3119 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CLOCKING, in wm_adsp2_set_dspclk()
3135 (struct soc_mixer_control *)kcontrol->private_value; in wm_adsp2_preloader_get()
3136 struct wm_adsp *dsp = &dsps[mc->shift - 1]; in wm_adsp2_preloader_get()
3138 ucontrol->value.integer.value[0] = dsp->preloaded; in wm_adsp2_preloader_get()
3151 (struct soc_mixer_control *)kcontrol->private_value; in wm_adsp2_preloader_put()
3152 struct wm_adsp *dsp = &dsps[mc->shift - 1]; in wm_adsp2_preloader_put()
3155 snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name); in wm_adsp2_preloader_put()
3157 dsp->preloaded = ucontrol->value.integer.value[0]; in wm_adsp2_preloader_put()
3159 if (ucontrol->value.integer.value[0]) in wm_adsp2_preloader_put()
3166 flush_work(&dsp->boot_work); in wm_adsp2_preloader_put()
3174 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG, in wm_adsp_stop_watchdog()
3180 regmap_update_bits(dsp->regmap, dsp->base + HALO_WDT_CONTROL, in wm_halo_stop_watchdog()
3187 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); in wm_adsp_early_event()
3189 struct wm_adsp *dsp = &dsps[w->shift]; in wm_adsp_early_event()
3194 queue_work(system_unbound_wq, &dsp->boot_work); in wm_adsp_early_event()
3197 mutex_lock(&dsp->pwr_lock); in wm_adsp_early_event()
3201 dsp->fw_id = 0; in wm_adsp_early_event()
3202 dsp->fw_id_version = 0; in wm_adsp_early_event()
3204 dsp->booted = false; in wm_adsp_early_event()
3206 if (dsp->ops->disable_memory) in wm_adsp_early_event()
3207 dsp->ops->disable_memory(dsp); in wm_adsp_early_event()
3209 list_for_each_entry(ctl, &dsp->ctl_list, list) in wm_adsp_early_event()
3210 ctl->enabled = 0; in wm_adsp_early_event()
3214 mutex_unlock(&dsp->pwr_lock); in wm_adsp_early_event()
3216 adsp_dbg(dsp, "Shutdown complete\n"); in wm_adsp_early_event()
3228 return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in wm_adsp2_start_core()
3235 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in wm_adsp2_stop_core()
3242 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); in wm_adsp_event()
3244 struct wm_adsp *dsp = &dsps[w->shift]; in wm_adsp_event()
3249 flush_work(&dsp->boot_work); in wm_adsp_event()
3251 mutex_lock(&dsp->pwr_lock); in wm_adsp_event()
3253 if (!dsp->booted) { in wm_adsp_event()
3254 ret = -EIO; in wm_adsp_event()
3258 if (dsp->ops->enable_core) { in wm_adsp_event()
3259 ret = dsp->ops->enable_core(dsp); in wm_adsp_event()
3269 if (dsp->ops->lock_memory) { in wm_adsp_event()
3270 ret = dsp->ops->lock_memory(dsp, dsp->lock_regions); in wm_adsp_event()
3278 if (dsp->ops->start_core) { in wm_adsp_event()
3279 ret = dsp->ops->start_core(dsp); in wm_adsp_event()
3284 if (wm_adsp_fw[dsp->fw].num_caps != 0) { in wm_adsp_event()
3290 dsp->running = true; in wm_adsp_event()
3292 mutex_unlock(&dsp->pwr_lock); in wm_adsp_event()
3299 if (dsp->ops->stop_watchdog) in wm_adsp_event()
3300 dsp->ops->stop_watchdog(dsp); in wm_adsp_event()
3303 if (dsp->ops->show_fw_status) in wm_adsp_event()
3304 dsp->ops->show_fw_status(dsp); in wm_adsp_event()
3306 mutex_lock(&dsp->pwr_lock); in wm_adsp_event()
3308 dsp->running = false; in wm_adsp_event()
3310 if (dsp->ops->stop_core) in wm_adsp_event()
3311 dsp->ops->stop_core(dsp); in wm_adsp_event()
3312 if (dsp->ops->disable_core) in wm_adsp_event()
3313 dsp->ops->disable_core(dsp); in wm_adsp_event()
3315 if (wm_adsp_fw[dsp->fw].num_caps != 0) in wm_adsp_event()
3318 dsp->fatal_error = false; in wm_adsp_event()
3320 mutex_unlock(&dsp->pwr_lock); in wm_adsp_event()
3331 if (dsp->ops->stop_core) in wm_adsp_event()
3332 dsp->ops->stop_core(dsp); in wm_adsp_event()
3333 if (dsp->ops->disable_core) in wm_adsp_event()
3334 dsp->ops->disable_core(dsp); in wm_adsp_event()
3335 mutex_unlock(&dsp->pwr_lock); in wm_adsp_event()
3342 return regmap_update_bits(dsp->regmap, in wm_halo_start_core()
3343 dsp->base + HALO_CCM_CORE_CONTROL, in wm_halo_start_core()
3349 regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL, in wm_halo_stop_core()
3353 regmap_update_bits(dsp->regmap, dsp->base + HALO_CORE_SOFT_RESET, in wm_halo_stop_core()
3361 snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name); in wm_adsp2_component_probe()
3366 dsp->component = component; in wm_adsp2_component_probe()
3388 switch (dsp->rev) { in wm_adsp2_init()
3394 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in wm_adsp2_init()
3402 dsp->ops = &wm_adsp2_ops[0]; in wm_adsp2_init()
3405 dsp->ops = &wm_adsp2_ops[1]; in wm_adsp2_init()
3408 dsp->ops = &wm_adsp2_ops[2]; in wm_adsp2_init()
3412 INIT_WORK(&dsp->boot_work, wm_adsp_boot_work); in wm_adsp2_init()
3426 dsp->ops = &wm_halo_ops; in wm_halo_init()
3428 INIT_WORK(&dsp->boot_work, wm_adsp_boot_work); in wm_halo_init()
3438 while (!list_empty(&dsp->ctl_list)) { in wm_adsp2_remove()
3439 ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl, in wm_adsp2_remove()
3441 list_del(&ctl->list); in wm_adsp2_remove()
3449 return compr->buf != NULL; in wm_adsp_compr_attached()
3456 if (compr->dsp->fatal_error) in wm_adsp_compr_attach()
3457 return -EINVAL; in wm_adsp_compr_attach()
3459 list_for_each_entry(tmp, &compr->dsp->buffer_list, list) { in wm_adsp_compr_attach()
3460 if (!tmp->name || !strcmp(compr->name, tmp->name)) { in wm_adsp_compr_attach()
3467 return -EINVAL; in wm_adsp_compr_attach()
3469 compr->buf = buf; in wm_adsp_compr_attach()
3470 buf->compr = compr; in wm_adsp_compr_attach()
3481 if (compr->stream) in wm_adsp_compr_detach()
3482 snd_compr_fragment_elapsed(compr->stream); in wm_adsp_compr_detach()
3485 compr->buf->compr = NULL; in wm_adsp_compr_detach()
3486 compr->buf = NULL; in wm_adsp_compr_detach()
3493 struct snd_soc_pcm_runtime *rtd = stream->private_data; in wm_adsp_compr_open()
3496 mutex_lock(&dsp->pwr_lock); in wm_adsp_compr_open()
3498 if (wm_adsp_fw[dsp->fw].num_caps == 0) { in wm_adsp_compr_open()
3500 asoc_rtd_to_codec(rtd, 0)->name); in wm_adsp_compr_open()
3501 ret = -ENXIO; in wm_adsp_compr_open()
3505 if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) { in wm_adsp_compr_open()
3507 asoc_rtd_to_codec(rtd, 0)->name); in wm_adsp_compr_open()
3508 ret = -EINVAL; in wm_adsp_compr_open()
3512 list_for_each_entry(tmp, &dsp->compr_list, list) { in wm_adsp_compr_open()
3513 if (!strcmp(tmp->name, asoc_rtd_to_codec(rtd, 0)->name)) { in wm_adsp_compr_open()
3515 asoc_rtd_to_codec(rtd, 0)->name); in wm_adsp_compr_open()
3516 ret = -EBUSY; in wm_adsp_compr_open()
3523 ret = -ENOMEM; in wm_adsp_compr_open()
3527 compr->dsp = dsp; in wm_adsp_compr_open()
3528 compr->stream = stream; in wm_adsp_compr_open()
3529 compr->name = asoc_rtd_to_codec(rtd, 0)->name; in wm_adsp_compr_open()
3531 list_add_tail(&compr->list, &dsp->compr_list); in wm_adsp_compr_open()
3533 stream->runtime->private_data = compr; in wm_adsp_compr_open()
3536 mutex_unlock(&dsp->pwr_lock); in wm_adsp_compr_open()
3545 struct wm_adsp_compr *compr = stream->runtime->private_data; in wm_adsp_compr_free()
3546 struct wm_adsp *dsp = compr->dsp; in wm_adsp_compr_free()
3548 mutex_lock(&dsp->pwr_lock); in wm_adsp_compr_free()
3551 list_del(&compr->list); in wm_adsp_compr_free()
3553 kfree(compr->raw_buf); in wm_adsp_compr_free()
3556 mutex_unlock(&dsp->pwr_lock); in wm_adsp_compr_free()
3565 struct wm_adsp_compr *compr = stream->runtime->private_data; in wm_adsp_compr_check_params()
3566 struct wm_adsp *dsp = compr->dsp; in wm_adsp_compr_check_params()
3571 if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE || in wm_adsp_compr_check_params()
3572 params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE || in wm_adsp_compr_check_params()
3573 params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS || in wm_adsp_compr_check_params()
3574 params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS || in wm_adsp_compr_check_params()
3575 params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) { in wm_adsp_compr_check_params()
3577 params->buffer.fragment_size, in wm_adsp_compr_check_params()
3578 params->buffer.fragments); in wm_adsp_compr_check_params()
3580 return -EINVAL; in wm_adsp_compr_check_params()
3583 for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) { in wm_adsp_compr_check_params()
3584 caps = &wm_adsp_fw[dsp->fw].caps[i]; in wm_adsp_compr_check_params()
3585 desc = &caps->desc; in wm_adsp_compr_check_params()
3587 if (caps->id != params->codec.id) in wm_adsp_compr_check_params()
3590 if (stream->direction == SND_COMPRESS_PLAYBACK) { in wm_adsp_compr_check_params()
3591 if (desc->max_ch < params->codec.ch_out) in wm_adsp_compr_check_params()
3594 if (desc->max_ch < params->codec.ch_in) in wm_adsp_compr_check_params()
3598 if (!(desc->formats & (1 << params->codec.format))) in wm_adsp_compr_check_params()
3601 for (j = 0; j < desc->num_sample_rates; ++j) in wm_adsp_compr_check_params()
3602 if (desc->sample_rates[j] == params->codec.sample_rate) in wm_adsp_compr_check_params()
3607 params->codec.id, params->codec.ch_in, params->codec.ch_out, in wm_adsp_compr_check_params()
3608 params->codec.sample_rate, params->codec.format); in wm_adsp_compr_check_params()
3609 return -EINVAL; in wm_adsp_compr_check_params()
3614 return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE; in wm_adsp_compr_frag_words()
3621 struct wm_adsp_compr *compr = stream->runtime->private_data; in wm_adsp_compr_set_params()
3629 compr->size = params->buffer; in wm_adsp_compr_set_params()
3632 compr->size.fragment_size, compr->size.fragments); in wm_adsp_compr_set_params()
3634 size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf); in wm_adsp_compr_set_params()
3635 compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL); in wm_adsp_compr_set_params()
3636 if (!compr->raw_buf) in wm_adsp_compr_set_params()
3637 return -ENOMEM; in wm_adsp_compr_set_params()
3639 compr->sample_rate = params->codec.sample_rate; in wm_adsp_compr_set_params()
3649 struct wm_adsp_compr *compr = stream->runtime->private_data; in wm_adsp_compr_get_caps()
3650 int fw = compr->dsp->fw; in wm_adsp_compr_get_caps()
3655 caps->codecs[i] = wm_adsp_fw[fw].caps[i].id; in wm_adsp_compr_get_caps()
3657 caps->num_codecs = i; in wm_adsp_compr_get_caps()
3658 caps->direction = wm_adsp_fw[fw].compr_direction; in wm_adsp_compr_get_caps()
3660 caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE; in wm_adsp_compr_get_caps()
3661 caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE; in wm_adsp_compr_get_caps()
3662 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS; in wm_adsp_compr_get_caps()
3663 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS; in wm_adsp_compr_get_caps()
3679 return -EINVAL; in wm_adsp_read_data_block()
3681 reg = dsp->ops->region_to_reg(mem, mem_addr); in wm_adsp_read_data_block()
3683 ret = regmap_raw_read(dsp->regmap, reg, data, in wm_adsp_read_data_block()
3707 return -EINVAL; in wm_adsp_write_data_word()
3709 reg = dsp->ops->region_to_reg(mem, mem_addr); in wm_adsp_write_data_word()
3713 return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data)); in wm_adsp_write_data_word()
3719 return wm_adsp_read_data_word(buf->dsp, buf->host_buf_mem_type, in wm_adsp_buffer_read()
3720 buf->host_buf_ptr + field_offset, data); in wm_adsp_buffer_read()
3726 return wm_adsp_write_data_word(buf->dsp, buf->host_buf_mem_type, in wm_adsp_buffer_write()
3727 buf->host_buf_ptr + field_offset, data); in wm_adsp_buffer_write()
3741 pack_in += sizeof(*buf) - data_word_size; in wm_adsp_remove_padding()
3747 const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps; in wm_adsp_buffer_populate()
3752 buf->regions = kcalloc(caps->num_regions, sizeof(*buf->regions), in wm_adsp_buffer_populate()
3754 if (!buf->regions) in wm_adsp_buffer_populate()
3755 return -ENOMEM; in wm_adsp_buffer_populate()
3757 for (i = 0; i < caps->num_regions; ++i) { in wm_adsp_buffer_populate()
3758 region = &buf->regions[i]; in wm_adsp_buffer_populate()
3760 region->offset = offset; in wm_adsp_buffer_populate()
3761 region->mem_type = caps->region_defs[i].mem_type; in wm_adsp_buffer_populate()
3763 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset, in wm_adsp_buffer_populate()
3764 &region->base_addr); in wm_adsp_buffer_populate()
3768 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset, in wm_adsp_buffer_populate()
3773 region->cumulative_size = offset; in wm_adsp_buffer_populate()
3777 i, region->mem_type, region->base_addr, in wm_adsp_buffer_populate()
3778 region->offset, region->cumulative_size); in wm_adsp_buffer_populate()
3786 buf->irq_count = 0xFFFFFFFF; in wm_adsp_buffer_clear()
3787 buf->read_index = -1; in wm_adsp_buffer_clear()
3788 buf->avail = 0; in wm_adsp_buffer_clear()
3799 buf->dsp = dsp; in wm_adsp_buffer_alloc()
3803 list_add_tail(&buf->list, &dsp->buffer_list); in wm_adsp_buffer_alloc()
3815 alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id); in wm_adsp_buffer_parse_legacy()
3818 return -EINVAL; in wm_adsp_buffer_parse_legacy()
3823 return -ENOMEM; in wm_adsp_buffer_parse_legacy()
3825 xmalg = dsp->ops->sys_config_size / sizeof(__be32); in wm_adsp_buffer_parse_legacy()
3827 addr = alg_region->base + xmalg + ALG_XM_FIELD(magic); in wm_adsp_buffer_parse_legacy()
3833 return -ENODEV; in wm_adsp_buffer_parse_legacy()
3835 addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr); in wm_adsp_buffer_parse_legacy()
3838 &buf->host_buf_ptr); in wm_adsp_buffer_parse_legacy()
3842 if (buf->host_buf_ptr) in wm_adsp_buffer_parse_legacy()
3848 if (!buf->host_buf_ptr) in wm_adsp_buffer_parse_legacy()
3849 return -EIO; in wm_adsp_buffer_parse_legacy()
3851 buf->host_buf_mem_type = WMFW_ADSP2_XM; in wm_adsp_buffer_parse_legacy()
3857 compr_dbg(buf, "legacy host_buf_ptr=%x\n", buf->host_buf_ptr); in wm_adsp_buffer_parse_legacy()
3874 ret = regmap_raw_read(ctl->dsp->regmap, reg, &val, sizeof(val)); in wm_adsp_buffer_parse_coeff()
3885 adsp_err(ctl->dsp, "Failed to acquire host buffer\n"); in wm_adsp_buffer_parse_coeff()
3886 return -EIO; in wm_adsp_buffer_parse_coeff()
3889 buf = wm_adsp_buffer_alloc(ctl->dsp); in wm_adsp_buffer_parse_coeff()
3891 return -ENOMEM; in wm_adsp_buffer_parse_coeff()
3893 buf->host_buf_mem_type = ctl->alg_region.type; in wm_adsp_buffer_parse_coeff()
3894 buf->host_buf_ptr = be32_to_cpu(val); in wm_adsp_buffer_parse_coeff()
3904 if (ctl->len == 4) { in wm_adsp_buffer_parse_coeff()
3905 compr_dbg(buf, "host_buf_ptr=%x\n", buf->host_buf_ptr); in wm_adsp_buffer_parse_coeff()
3909 ret = regmap_raw_read(ctl->dsp->regmap, reg, &coeff_v1, in wm_adsp_buffer_parse_coeff()
3919 adsp_err(ctl->dsp, in wm_adsp_buffer_parse_coeff()
3922 return -EINVAL; in wm_adsp_buffer_parse_coeff()
3932 buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", ctl->dsp->part, in wm_adsp_buffer_parse_coeff()
3936 buf->host_buf_ptr, val); in wm_adsp_buffer_parse_coeff()
3946 list_for_each_entry(ctl, &dsp->ctl_list, list) { in wm_adsp_buffer_init()
3947 if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER) in wm_adsp_buffer_init()
3950 if (!ctl->enabled) in wm_adsp_buffer_init()
3963 if (list_empty(&dsp->buffer_list)) { in wm_adsp_buffer_init()
3983 list_for_each_entry_safe(buf, tmp, &dsp->buffer_list, list) { in wm_adsp_buffer_free()
3984 wm_adsp_compr_detach(buf->compr); in wm_adsp_buffer_free()
3986 kfree(buf->name); in wm_adsp_buffer_free()
3987 kfree(buf->regions); in wm_adsp_buffer_free()
3988 list_del(&buf->list); in wm_adsp_buffer_free()
3999 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error); in wm_adsp_buffer_get_error()
4004 if (buf->error != 0) { in wm_adsp_buffer_get_error()
4005 compr_err(buf, "Buffer error occurred: %d\n", buf->error); in wm_adsp_buffer_get_error()
4006 return -EIO; in wm_adsp_buffer_get_error()
4015 struct wm_adsp_compr *compr = stream->runtime->private_data; in wm_adsp_compr_trigger()
4016 struct wm_adsp *dsp = compr->dsp; in wm_adsp_compr_trigger()
4021 mutex_lock(&dsp->pwr_lock); in wm_adsp_compr_trigger()
4034 ret = wm_adsp_buffer_get_error(compr->buf); in wm_adsp_compr_trigger()
4039 ret = wm_adsp_buffer_write(compr->buf, in wm_adsp_compr_trigger()
4050 wm_adsp_buffer_clear(compr->buf); in wm_adsp_compr_trigger()
4053 ret = -EINVAL; in wm_adsp_compr_trigger()
4057 mutex_unlock(&dsp->pwr_lock); in wm_adsp_compr_trigger()
4065 int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1; in wm_adsp_buffer_size()
4067 return buf->regions[last_region].cumulative_size; in wm_adsp_buffer_size()
4077 if (buf->read_index < 0) { in wm_adsp_buffer_update_avail()
4091 buf->read_index = read_index; in wm_adsp_buffer_update_avail()
4101 avail = write_index - buf->read_index; in wm_adsp_buffer_update_avail()
4106 buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE); in wm_adsp_buffer_update_avail()
4108 buf->avail = avail; in wm_adsp_buffer_update_avail()
4119 mutex_lock(&dsp->pwr_lock); in wm_adsp_compr_handle_irq()
4121 if (list_empty(&dsp->buffer_list)) { in wm_adsp_compr_handle_irq()
4122 ret = -ENODEV; in wm_adsp_compr_handle_irq()
4128 list_for_each_entry(buf, &dsp->buffer_list, list) { in wm_adsp_compr_handle_irq()
4129 compr = buf->compr; in wm_adsp_compr_handle_irq()
4136 &buf->irq_count); in wm_adsp_compr_handle_irq()
4148 if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2) in wm_adsp_compr_handle_irq()
4152 if (compr && compr->stream) in wm_adsp_compr_handle_irq()
4153 snd_compr_fragment_elapsed(compr->stream); in wm_adsp_compr_handle_irq()
4157 mutex_unlock(&dsp->pwr_lock); in wm_adsp_compr_handle_irq()
4165 if (buf->irq_count & 0x01) in wm_adsp_buffer_reenable_irq()
4168 compr_dbg(buf, "Enable IRQ(0x%x) for next fragment\n", buf->irq_count); in wm_adsp_buffer_reenable_irq()
4170 buf->irq_count |= 0x01; in wm_adsp_buffer_reenable_irq()
4173 buf->irq_count); in wm_adsp_buffer_reenable_irq()
4180 struct wm_adsp_compr *compr = stream->runtime->private_data; in wm_adsp_compr_pointer()
4181 struct wm_adsp *dsp = compr->dsp; in wm_adsp_compr_pointer()
4187 mutex_lock(&dsp->pwr_lock); in wm_adsp_compr_pointer()
4189 buf = compr->buf; in wm_adsp_compr_pointer()
4191 if (dsp->fatal_error || !buf || buf->error) { in wm_adsp_compr_pointer()
4193 ret = -EIO; in wm_adsp_compr_pointer()
4197 if (buf->avail < wm_adsp_compr_frag_words(compr)) { in wm_adsp_compr_pointer()
4208 if (buf->avail < wm_adsp_compr_frag_words(compr)) { in wm_adsp_compr_pointer()
4211 if (buf->error) in wm_adsp_compr_pointer()
4219 compr_err(compr, "Failed to re-enable buffer IRQ: %d\n", in wm_adsp_compr_pointer()
4226 tstamp->copied_total = compr->copied_total; in wm_adsp_compr_pointer()
4227 tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE; in wm_adsp_compr_pointer()
4228 tstamp->sampling_rate = compr->sample_rate; in wm_adsp_compr_pointer()
4231 mutex_unlock(&dsp->pwr_lock); in wm_adsp_compr_pointer()
4239 struct wm_adsp_compr_buf *buf = compr->buf; in wm_adsp_buffer_capture_block()
4245 for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i) in wm_adsp_buffer_capture_block()
4246 if (buf->read_index < buf->regions[i].cumulative_size) in wm_adsp_buffer_capture_block()
4249 if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions) in wm_adsp_buffer_capture_block()
4250 return -EINVAL; in wm_adsp_buffer_capture_block()
4252 mem_type = buf->regions[i].mem_type; in wm_adsp_buffer_capture_block()
4253 adsp_addr = buf->regions[i].base_addr + in wm_adsp_buffer_capture_block()
4254 (buf->read_index - buf->regions[i].offset); in wm_adsp_buffer_capture_block()
4257 nwords = buf->regions[i].cumulative_size - buf->read_index; in wm_adsp_buffer_capture_block()
4261 if (nwords > buf->avail) in wm_adsp_buffer_capture_block()
4262 nwords = buf->avail; in wm_adsp_buffer_capture_block()
4269 ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr, in wm_adsp_buffer_capture_block()
4270 nwords, compr->raw_buf); in wm_adsp_buffer_capture_block()
4274 wm_adsp_remove_padding(compr->raw_buf, nwords, WM_ADSP_DATA_WORD_SIZE); in wm_adsp_buffer_capture_block()
4277 buf->read_index += nwords; in wm_adsp_buffer_capture_block()
4278 if (buf->read_index == wm_adsp_buffer_size(buf)) in wm_adsp_buffer_capture_block()
4279 buf->read_index = 0; in wm_adsp_buffer_capture_block()
4282 buf->read_index); in wm_adsp_buffer_capture_block()
4287 buf->avail -= nwords; in wm_adsp_buffer_capture_block()
4295 struct wm_adsp *dsp = compr->dsp; in wm_adsp_compr_read()
4301 if (dsp->fatal_error || !compr->buf || compr->buf->error) { in wm_adsp_compr_read()
4302 snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN); in wm_adsp_compr_read()
4303 return -EIO; in wm_adsp_compr_read()
4320 if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) { in wm_adsp_compr_read()
4323 return -EFAULT; in wm_adsp_compr_read()
4326 count -= nwords; in wm_adsp_compr_read()
4330 compr->copied_total += ntotal; in wm_adsp_compr_read()
4339 struct wm_adsp_compr *compr = stream->runtime->private_data; in wm_adsp_compr_copy()
4340 struct wm_adsp *dsp = compr->dsp; in wm_adsp_compr_copy()
4343 mutex_lock(&dsp->pwr_lock); in wm_adsp_compr_copy()
4345 if (stream->direction == SND_COMPRESS_CAPTURE) in wm_adsp_compr_copy()
4348 ret = -ENOTSUPP; in wm_adsp_compr_copy()
4350 mutex_unlock(&dsp->pwr_lock); in wm_adsp_compr_copy()
4360 dsp->fatal_error = true; in wm_adsp_fatal_error()
4362 list_for_each_entry(compr, &dsp->compr_list, list) { in wm_adsp_fatal_error()
4363 if (compr->stream) in wm_adsp_fatal_error()
4364 snd_compr_fragment_elapsed(compr->stream); in wm_adsp_fatal_error()
4372 struct regmap *regmap = dsp->regmap; in wm_adsp2_bus_error()
4375 mutex_lock(&dsp->pwr_lock); in wm_adsp2_bus_error()
4377 ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val); in wm_adsp2_bus_error()
4386 dsp->ops->stop_watchdog(dsp); in wm_adsp2_bus_error()
4396 ret = regmap_read(regmap, dsp->base + ADSP2_BUS_ERR_ADDR, &val); in wm_adsp2_bus_error()
4408 dsp->base + ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR, in wm_adsp2_bus_error()
4424 regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, in wm_adsp2_bus_error()
4428 mutex_unlock(&dsp->pwr_lock); in wm_adsp2_bus_error()
4437 struct regmap *regmap = dsp->regmap; in wm_halo_bus_error()
4440 { dsp->base + HALO_MPU_XM_VIO_STATUS, 0x0 }, in wm_halo_bus_error()
4441 { dsp->base + HALO_MPU_YM_VIO_STATUS, 0x0 }, in wm_halo_bus_error()
4442 { dsp->base + HALO_MPU_PM_VIO_STATUS, 0x0 }, in wm_halo_bus_error()
4446 mutex_lock(&dsp->pwr_lock); in wm_halo_bus_error()
4448 ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_1, in wm_halo_bus_error()
4460 ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_0, in wm_halo_bus_error()
4469 ret = regmap_bulk_read(regmap, dsp->base + HALO_MPU_XM_VIO_ADDR, in wm_halo_bus_error()
4480 ret = regmap_multi_reg_write(dsp->regmap, clear, ARRAY_SIZE(clear)); in wm_halo_bus_error()
4485 mutex_unlock(&dsp->pwr_lock); in wm_halo_bus_error()
4495 mutex_lock(&dsp->pwr_lock); in wm_halo_wdt_expire()
4498 dsp->ops->stop_watchdog(dsp); in wm_halo_wdt_expire()
4501 mutex_unlock(&dsp->pwr_lock); in wm_halo_wdt_expire()