Linux Sound subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Roman Maidanovych" <devuarpd@gmail.com>
Cc: linux-sound@vger.kernel.org
Subject: Re: [PATCH RFC] ALSA: hda/tas2781: Reload DSP program if the amplifiers lost it
Date: Sat, 31 Oct 2026 23:29:34 +0000	[thread overview]
Message-ID: <sashiko-outbox-192221@kernel.org> (raw)
In-Reply-To: <20261101-tas2781-reload-if-lost-v1-1-9d336120f1ba@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] ALSA: hda/tas2781: partial reload in tas2781_hda_reload_if_lost() wipes config
- [Medium] ALSA: hda/tas2781: missing init_profile_id and double load in reload_if_lost()
- [Medium] ALSA: hda/tas2781: missing fw_state check in tas2781_hda_reload_if_lost()
--

commit 74dce121e5a4c4de7e8754632f2407d57f7750d6
Author: Roman Maidanovych <devuarpd@gmail.com>

ALSA: hda/tas2781: Reload DSP program if the amplifiers lost it

This patch checks bit 7 of B0_P0_R0x44 on TAS2781 amplifiers when a PCM stream
is opened and reloads the DSP program if the amplifier lost its program during
HDA codec runtime suspend.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=221735

> diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
> index 44855f593daf8..177a2194aeb70 100644
> --- a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
> +++ b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c

[ ... ]

> @@ -162,6 +165,38 @@ static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid)
>  	return ret;
>  }
>  
> +/*
> + * The amplifiers can lose their DSP program while the HDA codec is runtime
> + * suspended, without the chip being reset. The cached program/configuration
> + * then makes tasdevice_tuning_switch() skip the download and the speakers
> + * stay silent. Bit 7 of B0_P0_R0x44 is set in that state: invalidate the
> + * cache and download the program again.
> + */
> +static void tas2781_hda_reload_if_lost(struct tasdevice_priv *tas_priv)
> +{
> +	bool lost = false;
> +	int i, ret, val;
> +
> +	if (tas_priv->chip_id != TAS2781)
> +		return;

[Severity: Medium]
Should tas2781_hda_reload_if_lost() also check that tas_priv->fw_state is
TASDEVICE_DSP_FW_ALL_OK before checking TAS2781_REG_DSP_LOST and calling
tasdevice_prmg_load()?

In tas2781_hda_bind(), tascodec_init() schedules asynchronous firmware loading
via request_firmware_nowait() and registers comp->playback_hook while
tas_priv->fw_state is still TASDEVICE_DSP_FW_PENDING and tas_priv->fmw is NULL.
Similarly, if tasdevice_dsp_parser() fails in tasdevice_dspfw_init(),
tas_priv->fw_state is set to TASDEVICE_DSP_FW_FAIL without freeing a partially
populated tas_priv->fmw:

sound/hda/codecs/side-codecs/tas2781_hda_i2c.c:tasdevice_dspfw_init() {
	...
	ret = tasdevice_dsp_parser(tas_priv);
	if (ret) {
		dev_err(tas_priv->dev, "dspfw load %s error\n",
			tas_priv->coef_binaryname);
		tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
		return;
	}
}

Previously, tas2781_hda_playback_hook() only called tasdevice_tuning_switch(),
which returns early unless fw_state is TASDEVICE_RCA_FW_OK or
TASDEVICE_DSP_FW_ALL_OK. Without checking fw_state == TASDEVICE_DSP_FW_ALL_OK
here, opening a PCM stream before firmware loading finishes, in RCA-only mode,
or after a DSP firmware parse error can read TAS2781_DSP_LOST as set on the
unprogrammed amplifier and call tasdevice_prmg_load() with NULL or partially
parsed firmware.

> +
> +	for (i = 0; i < tas_priv->ndev; i++) {
> +		ret = tasdevice_dev_read(tas_priv, i, TAS2781_REG_DSP_LOST, &val);
> +		if (ret || !(val & TAS2781_DSP_LOST))
> +			continue;
> +
> +		tas_priv->tasdevice[i].cur_book = -1;
> +		tas_priv->tasdevice[i].cur_prog = -1;
> +		tas_priv->tasdevice[i].cur_conf = -1;
> +		lost = true;
> +	}

[Severity: Medium]
What happens if only a subset of channels have TAS2781_DSP_LOST set (or if
tasdevice_dev_read() fails transiently on one channel while succeeding on
another)?

Earlier calls to tasdevice_select_cfg_blk() leave
tas_priv->tasdevice[chn].is_loading set to true on all channels:

sound/soc/codecs/tas2781-fmwlib.c:tasdevice_select_cfg_blk() {
	...
			for (; chn < chnend; chn++)
				tas_priv->tasdevice[chn].is_loading = true;
	...
}

When tas2781_hda_reload_if_lost() then calls tasdevice_prmg_load(), the loop
only updates channels where cur_prog != prm_no and does not clear is_loading
to false on the remaining channels:

sound/soc/codecs/tas2781-fmwlib.c:tasdevice_prmg_load() {
	...
	for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) {
		if (prm_no >= 0 && tas_priv->tasdevice[i].cur_prog != prm_no) {
			tas_priv->tasdevice[i].cur_conf = -1;
			tas_priv->tasdevice[i].is_loading = true;
			prog_status++;
		}
	}
}

Because is_loading is still true on the non-lost channel,
tasdevice_load_data(tas_priv, &(program->dev_data)) downloads the DSP program
(including its software reset commands) to that channel as well, wiping its
hardware state. However, because cur_conf was never reset to -1 on that
channel, the subsequent tasdevice_tuning_switch() ->
tasdevice_select_tuningprm_cfg() call sees cur_conf == cfg_no and skips
reloading the configuration and calibration data on that channel, leaving it
unconfigured.

> +
> +	if (lost) {
> +		dev_dbg(tas_priv->dev, "DSP program lost, reloading\n");
> +		tasdevice_prmg_load(tas_priv, tas_priv->cur_prog);
> +	}
> +}

[Severity: Medium]
Does reloading the program here miss applying tas_priv->rcabin.init_profile_id,
and can it cause a double program download when force_fwload_status is enabled?

In both tasdevice_dspfw_init() and tas2781_system_resume(), calling
tasdevice_prmg_load() is immediately followed by applying init_profile_id
before tasdevice_tuning_switch():

sound/hda/codecs/side-codecs/tas2781_hda_i2c.c:tas2781_system_resume() {
	...
	tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);

	/* Init common setting for different audio profiles */
	if (tas_hda->priv->rcabin.init_profile_id >= 0)
		tasdevice_select_cfg_blk(tas_hda->priv,
			tas_hda->priv->rcabin.init_profile_id,
			TASDEVICE_BIN_BLK_PRE_POWER_UP);
	...
}

Without that step in tas2781_hda_reload_if_lost(), common profile settings
from init_profile_id are not restored after tasdevice_prmg_load() reloads the
DSP program.

In addition, tasdevice_tuning_switch(tas_hda->priv, 0, false) runs immediately
after tas2781_hda_reload_if_lost() in tas2781_hda_playback_hook() and calls
tasdevice_select_tuningprm_cfg(), which reloads the DSP program whenever
cur_prog != prm_no || tas_priv->force_fwload_status:

sound/soc/codecs/tas2781-fmwlib.c:tasdevice_select_tuningprm_cfg() {
	...
			if (prm_no >= 0
				&& (tas_priv->tasdevice[i].cur_prog != prm_no
				|| tas_priv->force_fwload_status)) {
				tas_priv->tasdevice[i].cur_conf = -1;
				tas_priv->tasdevice[i].is_loading = true;
				prog_status++;
			}
	...
}

If the "Speaker Force Firmware Load" control (force_fwload_status) is enabled,
calling tasdevice_prmg_load() in tas2781_hda_reload_if_lost() and then calling
tasdevice_tuning_switch() will download the full DSP program twice in a row on
PCM open.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261101-tas2781-reload-if-lost-v1-1-9d336120f1ba@gmail.com?part=1

      reply	other threads:[~2026-10-31 23:29 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-31 23:13 [PATCH RFC] ALSA: hda/tas2781: Reload DSP program if the amplifiers lost it Roman Maidanovych via B4 Relay
2026-10-31 23:29 ` sashiko-bot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-192221@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=devuarpd@gmail.com \
    --cc=linux-sound@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox