[SRU][R][PATCH 1/1] ASoC: tas2783-sdw: add firmware download status check
Chris Chiu
chris.chiu at canonical.com
Tue Oct 13 03:54:04 UTC 2026
From: Baojun Xu <baojun.xu at ti.com>
BugLink: https://bugs.launchpad.net/bugs/2169023
Currently, firmware download during system resume from suspend introduces
significant wake-up latency. However, since PRAM content in the AMP
persists across resets and is not erased, this step can be optimized.
By verifying that the firmware version read from registers matches the
expected value, we can confirm that memory content was retained.
Consequently, the PRAM download can be skipped, significantly reducing
resume latency.
Signed-off-by: Baojun Xu <baojun.xu at ti.com>
Link: https://patch.msgid.link/20260921111930.1040-1-baojun.xu@ti.com
Signed-off-by: Mark Brown <broonie at kernel.org>
(backported from commit f42fbd560cd834c7d10118743683def979c68739 linux-next)
[ChrisChiu: the content of dependency commit 173cb3147ba2 is not required]
Signed-off-by: Chris Chiu <chris.chiu at canonical.com>
---
sound/soc/codecs/tas2783-sdw.c | 46 ++++++++++++++++++++++++++++++----
sound/soc/codecs/tas2783.h | 4 ++-
2 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c
index 66f9a51c00b0..aea15f5a1cf1 100644
--- a/sound/soc/codecs/tas2783-sdw.c
+++ b/sound/soc/codecs/tas2783-sdw.c
@@ -96,6 +96,7 @@ struct tas2783_prv {
u8 rca_binaryname[64];
u8 dev_name[32];
bool hw_init;
+ unsigned int fw_version;
/* wq for firmware download */
wait_queue_head_t fw_wait;
bool fw_dl_task_done;
@@ -343,8 +344,10 @@ static int tas2783_sdca_mbq_size(struct device *dev, u32 reg)
case 0x300 ... 0x340: /* Data port 3. */
case 0x400 ... 0x440: /* Data port 4. */
case 0x500 ... 0x540: /* Data port 5. */
- case 0x800000 ... 0x803fff: /* Page 0 ~ 127. */
- case 0x807e80 ... 0x807eff: /* Page 253. */
+ case TASDEV_REG_SDW(0, 0, 0) ... TASDEV_REG_SDW(0x00, 0x01, 0x80):
+ case TASDEV_REG_SDW(0, 0xfd, 0) ... TASDEV_REG_SDW(0, 0xfd, 0x80):
+ case PRAM_ADDR_START ... PRAM_ADDR_END:
+ case YRAM_ADDR_START ... YRAM_ADDR_END:
case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_UDMPU23,
TAS2783_SDCA_CTL_UDMPU_CLUSTER, 0):
case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, TAS2783_SDCA_CTL_FU_MUTE,
@@ -516,7 +519,7 @@ static const struct regmap_config tas_regmap = {
.volatile_reg = tas2783_volatile_register,
.reg_defaults = tas2783_reg_default,
.num_reg_defaults = ARRAY_SIZE(tas2783_reg_default),
- .max_register = 0x41008000 + TASDEV_REG_SDW(0xa1, 0x60, 0x7f),
+ .max_register = 0x41000000 + PRAM_ADDR_END,
.cache_type = REGCACHE_MAPLE,
.use_single_read = true,
.use_single_write = true,
@@ -731,6 +734,7 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
const u8 *buf = NULL;
s32 img_sz, ret = 0, cur_file = 0;
s32 offset = 0;
+ u32 val[4], fw_version;
struct tas_fw_hdr *hdr __free(kfree) = kzalloc_obj(*hdr);
struct tas_fw_file *file __free(kfree) = kzalloc_obj(*file);
@@ -764,6 +768,11 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
}
mutex_lock(&tas_dev->pde_lock);
+ ret = regmap_bulk_read(tas_dev->regmap, TAS2783_FW_VERSION, &val, 4);
+ fw_version = (val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3];
+ dev_dbg(tas_dev->dev, "Get Firmware version: %08x == %08x?, err=%d",
+ fw_version, tas_dev->fw_version, ret);
+
while (offset < (img_sz - FW_FL_HDR)) {
offset += tas_fw_get_next_file(&buf[offset], file);
dev_dbg(tas_dev->dev,
@@ -772,6 +781,13 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
file->version, file->length,
file->dest_addr, file->fw_data);
+ if (tas_dev->fw_version == fw_version &&
+ file->dest_addr >= PRAM_ADDR_START &&
+ (file->dest_addr + file->length) <= PRAM_ADDR_END) {
+ cur_file++;
+ dev_dbg(tas_dev->dev, "Ignore PRAM block");
+ continue;
+ }
ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral,
file->dest_addr,
file->length,
@@ -779,17 +795,34 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
if (ret < 0) {
dev_err(tas_dev->dev,
"FW download failed: %d", ret);
- break;
+ /*
+ * We do retry here for some special case of download
+ * failed after Power-On.
+ */
+ ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral,
+ file->dest_addr,
+ file->length,
+ file->fw_data);
+ if (ret < 0) {
+ dev_err(tas_dev->dev,
+ "FW download failed again: %d", ret);
+ break;
+ }
}
cur_file++;
}
mutex_unlock(&tas_dev->pde_lock);
+ regcache_drop_region(tas_dev->regmap, 0, UINT_MAX);
if (cur_file == 0) {
dev_err(tas_dev->dev, "fw with no files");
ret = -EINVAL;
} else {
tas2783_update_calibdata(tas_dev);
+ ret = regmap_bulk_read(tas_dev->regmap, TAS2783_FW_VERSION,
+ &val, 4);
+ tas_dev->fw_version = (val[0] << 24) | (val[1] << 16) |
+ (val[2] << 8) | val[3];
}
out:
@@ -1032,7 +1065,7 @@ static const struct snd_soc_component_driver soc_codec_driver_tasdevice = {
.num_dapm_widgets = ARRAY_SIZE(tas_dapm_widgets),
.dapm_routes = tas_audio_map,
.num_dapm_routes = ARRAY_SIZE(tas_audio_map),
- .idle_bias_on = 1,
+ .idle_bias_on = 0,
.endianness = 1,
};
@@ -1173,6 +1206,8 @@ static s32 tas_io_init(struct device *dev, struct sdw_slave *slave)
ret = regmap_multi_reg_write(tas_dev->regmap, tas2783_init_seq,
ARRAY_SIZE(tas2783_init_seq));
+ /* Re-active AMP after resume. */
+ regmap_write(tas_dev->regmap, TASDEV_REG_SDW(0, 0, 2), 0);
if (ret)
dev_err(tas_dev->dev,
"init writes failed, err=%d", ret);
@@ -1332,6 +1367,7 @@ static s32 tas_sdw_probe(struct sdw_slave *peripheral,
tas_dev->dev = dev;
tas_dev->sdw_peripheral = peripheral;
tas_dev->hw_init = false;
+ tas_dev->fw_version = 0;
mutex_init(&tas_dev->calib_lock);
mutex_init(&tas_dev->pde_lock);
diff --git a/sound/soc/codecs/tas2783.h b/sound/soc/codecs/tas2783.h
index bf34319c9a9f..d0fb6cb08bec 100644
--- a/sound/soc/codecs/tas2783.h
+++ b/sound/soc/codecs/tas2783.h
@@ -35,10 +35,12 @@
#define TAS2783_AMP_LEVEL_MASK GENMASK(5, 1)
#define PRAM_ADDR_START TASDEV_REG_SDW(0x8c, 0x01, 0x8)
-#define PRAM_ADDR_END TASDEV_REG_SDW(0x8c, 0xff, 0x7f)
+#define PRAM_ADDR_END TASDEV_REG_SDW(0x8c, 0xff, 0x80)
#define YRAM_ADDR_START TASDEV_REG_SDW(0x00, 0x02, 0x8)
#define YRAM_ADDR_END TASDEV_REG_SDW(0x00, 0x37, 0x7f)
+#define TAS2783_FW_VERSION TASDEV_REG_SDW(0x00, 0x20, 0x3c)
+
/* Calibration data */
#define TAS2783_CAL_R0 TASDEV_REG_SDW(0, 0x16, 0x4C)
#define TAS2783_CAL_INVR0 TASDEV_REG_SDW(0, 0x16, 0x5C)
--
2.43.0
More information about the kernel-team
mailing list