[PATCH v3] ASoC: tas2783-sdw: add firmware download status check
Baojun Xu <[email protected]>
| Newsgroups | org.kernel.vger.linux-sound,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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. Signed-off-by: Baojun Xu <[email protected]> --- v3: - Updated description about memory page download reduce. - Removed the logic that skips memory page downloads. v2: - Update register address from 0x07 to 7 and keep the line within the 80-character limit. - Remove stray/unnecessary changes. - Change variable type to unsigned int to comply with API requirements. - Replace usleep_range() with fsleep(). - Set idle_bias_on to 0 to enable low-power mode. - Reactivate the AMP after resume. --- sound/soc/codecs/tas2783-sdw.c | 36 ++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c index eaebb0ebbe0d..2561bbc7823b 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; @@ -852,6 +853,8 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context) ret = -EINVAL; } else { tas2783_update_calibdata(tas_dev); + regmap_write(tas_dev->regmap, TASDEV_REG_SDW(0, 0, 7), 0x22); + tas_dev->first_hw_init = true; } out: @@ -991,7 +994,7 @@ static s32 tas_sdw_hw_params(struct snd_pcm_substream *substream, TAS2783_SDCA_POW_STATE_ON); if (!ret) break; - usleep_range(2000, 2200); + fsleep(2200); } while (retry--); } @@ -1089,7 +1092,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, }; @@ -1222,25 +1225,29 @@ 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); + unsigned int val; s32 ret; if (tas_dev->hw_init) return 0; - tas_dev->fw_dl_success = false; + regmap_read(tas_dev->regmap, TASDEV_REG_SDW(0, 0, 7), &val); + /* Check if the AMP is in reset status. */ + if (val == 0x20) { + 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; + } + fsleep(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, @@ -1249,6 +1256,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); @@ -1428,6 +1437,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