Lines Matching full:dsp
3 * cs_dsp.c -- Cirrus Logic DSP firmware support
279 bool (*validate_version)(struct cs_dsp *dsp, unsigned int version);
280 unsigned int (*parse_sizes)(struct cs_dsp *dsp,
284 int (*setup_algs)(struct cs_dsp *dsp);
288 void (*show_fw_status)(struct cs_dsp *dsp);
289 void (*stop_watchdog)(struct cs_dsp *dsp);
291 int (*enable_memory)(struct cs_dsp *dsp);
292 void (*disable_memory)(struct cs_dsp *dsp);
293 int (*lock_memory)(struct cs_dsp *dsp, unsigned int lock_regions);
295 int (*enable_core)(struct cs_dsp *dsp);
296 void (*disable_core)(struct cs_dsp *dsp);
298 int (*start_core)(struct cs_dsp *dsp);
299 void (*stop_core)(struct cs_dsp *dsp);
377 static void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp, const char *s) in cs_dsp_debugfs_save_wmfwname() argument
381 kfree(dsp->wmfw_file_name); in cs_dsp_debugfs_save_wmfwname()
382 dsp->wmfw_file_name = tmp; in cs_dsp_debugfs_save_wmfwname()
385 static void cs_dsp_debugfs_save_binname(struct cs_dsp *dsp, const char *s) in cs_dsp_debugfs_save_binname() argument
389 kfree(dsp->bin_file_name); in cs_dsp_debugfs_save_binname()
390 dsp->bin_file_name = tmp; in cs_dsp_debugfs_save_binname()
393 static void cs_dsp_debugfs_clear(struct cs_dsp *dsp) in cs_dsp_debugfs_clear() argument
395 kfree(dsp->wmfw_file_name); in cs_dsp_debugfs_clear()
396 kfree(dsp->bin_file_name); in cs_dsp_debugfs_clear()
397 dsp->wmfw_file_name = NULL; in cs_dsp_debugfs_clear()
398 dsp->bin_file_name = NULL; in cs_dsp_debugfs_clear()
405 struct cs_dsp *dsp = file->private_data; in cs_dsp_debugfs_wmfw_read() local
408 mutex_lock(&dsp->pwr_lock); in cs_dsp_debugfs_wmfw_read()
410 if (!dsp->wmfw_file_name || !dsp->booted) in cs_dsp_debugfs_wmfw_read()
414 dsp->wmfw_file_name, in cs_dsp_debugfs_wmfw_read()
415 strlen(dsp->wmfw_file_name)); in cs_dsp_debugfs_wmfw_read()
417 mutex_unlock(&dsp->pwr_lock); in cs_dsp_debugfs_wmfw_read()
425 struct cs_dsp *dsp = file->private_data; in cs_dsp_debugfs_bin_read() local
428 mutex_lock(&dsp->pwr_lock); in cs_dsp_debugfs_bin_read()
430 if (!dsp->bin_file_name || !dsp->booted) in cs_dsp_debugfs_bin_read()
434 dsp->bin_file_name, in cs_dsp_debugfs_bin_read()
435 strlen(dsp->bin_file_name)); in cs_dsp_debugfs_bin_read()
437 mutex_unlock(&dsp->pwr_lock); in cs_dsp_debugfs_bin_read()
466 struct cs_dsp *dsp = s->private; in cs_dsp_debugfs_read_controls_show() local
470 list_for_each_entry(ctl, &dsp->ctl_list, list) { in cs_dsp_debugfs_read_controls_show()
489 * cs_dsp_init_debugfs() - Create and populate DSP representation in debugfs
490 * @dsp: pointer to DSP structure
491 * @debugfs_root: pointer to debugfs directory in which to create this DSP
494 void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root) in cs_dsp_init_debugfs() argument
499 root = debugfs_create_dir(dsp->name, debugfs_root); in cs_dsp_init_debugfs()
501 debugfs_create_bool("booted", 0444, root, &dsp->booted); in cs_dsp_init_debugfs()
502 debugfs_create_bool("running", 0444, root, &dsp->running); in cs_dsp_init_debugfs()
503 debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id); in cs_dsp_init_debugfs()
504 debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version); in cs_dsp_init_debugfs()
508 dsp, &cs_dsp_debugfs_fops[i].fops); in cs_dsp_init_debugfs()
510 debugfs_create_file("controls", 0444, root, dsp, in cs_dsp_init_debugfs()
513 dsp->debugfs_root = root; in cs_dsp_init_debugfs()
518 * cs_dsp_cleanup_debugfs() - Removes DSP representation from debugfs
519 * @dsp: pointer to DSP structure
521 void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp) in cs_dsp_cleanup_debugfs() argument
523 cs_dsp_debugfs_clear(dsp); in cs_dsp_cleanup_debugfs()
524 debugfs_remove_recursive(dsp->debugfs_root); in cs_dsp_cleanup_debugfs()
525 dsp->debugfs_root = NULL; in cs_dsp_cleanup_debugfs()
529 void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root) in cs_dsp_init_debugfs() argument
534 void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp) in cs_dsp_cleanup_debugfs() argument
539 static inline void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp, in cs_dsp_debugfs_save_wmfwname() argument
544 static inline void cs_dsp_debugfs_save_binname(struct cs_dsp *dsp, in cs_dsp_debugfs_save_binname() argument
549 static inline void cs_dsp_debugfs_clear(struct cs_dsp *dsp) in cs_dsp_debugfs_clear() argument
554 static const struct cs_dsp_region *cs_dsp_find_region(struct cs_dsp *dsp, in cs_dsp_find_region() argument
559 for (i = 0; i < dsp->num_mems; i++) in cs_dsp_find_region()
560 if (dsp->mem[i].type == type) in cs_dsp_find_region()
561 return &dsp->mem[i]; in cs_dsp_find_region()
601 static void cs_dsp_read_fw_status(struct cs_dsp *dsp, in cs_dsp_read_fw_status() argument
608 ret = regmap_read(dsp->regmap, dsp->base + offs[i], &offs[i]); in cs_dsp_read_fw_status()
610 cs_dsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret); in cs_dsp_read_fw_status()
616 static void cs_dsp_adsp2_show_fw_status(struct cs_dsp *dsp) in cs_dsp_adsp2_show_fw_status() argument
622 cs_dsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs); in cs_dsp_adsp2_show_fw_status()
624 cs_dsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", in cs_dsp_adsp2_show_fw_status()
628 static void cs_dsp_adsp2v2_show_fw_status(struct cs_dsp *dsp) in cs_dsp_adsp2v2_show_fw_status() argument
632 cs_dsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs); in cs_dsp_adsp2v2_show_fw_status()
634 cs_dsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", in cs_dsp_adsp2v2_show_fw_status()
639 static void cs_dsp_halo_show_fw_status(struct cs_dsp *dsp) in cs_dsp_halo_show_fw_status() argument
645 cs_dsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs); in cs_dsp_halo_show_fw_status()
647 cs_dsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", in cs_dsp_halo_show_fw_status()
655 struct cs_dsp *dsp = ctl->dsp; in cs_dsp_coeff_base_reg() local
658 mem = cs_dsp_find_region(dsp, alg_region->type); in cs_dsp_coeff_base_reg()
660 cs_dsp_err(dsp, "No base for region %x\n", in cs_dsp_coeff_base_reg()
665 *reg = dsp->ops->region_to_reg(mem, ctl->alg_region.base + ctl->offset + off); in cs_dsp_coeff_base_reg()
684 struct cs_dsp *dsp = ctl->dsp; in cs_dsp_coeff_write_acked_control() local
689 lockdep_assert_held(&dsp->pwr_lock); in cs_dsp_coeff_write_acked_control()
691 if (!dsp->running) in cs_dsp_coeff_write_acked_control()
698 cs_dsp_dbg(dsp, "Sending 0x%x to acked control alg 0x%x %s:0x%x\n", in cs_dsp_coeff_write_acked_control()
702 ret = regmap_raw_write(dsp->regmap, reg, &val, sizeof(val)); in cs_dsp_coeff_write_acked_control()
704 cs_dsp_err(dsp, "Failed to write %x: %d\n", reg, ret); in cs_dsp_coeff_write_acked_control()
726 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); in cs_dsp_coeff_write_acked_control()
728 cs_dsp_err(dsp, "Failed to read %x: %d\n", reg, ret); in cs_dsp_coeff_write_acked_control()
733 cs_dsp_dbg(dsp, "Acked control ACKED at poll %u\n", i); in cs_dsp_coeff_write_acked_control()
738 cs_dsp_warn(dsp, "Acked control @0x%x alg:0x%x %s:0x%x timed out\n", in cs_dsp_coeff_write_acked_control()
750 struct cs_dsp *dsp = ctl->dsp; in cs_dsp_coeff_write_ctrl_raw() local
763 ret = regmap_raw_write(dsp->regmap, reg, scratch, in cs_dsp_coeff_write_ctrl_raw()
766 cs_dsp_err(dsp, "Failed to write %zu bytes to %x: %d\n", in cs_dsp_coeff_write_ctrl_raw()
771 cs_dsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg); in cs_dsp_coeff_write_ctrl_raw()
797 lockdep_assert_held(&ctl->dsp->pwr_lock); in cs_dsp_coeff_write_ctrl()
812 if (ctl->enabled && ctl->dsp->running) in cs_dsp_coeff_write_ctrl()
825 struct cs_dsp *dsp = ctl->dsp; in cs_dsp_coeff_read_ctrl_raw() local
838 ret = regmap_raw_read(dsp->regmap, reg, scratch, len); in cs_dsp_coeff_read_ctrl_raw()
840 cs_dsp_err(dsp, "Failed to read %zu bytes from %x: %d\n", in cs_dsp_coeff_read_ctrl_raw()
845 cs_dsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg); in cs_dsp_coeff_read_ctrl_raw()
872 lockdep_assert_held(&ctl->dsp->pwr_lock); in cs_dsp_coeff_read_ctrl()
878 if (ctl->enabled && ctl->dsp->running) in cs_dsp_coeff_read_ctrl()
883 if (!ctl->flags && ctl->enabled && ctl->dsp->running) in cs_dsp_coeff_read_ctrl()
894 static int cs_dsp_coeff_init_control_caches(struct cs_dsp *dsp) in cs_dsp_coeff_init_control_caches() argument
899 list_for_each_entry(ctl, &dsp->ctl_list, list) { in cs_dsp_coeff_init_control_caches()
906 * For readable controls populate the cache from the DSP memory. in cs_dsp_coeff_init_control_caches()
920 static int cs_dsp_coeff_sync_controls(struct cs_dsp *dsp) in cs_dsp_coeff_sync_controls() argument
925 list_for_each_entry(ctl, &dsp->ctl_list, list) { in cs_dsp_coeff_sync_controls()
939 static void cs_dsp_signal_event_controls(struct cs_dsp *dsp, in cs_dsp_signal_event_controls() argument
945 list_for_each_entry(ctl, &dsp->ctl_list, list) { in cs_dsp_signal_event_controls()
954 cs_dsp_warn(dsp, in cs_dsp_signal_event_controls()
967 static int cs_dsp_create_control(struct cs_dsp *dsp, in cs_dsp_create_control() argument
976 list_for_each_entry(ctl, &dsp->ctl_list, list) { in cs_dsp_create_control()
977 if (ctl->fw_name == dsp->fw_name && in cs_dsp_create_control()
994 ctl->fw_name = dsp->fw_name; in cs_dsp_create_control()
996 if (subname && dsp->fw_ver >= 2) { in cs_dsp_create_control()
1006 ctl->dsp = dsp; in cs_dsp_create_control()
1018 list_add(&ctl->list, &dsp->ctl_list); in cs_dsp_create_control()
1020 if (dsp->client_ops->control_add) { in cs_dsp_create_control()
1021 ret = dsp->client_ops->control_add(ctl); in cs_dsp_create_control()
1099 static inline void cs_dsp_coeff_parse_alg(struct cs_dsp *dsp, const u8 **data, in cs_dsp_coeff_parse_alg() argument
1104 switch (dsp->fw_ver) { in cs_dsp_coeff_parse_alg()
1124 cs_dsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id); in cs_dsp_coeff_parse_alg()
1125 cs_dsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name); in cs_dsp_coeff_parse_alg()
1126 cs_dsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff); in cs_dsp_coeff_parse_alg()
1129 static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data, in cs_dsp_coeff_parse_coeff() argument
1136 switch (dsp->fw_ver) { in cs_dsp_coeff_parse_coeff()
1167 cs_dsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type); in cs_dsp_coeff_parse_coeff()
1168 cs_dsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset); in cs_dsp_coeff_parse_coeff()
1169 cs_dsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name); in cs_dsp_coeff_parse_coeff()
1170 cs_dsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags); in cs_dsp_coeff_parse_coeff()
1171 cs_dsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type); in cs_dsp_coeff_parse_coeff()
1172 cs_dsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len); in cs_dsp_coeff_parse_coeff()
1175 static int cs_dsp_check_coeff_flags(struct cs_dsp *dsp, in cs_dsp_check_coeff_flags() argument
1182 cs_dsp_err(dsp, "Illegal flags 0x%x for control type 0x%x\n", in cs_dsp_check_coeff_flags()
1190 static int cs_dsp_parse_coeff(struct cs_dsp *dsp, in cs_dsp_parse_coeff() argument
1199 cs_dsp_coeff_parse_alg(dsp, &data, &alg_blk); in cs_dsp_parse_coeff()
1201 cs_dsp_coeff_parse_coeff(dsp, &data, &coeff_blk); in cs_dsp_parse_coeff()
1210 ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk, in cs_dsp_parse_coeff()
1220 ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk, in cs_dsp_parse_coeff()
1230 ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk, in cs_dsp_parse_coeff()
1239 cs_dsp_err(dsp, "Unknown control type: %d\n", in cs_dsp_parse_coeff()
1247 ret = cs_dsp_create_control(dsp, &alg_region, in cs_dsp_parse_coeff()
1255 cs_dsp_err(dsp, "Failed to create control: %.*s, %d\n", in cs_dsp_parse_coeff()
1262 static unsigned int cs_dsp_adsp1_parse_sizes(struct cs_dsp *dsp, in cs_dsp_adsp1_parse_sizes() argument
1271 cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file, in cs_dsp_adsp1_parse_sizes()
1278 static unsigned int cs_dsp_adsp2_parse_sizes(struct cs_dsp *dsp, in cs_dsp_adsp2_parse_sizes() argument
1287 cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file, in cs_dsp_adsp2_parse_sizes()
1294 static bool cs_dsp_validate_version(struct cs_dsp *dsp, unsigned int version) in cs_dsp_validate_version() argument
1298 cs_dsp_warn(dsp, "Deprecated file format %d\n", version); in cs_dsp_validate_version()
1308 static bool cs_dsp_halo_validate_version(struct cs_dsp *dsp, unsigned int version) in cs_dsp_halo_validate_version() argument
1318 static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, in cs_dsp_load() argument
1322 struct regmap *regmap = dsp->regmap; in cs_dsp_load()
1343 cs_dsp_err(dsp, "%s: file too short, %zu bytes\n", in cs_dsp_load()
1351 cs_dsp_err(dsp, "%s: invalid magic\n", file); in cs_dsp_load()
1355 if (!dsp->ops->validate_version(dsp, header->ver)) { in cs_dsp_load()
1356 cs_dsp_err(dsp, "%s: unknown file format %d\n", in cs_dsp_load()
1361 cs_dsp_info(dsp, "Firmware version: %d\n", header->ver); in cs_dsp_load()
1362 dsp->fw_ver = header->ver; in cs_dsp_load()
1364 if (header->core != dsp->type) { in cs_dsp_load()
1365 cs_dsp_err(dsp, "%s: invalid core %d != %d\n", in cs_dsp_load()
1366 file, header->core, dsp->type); in cs_dsp_load()
1371 pos = dsp->ops->parse_sizes(dsp, file, pos, firmware); in cs_dsp_load()
1377 cs_dsp_err(dsp, "%s: unexpected header length %d\n", in cs_dsp_load()
1382 cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file, in cs_dsp_load()
1402 ret = cs_dsp_parse_coeff(dsp, region); in cs_dsp_load()
1423 mem = cs_dsp_find_region(dsp, type); in cs_dsp_load()
1425 cs_dsp_err(dsp, "No region of type: %x\n", type); in cs_dsp_load()
1431 reg = dsp->ops->region_to_reg(mem, offset); in cs_dsp_load()
1434 cs_dsp_warn(dsp, in cs_dsp_load()
1440 cs_dsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file, in cs_dsp_load()
1446 cs_dsp_err(dsp, in cs_dsp_load()
1456 cs_dsp_info(dsp, "%s: %s\n", file, text); in cs_dsp_load()
1466 cs_dsp_err(dsp, "Out of memory\n"); in cs_dsp_load()
1474 cs_dsp_err(dsp, in cs_dsp_load()
1489 cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret); in cs_dsp_load()
1494 cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", in cs_dsp_load()
1497 cs_dsp_debugfs_save_wmfwname(dsp, file); in cs_dsp_load()
1509 * @dsp: pointer to DSP structure
1518 struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type, in cs_dsp_get_ctl() argument
1523 lockdep_assert_held(&dsp->pwr_lock); in cs_dsp_get_ctl()
1525 list_for_each_entry(pos, &dsp->ctl_list, list) { in cs_dsp_get_ctl()
1529 pos->fw_name == dsp->fw_name && in cs_dsp_get_ctl()
1541 static void cs_dsp_ctl_fixup_base(struct cs_dsp *dsp, in cs_dsp_ctl_fixup_base() argument
1546 list_for_each_entry(ctl, &dsp->ctl_list, list) { in cs_dsp_ctl_fixup_base()
1547 if (ctl->fw_name == dsp->fw_name && in cs_dsp_ctl_fixup_base()
1555 static void *cs_dsp_read_algs(struct cs_dsp *dsp, size_t n_algs, in cs_dsp_read_algs() argument
1565 cs_dsp_err(dsp, "No algorithms\n"); in cs_dsp_read_algs()
1570 cs_dsp_err(dsp, "Algorithm count %zx excessive\n", n_algs); in cs_dsp_read_algs()
1575 reg = dsp->ops->region_to_reg(mem, pos + len); in cs_dsp_read_algs()
1577 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val)); in cs_dsp_read_algs()
1579 cs_dsp_err(dsp, "Failed to read algorithm list end: %d\n", in cs_dsp_read_algs()
1585 cs_dsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n", in cs_dsp_read_algs()
1588 /* Convert length from DSP words to bytes */ in cs_dsp_read_algs()
1595 reg = dsp->ops->region_to_reg(mem, pos); in cs_dsp_read_algs()
1597 ret = regmap_raw_read(dsp->regmap, reg, alg, len); in cs_dsp_read_algs()
1599 cs_dsp_err(dsp, "Failed to read algorithm list: %d\n", ret); in cs_dsp_read_algs()
1609 * @dsp: pointer to DSP structure
1615 struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp, in cs_dsp_find_alg_region() argument
1620 lockdep_assert_held(&dsp->pwr_lock); in cs_dsp_find_alg_region()
1622 list_for_each_entry(alg_region, &dsp->alg_regions, list) { in cs_dsp_find_alg_region()
1631 static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp, in cs_dsp_create_region() argument
1646 list_add_tail(&alg_region->list, &dsp->alg_regions); in cs_dsp_create_region()
1648 if (dsp->fw_ver > 0) in cs_dsp_create_region()
1649 cs_dsp_ctl_fixup_base(dsp, alg_region); in cs_dsp_create_region()
1654 static void cs_dsp_free_alg_regions(struct cs_dsp *dsp) in cs_dsp_free_alg_regions() argument
1658 while (!list_empty(&dsp->alg_regions)) { in cs_dsp_free_alg_regions()
1659 alg_region = list_first_entry(&dsp->alg_regions, in cs_dsp_free_alg_regions()
1667 static void cs_dsp_parse_wmfw_id_header(struct cs_dsp *dsp, in cs_dsp_parse_wmfw_id_header() argument
1670 dsp->fw_id = be32_to_cpu(fw->id); in cs_dsp_parse_wmfw_id_header()
1671 dsp->fw_id_version = be32_to_cpu(fw->ver); in cs_dsp_parse_wmfw_id_header()
1673 cs_dsp_info(dsp, "Firmware: %x v%d.%d.%d, %d algorithms\n", in cs_dsp_parse_wmfw_id_header()
1674 dsp->fw_id, (dsp->fw_id_version & 0xff0000) >> 16, in cs_dsp_parse_wmfw_id_header()
1675 (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff, in cs_dsp_parse_wmfw_id_header()
1679 static void cs_dsp_parse_wmfw_v3_id_header(struct cs_dsp *dsp, in cs_dsp_parse_wmfw_v3_id_header() argument
1682 dsp->fw_id = be32_to_cpu(fw->id); in cs_dsp_parse_wmfw_v3_id_header()
1683 dsp->fw_id_version = be32_to_cpu(fw->ver); in cs_dsp_parse_wmfw_v3_id_header()
1684 dsp->fw_vendor_id = be32_to_cpu(fw->vendor_id); in cs_dsp_parse_wmfw_v3_id_header()
1686 cs_dsp_info(dsp, "Firmware: %x vendor: 0x%x v%d.%d.%d, %d algorithms\n", in cs_dsp_parse_wmfw_v3_id_header()
1687 dsp->fw_id, dsp->fw_vendor_id, in cs_dsp_parse_wmfw_v3_id_header()
1688 (dsp->fw_id_version & 0xff0000) >> 16, in cs_dsp_parse_wmfw_v3_id_header()
1689 (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff, in cs_dsp_parse_wmfw_v3_id_header()
1693 static int cs_dsp_create_regions(struct cs_dsp *dsp, __be32 id, __be32 ver, in cs_dsp_create_regions() argument
1700 alg_region = cs_dsp_create_region(dsp, type[i], id, ver, base[i]); in cs_dsp_create_regions()
1708 static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp) in cs_dsp_adsp1_setup_algs() argument
1718 mem = cs_dsp_find_region(dsp, WMFW_ADSP1_DM); in cs_dsp_adsp1_setup_algs()
1722 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id, in cs_dsp_adsp1_setup_algs()
1725 cs_dsp_err(dsp, "Failed to read algorithm info: %d\n", in cs_dsp_adsp1_setup_algs()
1732 cs_dsp_parse_wmfw_id_header(dsp, &adsp1_id.fw, n_algs); in cs_dsp_adsp1_setup_algs()
1734 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_ZM, in cs_dsp_adsp1_setup_algs()
1740 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_DM, in cs_dsp_adsp1_setup_algs()
1746 /* Calculate offset and length in DSP words */ in cs_dsp_adsp1_setup_algs()
1750 adsp1_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len); in cs_dsp_adsp1_setup_algs()
1755 cs_dsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n", in cs_dsp_adsp1_setup_algs()
1763 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_DM, in cs_dsp_adsp1_setup_algs()
1771 if (dsp->fw_ver == 0) { in cs_dsp_adsp1_setup_algs()
1776 cs_dsp_create_control(dsp, alg_region, 0, in cs_dsp_adsp1_setup_algs()
1780 cs_dsp_warn(dsp, "Missing length info for region DM with ID %x\n", in cs_dsp_adsp1_setup_algs()
1785 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_ZM, in cs_dsp_adsp1_setup_algs()
1793 if (dsp->fw_ver == 0) { in cs_dsp_adsp1_setup_algs()
1798 cs_dsp_create_control(dsp, alg_region, 0, in cs_dsp_adsp1_setup_algs()
1802 cs_dsp_warn(dsp, "Missing length info for region ZM with ID %x\n", in cs_dsp_adsp1_setup_algs()
1813 static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp) in cs_dsp_adsp2_setup_algs() argument
1823 mem = cs_dsp_find_region(dsp, WMFW_ADSP2_XM); in cs_dsp_adsp2_setup_algs()
1827 ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id, in cs_dsp_adsp2_setup_algs()
1830 cs_dsp_err(dsp, "Failed to read algorithm info: %d\n", in cs_dsp_adsp2_setup_algs()
1837 cs_dsp_parse_wmfw_id_header(dsp, &adsp2_id.fw, n_algs); in cs_dsp_adsp2_setup_algs()
1839 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM, in cs_dsp_adsp2_setup_algs()
1845 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_YM, in cs_dsp_adsp2_setup_algs()
1851 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_ZM, in cs_dsp_adsp2_setup_algs()
1857 /* Calculate offset and length in DSP words */ in cs_dsp_adsp2_setup_algs()
1861 adsp2_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len); in cs_dsp_adsp2_setup_algs()
1866 cs_dsp_dbg(dsp, in cs_dsp_adsp2_setup_algs()
1876 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM, in cs_dsp_adsp2_setup_algs()
1884 if (dsp->fw_ver == 0) { in cs_dsp_adsp2_setup_algs()
1889 cs_dsp_create_control(dsp, alg_region, 0, in cs_dsp_adsp2_setup_algs()
1893 cs_dsp_warn(dsp, "Missing length info for region XM with ID %x\n", in cs_dsp_adsp2_setup_algs()
1898 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_YM, in cs_dsp_adsp2_setup_algs()
1906 if (dsp->fw_ver == 0) { in cs_dsp_adsp2_setup_algs()
1911 cs_dsp_create_control(dsp, alg_region, 0, in cs_dsp_adsp2_setup_algs()
1915 cs_dsp_warn(dsp, "Missing length info for region YM with ID %x\n", in cs_dsp_adsp2_setup_algs()
1920 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_ZM, in cs_dsp_adsp2_setup_algs()
1928 if (dsp->fw_ver == 0) { in cs_dsp_adsp2_setup_algs()
1933 cs_dsp_create_control(dsp, alg_region, 0, in cs_dsp_adsp2_setup_algs()
1937 cs_dsp_warn(dsp, "Missing length info for region ZM with ID %x\n", in cs_dsp_adsp2_setup_algs()
1948 static int cs_dsp_halo_create_regions(struct cs_dsp *dsp, __be32 id, __be32 ver, in cs_dsp_halo_create_regions() argument
1957 return cs_dsp_create_regions(dsp, id, ver, ARRAY_SIZE(types), types, bases); in cs_dsp_halo_create_regions()
1960 static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp) in cs_dsp_halo_setup_algs() argument
1969 mem = cs_dsp_find_region(dsp, WMFW_ADSP2_XM); in cs_dsp_halo_setup_algs()
1973 ret = regmap_raw_read(dsp->regmap, mem->base, &halo_id, in cs_dsp_halo_setup_algs()
1976 cs_dsp_err(dsp, "Failed to read algorithm info: %d\n", in cs_dsp_halo_setup_algs()
1983 cs_dsp_parse_wmfw_v3_id_header(dsp, &halo_id.fw, n_algs); in cs_dsp_halo_setup_algs()
1985 ret = cs_dsp_halo_create_regions(dsp, halo_id.fw.id, halo_id.fw.ver, in cs_dsp_halo_setup_algs()
1990 /* Calculate offset and length in DSP words */ in cs_dsp_halo_setup_algs()
1994 halo_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len); in cs_dsp_halo_setup_algs()
1999 cs_dsp_dbg(dsp, in cs_dsp_halo_setup_algs()
2008 ret = cs_dsp_halo_create_regions(dsp, halo_alg[i].alg.id, in cs_dsp_halo_setup_algs()
2021 static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware, in cs_dsp_load_coeff() argument
2025 struct regmap *regmap = dsp->regmap; in cs_dsp_load_coeff()
2041 cs_dsp_err(dsp, "%s: coefficient file too short, %zu bytes\n", in cs_dsp_load_coeff()
2048 cs_dsp_err(dsp, "%s: invalid coefficient magic\n", file); in cs_dsp_load_coeff()
2057 cs_dsp_err(dsp, "%s: Unsupported coefficient file format %d\n", in cs_dsp_load_coeff()
2063 cs_dsp_info(dsp, "%s: v%d.%d.%d\n", file, in cs_dsp_load_coeff()
2079 cs_dsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n", in cs_dsp_load_coeff()
2084 cs_dsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n", in cs_dsp_load_coeff()
2101 if (le32_to_cpu(blk->id) == dsp->fw_id && in cs_dsp_load_coeff()
2104 mem = cs_dsp_find_region(dsp, type); in cs_dsp_load_coeff()
2106 cs_dsp_err(dsp, "No ZM\n"); in cs_dsp_load_coeff()
2109 reg = dsp->ops->region_to_reg(mem, 0); in cs_dsp_load_coeff()
2124 cs_dsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n", in cs_dsp_load_coeff()
2129 mem = cs_dsp_find_region(dsp, type); in cs_dsp_load_coeff()
2131 cs_dsp_err(dsp, "No base for region %x\n", type); in cs_dsp_load_coeff()
2135 alg_region = cs_dsp_find_alg_region(dsp, type, in cs_dsp_load_coeff()
2139 cs_dsp_warn(dsp, in cs_dsp_load_coeff()
2149 reg = dsp->ops->region_to_reg(mem, reg); in cs_dsp_load_coeff()
2152 cs_dsp_err(dsp, "No %s for algorithm %x\n", in cs_dsp_load_coeff()
2158 cs_dsp_err(dsp, "%s.%d: Unknown region type %x at %d\n", in cs_dsp_load_coeff()
2165 cs_dsp_info(dsp, "%s: %s\n", dsp->fw_name, text); in cs_dsp_load_coeff()
2173 cs_dsp_err(dsp, in cs_dsp_load_coeff()
2186 cs_dsp_err(dsp, "Out of memory\n"); in cs_dsp_load_coeff()
2191 cs_dsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n", in cs_dsp_load_coeff()
2197 cs_dsp_err(dsp, in cs_dsp_load_coeff()
2209 cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret); in cs_dsp_load_coeff()
2212 cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", in cs_dsp_load_coeff()
2215 cs_dsp_debugfs_save_binname(dsp, file); in cs_dsp_load_coeff()
2224 static int cs_dsp_create_name(struct cs_dsp *dsp) in cs_dsp_create_name() argument
2226 if (!dsp->name) { in cs_dsp_create_name()
2227 dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d", in cs_dsp_create_name()
2228 dsp->num); in cs_dsp_create_name()
2229 if (!dsp->name) in cs_dsp_create_name()
2236 static int cs_dsp_common_init(struct cs_dsp *dsp) in cs_dsp_common_init() argument
2240 ret = cs_dsp_create_name(dsp); in cs_dsp_common_init()
2244 INIT_LIST_HEAD(&dsp->alg_regions); in cs_dsp_common_init()
2245 INIT_LIST_HEAD(&dsp->ctl_list); in cs_dsp_common_init()
2247 mutex_init(&dsp->pwr_lock); in cs_dsp_common_init()
2254 * @dsp: pointer to DSP structure
2258 int cs_dsp_adsp1_init(struct cs_dsp *dsp) in cs_dsp_adsp1_init() argument
2260 dsp->ops = &cs_dsp_adsp1_ops; in cs_dsp_adsp1_init()
2262 return cs_dsp_common_init(dsp); in cs_dsp_adsp1_init()
2268 * @dsp: pointer to DSP structure
2277 int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, in cs_dsp_adsp1_power_up() argument
2285 mutex_lock(&dsp->pwr_lock); in cs_dsp_adsp1_power_up()
2287 dsp->fw_name = fw_name; in cs_dsp_adsp1_power_up()
2289 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, in cs_dsp_adsp1_power_up()
2293 * For simplicity set the DSP clock rate to be the in cs_dsp_adsp1_power_up()
2296 if (dsp->sysclk_reg) { in cs_dsp_adsp1_power_up()
2297 ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val); in cs_dsp_adsp1_power_up()
2299 cs_dsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret); in cs_dsp_adsp1_power_up()
2303 val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift; in cs_dsp_adsp1_power_up()
2305 ret = regmap_update_bits(dsp->regmap, in cs_dsp_adsp1_power_up()
2306 dsp->base + ADSP1_CONTROL_31, in cs_dsp_adsp1_power_up()
2309 cs_dsp_err(dsp, "Failed to set clock rate: %d\n", ret); in cs_dsp_adsp1_power_up()
2314 ret = cs_dsp_load(dsp, wmfw_firmware, wmfw_filename); in cs_dsp_adsp1_power_up()
2318 ret = cs_dsp_adsp1_setup_algs(dsp); in cs_dsp_adsp1_power_up()
2322 ret = cs_dsp_load_coeff(dsp, coeff_firmware, coeff_filename); in cs_dsp_adsp1_power_up()
2327 ret = cs_dsp_coeff_init_control_caches(dsp); in cs_dsp_adsp1_power_up()
2332 ret = cs_dsp_coeff_sync_controls(dsp); in cs_dsp_adsp1_power_up()
2336 dsp->booted = true; in cs_dsp_adsp1_power_up()
2339 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, in cs_dsp_adsp1_power_up()
2343 dsp->running = true; in cs_dsp_adsp1_power_up()
2345 mutex_unlock(&dsp->pwr_lock); in cs_dsp_adsp1_power_up()
2350 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, in cs_dsp_adsp1_power_up()
2353 mutex_unlock(&dsp->pwr_lock); in cs_dsp_adsp1_power_up()
2359 * cs_dsp_adsp1_power_down() - Halts the DSP
2360 * @dsp: pointer to DSP structure
2362 void cs_dsp_adsp1_power_down(struct cs_dsp *dsp) in cs_dsp_adsp1_power_down() argument
2366 mutex_lock(&dsp->pwr_lock); in cs_dsp_adsp1_power_down()
2368 dsp->running = false; in cs_dsp_adsp1_power_down()
2369 dsp->booted = false; in cs_dsp_adsp1_power_down()
2372 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, in cs_dsp_adsp1_power_down()
2375 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19, in cs_dsp_adsp1_power_down()
2378 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, in cs_dsp_adsp1_power_down()
2381 list_for_each_entry(ctl, &dsp->ctl_list, list) in cs_dsp_adsp1_power_down()
2384 cs_dsp_free_alg_regions(dsp); in cs_dsp_adsp1_power_down()
2386 mutex_unlock(&dsp->pwr_lock); in cs_dsp_adsp1_power_down()
2390 static int cs_dsp_adsp2v2_enable_core(struct cs_dsp *dsp) in cs_dsp_adsp2v2_enable_core() argument
2397 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val); in cs_dsp_adsp2v2_enable_core()
2408 cs_dsp_err(dsp, "Failed to start DSP RAM\n"); in cs_dsp_adsp2v2_enable_core()
2412 cs_dsp_dbg(dsp, "RAM ready after %d polls\n", count); in cs_dsp_adsp2v2_enable_core()
2417 static int cs_dsp_adsp2_enable_core(struct cs_dsp *dsp) in cs_dsp_adsp2_enable_core() argument
2421 ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL, in cs_dsp_adsp2_enable_core()
2426 return cs_dsp_adsp2v2_enable_core(dsp); in cs_dsp_adsp2_enable_core()
2429 static int cs_dsp_adsp2_lock(struct cs_dsp *dsp, unsigned int lock_regions) in cs_dsp_adsp2_lock() argument
2431 struct regmap *regmap = dsp->regmap; in cs_dsp_adsp2_lock()
2438 lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0; in cs_dsp_adsp2_lock()
2459 static int cs_dsp_adsp2_enable_memory(struct cs_dsp *dsp) in cs_dsp_adsp2_enable_memory() argument
2461 return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in cs_dsp_adsp2_enable_memory()
2465 static void cs_dsp_adsp2_disable_memory(struct cs_dsp *dsp) in cs_dsp_adsp2_disable_memory() argument
2467 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in cs_dsp_adsp2_disable_memory()
2471 static void cs_dsp_adsp2_disable_core(struct cs_dsp *dsp) in cs_dsp_adsp2_disable_core() argument
2473 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); in cs_dsp_adsp2_disable_core()
2474 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0); in cs_dsp_adsp2_disable_core()
2475 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0); in cs_dsp_adsp2_disable_core()
2477 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in cs_dsp_adsp2_disable_core()
2481 static void cs_dsp_adsp2v2_disable_core(struct cs_dsp *dsp) in cs_dsp_adsp2v2_disable_core() argument
2483 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); in cs_dsp_adsp2v2_disable_core()
2484 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0); in cs_dsp_adsp2v2_disable_core()
2485 regmap_write(dsp->regmap, dsp->base + ADSP2V2_WDMA_CONFIG_2, 0); in cs_dsp_adsp2v2_disable_core()
2488 static int cs_dsp_halo_configure_mpu(struct cs_dsp *dsp, unsigned int lock_regions) in cs_dsp_halo_configure_mpu() argument
2491 { dsp->base + HALO_MPU_LOCK_CONFIG, 0x5555 }, in cs_dsp_halo_configure_mpu()
2492 { dsp->base + HALO_MPU_LOCK_CONFIG, 0xAAAA }, in cs_dsp_halo_configure_mpu()
2493 { dsp->base + HALO_MPU_XMEM_ACCESS_0, 0xFFFFFFFF }, in cs_dsp_halo_configure_mpu()
2494 { dsp->base + HALO_MPU_YMEM_ACCESS_0, 0xFFFFFFFF }, in cs_dsp_halo_configure_mpu()
2495 { dsp->base + HALO_MPU_WINDOW_ACCESS_0, lock_regions }, in cs_dsp_halo_configure_mpu()
2496 { dsp->base + HALO_MPU_XREG_ACCESS_0, lock_regions }, in cs_dsp_halo_configure_mpu()
2497 { dsp->base + HALO_MPU_YREG_ACCESS_0, lock_regions }, in cs_dsp_halo_configure_mpu()
2498 { dsp->base + HALO_MPU_XMEM_ACCESS_1, 0xFFFFFFFF }, in cs_dsp_halo_configure_mpu()
2499 { dsp->base + HALO_MPU_YMEM_ACCESS_1, 0xFFFFFFFF }, in cs_dsp_halo_configure_mpu()
2500 { dsp->base + HALO_MPU_WINDOW_ACCESS_1, lock_regions }, in cs_dsp_halo_configure_mpu()
2501 { dsp->base + HALO_MPU_XREG_ACCESS_1, lock_regions }, in cs_dsp_halo_configure_mpu()
2502 { dsp->base + HALO_MPU_YREG_ACCESS_1, lock_regions }, in cs_dsp_halo_configure_mpu()
2503 { dsp->base + HALO_MPU_XMEM_ACCESS_2, 0xFFFFFFFF }, in cs_dsp_halo_configure_mpu()
2504 { dsp->base + HALO_MPU_YMEM_ACCESS_2, 0xFFFFFFFF }, in cs_dsp_halo_configure_mpu()
2505 { dsp->base + HALO_MPU_WINDOW_ACCESS_2, lock_regions }, in cs_dsp_halo_configure_mpu()
2506 { dsp->base + HALO_MPU_XREG_ACCESS_2, lock_regions }, in cs_dsp_halo_configure_mpu()
2507 { dsp->base + HALO_MPU_YREG_ACCESS_2, lock_regions }, in cs_dsp_halo_configure_mpu()
2508 { dsp->base + HALO_MPU_XMEM_ACCESS_3, 0xFFFFFFFF }, in cs_dsp_halo_configure_mpu()
2509 { dsp->base + HALO_MPU_YMEM_ACCESS_3, 0xFFFFFFFF }, in cs_dsp_halo_configure_mpu()
2510 { dsp->base + HALO_MPU_WINDOW_ACCESS_3, lock_regions }, in cs_dsp_halo_configure_mpu()
2511 { dsp->base + HALO_MPU_XREG_ACCESS_3, lock_regions }, in cs_dsp_halo_configure_mpu()
2512 { dsp->base + HALO_MPU_YREG_ACCESS_3, lock_regions }, in cs_dsp_halo_configure_mpu()
2513 { dsp->base + HALO_MPU_LOCK_CONFIG, 0 }, in cs_dsp_halo_configure_mpu()
2516 return regmap_multi_reg_write(dsp->regmap, config, ARRAY_SIZE(config)); in cs_dsp_halo_configure_mpu()
2521 * @dsp: pointer to DSP structure
2528 int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq) in cs_dsp_set_dspclk() argument
2532 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CLOCKING, in cs_dsp_set_dspclk()
2536 cs_dsp_err(dsp, "Failed to set clock rate: %d\n", ret); in cs_dsp_set_dspclk()
2542 static void cs_dsp_stop_watchdog(struct cs_dsp *dsp) in cs_dsp_stop_watchdog() argument
2544 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG, in cs_dsp_stop_watchdog()
2548 static void cs_dsp_halo_stop_watchdog(struct cs_dsp *dsp) in cs_dsp_halo_stop_watchdog() argument
2550 regmap_update_bits(dsp->regmap, dsp->base + HALO_WDT_CONTROL, in cs_dsp_halo_stop_watchdog()
2555 * cs_dsp_power_up() - Downloads firmware to the DSP
2556 * @dsp: pointer to DSP structure
2563 * This function is used on ADSP2 and Halo DSP cores, it powers-up the DSP core
2571 int cs_dsp_power_up(struct cs_dsp *dsp, in cs_dsp_power_up() argument
2578 mutex_lock(&dsp->pwr_lock); in cs_dsp_power_up()
2580 dsp->fw_name = fw_name; in cs_dsp_power_up()
2582 if (dsp->ops->enable_memory) { in cs_dsp_power_up()
2583 ret = dsp->ops->enable_memory(dsp); in cs_dsp_power_up()
2588 if (dsp->ops->enable_core) { in cs_dsp_power_up()
2589 ret = dsp->ops->enable_core(dsp); in cs_dsp_power_up()
2594 ret = cs_dsp_load(dsp, wmfw_firmware, wmfw_filename); in cs_dsp_power_up()
2598 ret = dsp->ops->setup_algs(dsp); in cs_dsp_power_up()
2602 ret = cs_dsp_load_coeff(dsp, coeff_firmware, coeff_filename); in cs_dsp_power_up()
2607 ret = cs_dsp_coeff_init_control_caches(dsp); in cs_dsp_power_up()
2611 if (dsp->ops->disable_core) in cs_dsp_power_up()
2612 dsp->ops->disable_core(dsp); in cs_dsp_power_up()
2614 dsp->booted = true; in cs_dsp_power_up()
2616 mutex_unlock(&dsp->pwr_lock); in cs_dsp_power_up()
2620 if (dsp->ops->disable_core) in cs_dsp_power_up()
2621 dsp->ops->disable_core(dsp); in cs_dsp_power_up()
2623 if (dsp->ops->disable_memory) in cs_dsp_power_up()
2624 dsp->ops->disable_memory(dsp); in cs_dsp_power_up()
2626 mutex_unlock(&dsp->pwr_lock); in cs_dsp_power_up()
2633 * cs_dsp_power_down() - Powers-down the DSP
2634 * @dsp: pointer to DSP structure
2639 void cs_dsp_power_down(struct cs_dsp *dsp) in cs_dsp_power_down() argument
2643 mutex_lock(&dsp->pwr_lock); in cs_dsp_power_down()
2645 cs_dsp_debugfs_clear(dsp); in cs_dsp_power_down()
2647 dsp->fw_id = 0; in cs_dsp_power_down()
2648 dsp->fw_id_version = 0; in cs_dsp_power_down()
2650 dsp->booted = false; in cs_dsp_power_down()
2652 if (dsp->ops->disable_memory) in cs_dsp_power_down()
2653 dsp->ops->disable_memory(dsp); in cs_dsp_power_down()
2655 list_for_each_entry(ctl, &dsp->ctl_list, list) in cs_dsp_power_down()
2658 cs_dsp_free_alg_regions(dsp); in cs_dsp_power_down()
2660 mutex_unlock(&dsp->pwr_lock); in cs_dsp_power_down()
2662 cs_dsp_dbg(dsp, "Shutdown complete\n"); in cs_dsp_power_down()
2666 static int cs_dsp_adsp2_start_core(struct cs_dsp *dsp) in cs_dsp_adsp2_start_core() argument
2668 return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in cs_dsp_adsp2_start_core()
2673 static void cs_dsp_adsp2_stop_core(struct cs_dsp *dsp) in cs_dsp_adsp2_stop_core() argument
2675 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in cs_dsp_adsp2_stop_core()
2681 * @dsp: pointer to DSP structure
2687 int cs_dsp_run(struct cs_dsp *dsp) in cs_dsp_run() argument
2691 mutex_lock(&dsp->pwr_lock); in cs_dsp_run()
2693 if (!dsp->booted) { in cs_dsp_run()
2698 if (dsp->ops->enable_core) { in cs_dsp_run()
2699 ret = dsp->ops->enable_core(dsp); in cs_dsp_run()
2704 if (dsp->client_ops->pre_run) { in cs_dsp_run()
2705 ret = dsp->client_ops->pre_run(dsp); in cs_dsp_run()
2711 ret = cs_dsp_coeff_sync_controls(dsp); in cs_dsp_run()
2715 if (dsp->ops->lock_memory) { in cs_dsp_run()
2716 ret = dsp->ops->lock_memory(dsp, dsp->lock_regions); in cs_dsp_run()
2718 cs_dsp_err(dsp, "Error configuring MPU: %d\n", ret); in cs_dsp_run()
2723 if (dsp->ops->start_core) { in cs_dsp_run()
2724 ret = dsp->ops->start_core(dsp); in cs_dsp_run()
2729 dsp->running = true; in cs_dsp_run()
2731 if (dsp->client_ops->post_run) { in cs_dsp_run()
2732 ret = dsp->client_ops->post_run(dsp); in cs_dsp_run()
2737 mutex_unlock(&dsp->pwr_lock); in cs_dsp_run()
2742 if (dsp->ops->stop_core) in cs_dsp_run()
2743 dsp->ops->stop_core(dsp); in cs_dsp_run()
2744 if (dsp->ops->disable_core) in cs_dsp_run()
2745 dsp->ops->disable_core(dsp); in cs_dsp_run()
2746 mutex_unlock(&dsp->pwr_lock); in cs_dsp_run()
2754 * @dsp: pointer to DSP structure
2758 void cs_dsp_stop(struct cs_dsp *dsp) in cs_dsp_stop() argument
2761 cs_dsp_signal_event_controls(dsp, CS_DSP_FW_EVENT_SHUTDOWN); in cs_dsp_stop()
2763 if (dsp->ops->stop_watchdog) in cs_dsp_stop()
2764 dsp->ops->stop_watchdog(dsp); in cs_dsp_stop()
2767 if (dsp->ops->show_fw_status) in cs_dsp_stop()
2768 dsp->ops->show_fw_status(dsp); in cs_dsp_stop()
2770 mutex_lock(&dsp->pwr_lock); in cs_dsp_stop()
2772 if (dsp->client_ops->pre_stop) in cs_dsp_stop()
2773 dsp->client_ops->pre_stop(dsp); in cs_dsp_stop()
2775 dsp->running = false; in cs_dsp_stop()
2777 if (dsp->ops->stop_core) in cs_dsp_stop()
2778 dsp->ops->stop_core(dsp); in cs_dsp_stop()
2779 if (dsp->ops->disable_core) in cs_dsp_stop()
2780 dsp->ops->disable_core(dsp); in cs_dsp_stop()
2782 if (dsp->client_ops->post_stop) in cs_dsp_stop()
2783 dsp->client_ops->post_stop(dsp); in cs_dsp_stop()
2785 mutex_unlock(&dsp->pwr_lock); in cs_dsp_stop()
2787 cs_dsp_dbg(dsp, "Execution stopped\n"); in cs_dsp_stop()
2791 static int cs_dsp_halo_start_core(struct cs_dsp *dsp) in cs_dsp_halo_start_core() argument
2795 ret = regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL, in cs_dsp_halo_start_core()
2801 return regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL, in cs_dsp_halo_start_core()
2805 static void cs_dsp_halo_stop_core(struct cs_dsp *dsp) in cs_dsp_halo_stop_core() argument
2807 regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL, in cs_dsp_halo_stop_core()
2811 regmap_update_bits(dsp->regmap, dsp->base + HALO_CORE_SOFT_RESET, in cs_dsp_halo_stop_core()
2817 * @dsp: pointer to DSP structure
2821 int cs_dsp_adsp2_init(struct cs_dsp *dsp) in cs_dsp_adsp2_init() argument
2825 switch (dsp->rev) { in cs_dsp_adsp2_init()
2828 * Disable the DSP memory by default when in reset for a small in cs_dsp_adsp2_init()
2831 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, in cs_dsp_adsp2_init()
2834 cs_dsp_err(dsp, in cs_dsp_adsp2_init()
2839 dsp->ops = &cs_dsp_adsp2_ops[0]; in cs_dsp_adsp2_init()
2842 dsp->ops = &cs_dsp_adsp2_ops[1]; in cs_dsp_adsp2_init()
2845 dsp->ops = &cs_dsp_adsp2_ops[2]; in cs_dsp_adsp2_init()
2849 return cs_dsp_common_init(dsp); in cs_dsp_adsp2_init()
2854 * cs_dsp_halo_init() - Initialise a cs_dsp structure representing a HALO Core DSP
2855 * @dsp: pointer to DSP structure
2859 int cs_dsp_halo_init(struct cs_dsp *dsp) in cs_dsp_halo_init() argument
2861 if (dsp->no_core_startstop) in cs_dsp_halo_init()
2862 dsp->ops = &cs_dsp_halo_ao_ops; in cs_dsp_halo_init()
2864 dsp->ops = &cs_dsp_halo_ops; in cs_dsp_halo_init()
2866 return cs_dsp_common_init(dsp); in cs_dsp_halo_init()
2872 * @dsp: pointer to DSP structure
2874 void cs_dsp_remove(struct cs_dsp *dsp) in cs_dsp_remove() argument
2878 while (!list_empty(&dsp->ctl_list)) { in cs_dsp_remove()
2879 ctl = list_first_entry(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); in cs_dsp_remove()
2881 if (dsp->client_ops->control_remove) in cs_dsp_remove()
2882 dsp->client_ops->control_remove(ctl); in cs_dsp_remove()
2891 * cs_dsp_read_raw_data_block() - Reads a block of data from DSP memory
2892 * @dsp: pointer to DSP structure
2893 * @mem_type: the type of DSP memory containing the data to be read
2898 * If this is used to read unpacked 24-bit memory, each 24-bit DSP word will
2904 int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, in cs_dsp_read_raw_data_block() argument
2907 struct cs_dsp_region const *mem = cs_dsp_find_region(dsp, mem_type); in cs_dsp_read_raw_data_block()
2911 lockdep_assert_held(&dsp->pwr_lock); in cs_dsp_read_raw_data_block()
2916 reg = dsp->ops->region_to_reg(mem, mem_addr); in cs_dsp_read_raw_data_block()
2918 ret = regmap_raw_read(dsp->regmap, reg, data, in cs_dsp_read_raw_data_block()
2928 * cs_dsp_read_data_word() - Reads a word from DSP memory
2929 * @dsp: pointer to DSP structure
2930 * @mem_type: the type of DSP memory containing the data to be read
2936 int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 *data) in cs_dsp_read_data_word() argument
2941 ret = cs_dsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw); in cs_dsp_read_data_word()
2952 * cs_dsp_write_data_word() - Writes a word to DSP memory
2953 * @dsp: pointer to DSP structure
2954 * @mem_type: the type of DSP memory containing the data to be written
2960 int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 data) in cs_dsp_write_data_word() argument
2962 struct cs_dsp_region const *mem = cs_dsp_find_region(dsp, mem_type); in cs_dsp_write_data_word()
2966 lockdep_assert_held(&dsp->pwr_lock); in cs_dsp_write_data_word()
2971 reg = dsp->ops->region_to_reg(mem, mem_addr); in cs_dsp_write_data_word()
2973 return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val)); in cs_dsp_write_data_word()
2979 * @buf: buffer containing DSP words read from DSP memory
2982 * DSP words from the register map have pad bytes and the data bytes
3002 * cs_dsp_adsp2_bus_error() - Handle a DSP bus error interrupt
3003 * @dsp: pointer to DSP structure
3005 * The firmware and DSP state will be logged for future analysis.
3007 void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp) in cs_dsp_adsp2_bus_error() argument
3010 struct regmap *regmap = dsp->regmap; in cs_dsp_adsp2_bus_error()
3013 mutex_lock(&dsp->pwr_lock); in cs_dsp_adsp2_bus_error()
3015 ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val); in cs_dsp_adsp2_bus_error()
3017 cs_dsp_err(dsp, in cs_dsp_adsp2_bus_error()
3023 cs_dsp_err(dsp, "watchdog timeout error\n"); in cs_dsp_adsp2_bus_error()
3024 dsp->ops->stop_watchdog(dsp); in cs_dsp_adsp2_bus_error()
3025 if (dsp->client_ops->watchdog_expired) in cs_dsp_adsp2_bus_error()
3026 dsp->client_ops->watchdog_expired(dsp); in cs_dsp_adsp2_bus_error()
3031 cs_dsp_err(dsp, "bus error: address error\n"); in cs_dsp_adsp2_bus_error()
3033 cs_dsp_err(dsp, "bus error: region lock error\n"); in cs_dsp_adsp2_bus_error()
3035 ret = regmap_read(regmap, dsp->base + ADSP2_BUS_ERR_ADDR, &val); in cs_dsp_adsp2_bus_error()
3037 cs_dsp_err(dsp, in cs_dsp_adsp2_bus_error()
3043 cs_dsp_err(dsp, "bus error address = 0x%x\n", in cs_dsp_adsp2_bus_error()
3047 dsp->base + ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR, in cs_dsp_adsp2_bus_error()
3050 cs_dsp_err(dsp, in cs_dsp_adsp2_bus_error()
3056 cs_dsp_err(dsp, "xmem error address = 0x%x\n", in cs_dsp_adsp2_bus_error()
3058 cs_dsp_err(dsp, "pmem error address = 0x%x\n", in cs_dsp_adsp2_bus_error()
3063 regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, in cs_dsp_adsp2_bus_error()
3067 mutex_unlock(&dsp->pwr_lock); in cs_dsp_adsp2_bus_error()
3072 * cs_dsp_halo_bus_error() - Handle a DSP bus error interrupt
3073 * @dsp: pointer to DSP structure
3075 * The firmware and DSP state will be logged for future analysis.
3077 void cs_dsp_halo_bus_error(struct cs_dsp *dsp) in cs_dsp_halo_bus_error() argument
3079 struct regmap *regmap = dsp->regmap; in cs_dsp_halo_bus_error()
3082 { dsp->base + HALO_MPU_XM_VIO_STATUS, 0x0 }, in cs_dsp_halo_bus_error()
3083 { dsp->base + HALO_MPU_YM_VIO_STATUS, 0x0 }, in cs_dsp_halo_bus_error()
3084 { dsp->base + HALO_MPU_PM_VIO_STATUS, 0x0 }, in cs_dsp_halo_bus_error()
3088 mutex_lock(&dsp->pwr_lock); in cs_dsp_halo_bus_error()
3090 ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_1, in cs_dsp_halo_bus_error()
3093 cs_dsp_warn(dsp, "Failed to read AHB DEBUG_1: %d\n", ret); in cs_dsp_halo_bus_error()
3097 cs_dsp_warn(dsp, "AHB: STATUS: 0x%x ADDR: 0x%x\n", in cs_dsp_halo_bus_error()
3102 ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_0, in cs_dsp_halo_bus_error()
3105 cs_dsp_warn(dsp, "Failed to read AHB DEBUG_0: %d\n", ret); in cs_dsp_halo_bus_error()
3109 cs_dsp_warn(dsp, "AHB: SYS_ADDR: 0x%x\n", *fault); in cs_dsp_halo_bus_error()
3111 ret = regmap_bulk_read(regmap, dsp->base + HALO_MPU_XM_VIO_ADDR, in cs_dsp_halo_bus_error()
3114 cs_dsp_warn(dsp, "Failed to read MPU fault info: %d\n", ret); in cs_dsp_halo_bus_error()
3118 cs_dsp_warn(dsp, "XM: STATUS:0x%x ADDR:0x%x\n", fault[1], fault[0]); in cs_dsp_halo_bus_error()
3119 cs_dsp_warn(dsp, "YM: STATUS:0x%x ADDR:0x%x\n", fault[3], fault[2]); in cs_dsp_halo_bus_error()
3120 cs_dsp_warn(dsp, "PM: STATUS:0x%x ADDR:0x%x\n", fault[5], fault[4]); in cs_dsp_halo_bus_error()
3122 ret = regmap_multi_reg_write(dsp->regmap, clear, ARRAY_SIZE(clear)); in cs_dsp_halo_bus_error()
3124 cs_dsp_warn(dsp, "Failed to clear MPU status: %d\n", ret); in cs_dsp_halo_bus_error()
3127 mutex_unlock(&dsp->pwr_lock); in cs_dsp_halo_bus_error()
3132 * cs_dsp_halo_wdt_expire() - Handle DSP watchdog expiry
3133 * @dsp: pointer to DSP structure
3137 void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp) in cs_dsp_halo_wdt_expire() argument
3139 mutex_lock(&dsp->pwr_lock); in cs_dsp_halo_wdt_expire()
3141 cs_dsp_warn(dsp, "WDT Expiry Fault\n"); in cs_dsp_halo_wdt_expire()
3143 dsp->ops->stop_watchdog(dsp); in cs_dsp_halo_wdt_expire()
3144 if (dsp->client_ops->watchdog_expired) in cs_dsp_halo_wdt_expire()
3145 dsp->client_ops->watchdog_expired(dsp); in cs_dsp_halo_wdt_expire()
3147 mutex_unlock(&dsp->pwr_lock); in cs_dsp_halo_wdt_expire()
3239 * cs_dsp_chunk_write() - Format data to a DSP memory chunk
3244 * This function sequentially writes values into the format required for DSP
3246 * big endian. Note that data is only committed to the chunk when a whole DSP
3285 * As cs_dsp_chunk_write only writes data when a whole DSP word is ready to
3287 * function will pad that data with zeros upto a whole DSP word and write out.
3301 * cs_dsp_chunk_read() - Parse data from a DSP memory chunk
3305 * This function sequentially reads values from a DSP memory formatted buffer,
3342 MODULE_DESCRIPTION("Cirrus Logic DSP Support");