sound/soc/codecs/tas2783-sdw.c | 54 +++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 23 deletions(-)
Currently, the firmware download is unnecessarily triggered on every
system resume from suspend, causing significant wake-up latency. However,
this step is redundant if the AMP remains powered on. Furthermore, certain
memory pages (addresses > 0xc60000) are skipped even after an AMP reset.
Signed-off-by: Baojun Xu <baojun.xu@ti.com>
---
sound/soc/codecs/tas2783-sdw.c | 54 +++++++++++++++++++---------------
1 file changed, 31 insertions(+), 23 deletions(-)
diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c
index c217da5fccdf..fa206344dcde 100644
--- a/sound/soc/codecs/tas2783-sdw.c
+++ b/sound/soc/codecs/tas2783-sdw.c
@@ -97,6 +97,7 @@ struct tas2783_prv {
u8 rca_binaryname[64];
u8 dev_name[32];
bool hw_init;
+ bool first_hw_init;
/* wq for firmware download */
wait_queue_head_t fw_wait;
bool fw_dl_task_done;
@@ -782,15 +783,16 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
file->vendor_id, file->file_id,
file->version, file->length,
file->dest_addr, file->fw_data);
-
- 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: %d", ret);
- break;
+ if (!tas_dev->first_hw_init || file->dest_addr < 0xc60000) {
+ 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: %d", ret);
+ break;
+ }
}
cur_file++;
}
@@ -801,6 +803,10 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
ret = -EINVAL;
} else {
tas2783_update_calibdata(tas_dev);
+ /* Mark the AMP firmware download as complete. */
+ regmap_write(tas_dev->regmap, TASDEV_REG_SDW(0, 0, 0x07),
+ 0x22);
+ tas_dev->first_hw_init = true;
}
out:
@@ -1102,7 +1108,6 @@ static s32 tas2783_sdca_dev_resume(struct device *dev)
regcache_mark_dirty(tas_dev->regmap);
return ret;
}
-
return 0;
}
@@ -1171,25 +1176,28 @@ static s32 tas_fw_load(struct tas2783_prv *tas_dev, struct sdw_slave *slave)
static s32 tas_io_init(struct device *dev, struct sdw_slave *slave)
{
struct tas2783_prv *tas_dev = dev_get_drvdata(dev);
- s32 ret;
+ s32 ret, val;
if (tas_dev->hw_init)
return 0;
+ regmap_read(tas_dev->regmap, TASDEV_REG_SDW(0, 0, 0x07), &val);
+ /* Check if the AMP is in reset status. */
+ if (val == 0x20) {
- tas_dev->fw_dl_success = false;
+ tas_dev->fw_dl_success = false;
- ret = regmap_write(tas_dev->regmap, TAS2783_SW_RESET, 0x1);
- if (ret) {
- dev_err(dev, "sw reset failed, err=%d", ret);
- return ret;
- }
- usleep_range(2000, 2200);
+ ret = regmap_write(tas_dev->regmap, TAS2783_SW_RESET, 0x1);
+ if (ret) {
+ dev_err(dev, "sw reset failed, err=%d", ret);
+ return ret;
+ }
+ usleep_range(2000, 2200);
- tas_dev->fw_use_fallback = false;
- ret = tas_fw_load(tas_dev, slave);
- if (!ret && tas_dev->fw_use_fallback)
+ tas_dev->fw_use_fallback = false;
ret = tas_fw_load(tas_dev, slave);
-
+ if (!ret && tas_dev->fw_use_fallback)
+ ret = tas_fw_load(tas_dev, slave);
+ }
if (!ret) {
if (tas_dev->sa_func_data)
ret = sdca_regmap_write_init(dev, tas_dev->regmap,
@@ -1197,7 +1205,6 @@ static s32 tas_io_init(struct device *dev, struct sdw_slave *slave)
else
ret = regmap_multi_reg_write(tas_dev->regmap, tas2783_init_seq,
ARRAY_SIZE(tas2783_init_seq));
-
if (ret)
dev_err(tas_dev->dev,
"init writes failed, err=%d", ret);
@@ -1357,6 +1364,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->first_hw_init = false;
mutex_init(&tas_dev->calib_lock);
mutex_init(&tas_dev->pde_lock);
--
2.25.1
On Wed, Aug 12, 2026 at 01:21:24PM +0800, Baojun Xu wrote:
> Currently, the firmware download is unnecessarily triggered on every
> system resume from suspend, causing significant wake-up latency. However,
> this step is redundant if the AMP remains powered on. Furthermore, certain
> memory pages (addresses > 0xc60000) are skipped even after an AMP reset.
...
> } else {
> tas2783_update_calibdata(tas_dev);
> + /* Mark the AMP firmware download as complete. */
> + regmap_write(tas_dev->regmap, TASDEV_REG_SDW(0, 0, 0x07),
> + 0x22);
Make it a single line.
> + tas_dev->first_hw_init = true;
> }
...
> @@ -1102,7 +1108,6 @@ static s32 tas2783_sdca_dev_resume(struct device *dev)
> regcache_mark_dirty(tas_dev->regmap);
> return ret;
> }
> -
> return 0;
> }
Stray change.
...
> static s32 tas_io_init(struct device *dev, struct sdw_slave *slave)
> {
> struct tas2783_prv *tas_dev = dev_get_drvdata(dev);
> - s32 ret;
> + s32 ret, val;
Why is 'val' signed? It should be unsigned int (which is what API requires).
...
> - usleep_range(2000, 2200);
> + usleep_range(2000, 2200);
While at it, replace with fsleep().
--
With Best Regards,
Andy Shevchenko
© 2016 - 2026 Red Hat, Inc.