Re: [PATCH v2] ALSA: hda/tas2781: Enable bass speakers support
From: Gergo Koteles
Date: Sun Oct 11 2026 - 15:23:09 EST
Hi Georg,
On Sun, 2026-10-04 at 09:12 +0200, Georg Wenzel wrote:
> Configure the driver to correctly initialize and enable the bass speakers
> on devices utilizing the TAS2781 amplifier. Without this change, only the
> tweeters or main speakers are active, leading to thin audio output.
>
> Set up the required register sequences and routing to ensure the bass
> channels are properly powered and mixed into the audio stream.
>
> Signed-off-by: Georg Wenzel <g.wenzel@xxxxxxxxx>
> ---
> v2:
> - Rebased onto sound/for-next (Takashi Iwai).
> - Removed non-ASCII characters in comments (Takashi Iwai).
>
> include/sound/tas2781.h | 12 +++
> .../hda/codecs/side-codecs/tas2781_hda_i2c.c | 98 +++++++++++++++++++
> 2 files changed, 110 insertions(+)
>
> diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h
> index b763da613769..ccc0142fbad5 100644
> --- a/include/sound/tas2781.h
> +++ b/include/sound/tas2781.h
> @@ -91,6 +91,18 @@
> /* prm_TE_1_Beta1 */
> #define TAS2563_TE_DT_REG TASDEVICE_REG(0x00, 0x0f, 0x70)
>
> +/* TAS2563 ASI (Audio Serial Interface) Register Definitions */
> +#define TAS2563_ASI_CFG_REG TASDEVICE_REG(0x00, 0x00, 0x06)
> +#define TAS2563_ASI_SR_REG TASDEVICE_REG(0x00, 0x00, 0x07)
> +#define TAS2563_ASI_FS_REG TASDEVICE_REG(0x00, 0x00, 0x08)
> +#define TAS2563_ASI_DA_REG TASDEVICE_REG(0x00, 0x00, 0x0a)
> +#define TAS2563_ASI_TDM_REG TASDEVICE_REG(0x00, 0x00, 0x0b)
> +#define TAS2563_ASI_DL_REG TASDEVICE_REG(0x00, 0x00, 0x0c)
> +#define TAS2563_ASI_SLOT_REG TASDEVICE_REG(0x00, 0x00, 0x30)
> +
> +/* TAS2563 ASI Apply Register (triggers configuration update) */
> +#define TAS2563_ASI_APPLY_REG TASDEVICE_REG(0x00, 0x00, 0x02)
> +
> #define TAS2781_PRM_INT_MASK_REG TASDEVICE_REG(0x00, 0x00, 0x3b)
> #define TAS2781_PRM_CLK_CFG_REG TASDEVICE_REG(0x00, 0x00, 0x5c)
> #define TAS2781_PRM_RSVD_REG TASDEVICE_REG(0x00, 0x01, 0x19)
> diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
> index 5e5f46c9fb6b..cef33159eba4 100644
> --- a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
> +++ b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
> @@ -46,6 +46,83 @@
> #define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14)
> #define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34)
>
> +/*
> + * TAS2563 Post-Firmware ASI Configuration.
> + *
> + * The DSP firmware loading can overwrite the ASI (Audio Serial Interface)
> + * registers that configure the I2S/TDM audio path to the amplifier.
> + * This function re-applies the correct ASI configuration after firmware load,
> + * matching the reference initialization sequence used by the vendor script:
> + * - Software reset
> + * - ASI_CFG = 0x09 (I2S mode, master/slave config)
> + * - ASI_SR = 0x02 (sample rate divider for 48 kHz)
> + * - ASI_DA = 0xf1 (data alignment / slot assignment)
> + * - ASI_TDM = 0x02 (TDM mode select)
> + * - ASI_DL = 0x00 (delay line off)
> + * - ASI_SLOT = 0x99 (slot enable mask for 2-channel stereo)
> + * - CHNL_0 = 0x02 (channel mapping)
> + * - ASI_FS = 0x1e or 0x2e (frame sync, device-specific: bit4 selects
> + * which of the two devices is the "primary" for FS generation)
> + * - ASI_APPLY= 0x00 (trigger configuration update)
> + */
> +static void tas2563_post_fw_init(struct tasdevice_priv *tas_priv)
> +{
> + int i, ret;
> +
> + dev_info(tas_priv->dev, "%s: ndev=%d, chip_id=%d\n",
> + __func__, tas_priv->ndev, tas_priv->chip_id);
> +
> + for (i = 0; i < tas_priv->ndev; i++) {
> + struct tasdevice *tasdev = &tas_priv->tasdevice[i];
> + u8 fs_val;
> +
> + dev_info(tas_priv->dev,
> + "%s: device[%d] dev_addr=0x%02x\n",
> + __func__, i, tasdev->dev_addr);
> +
> + /* Step 1: Software reset (matches script: 0x01 = 0x01) */
> + ret = tasdevice_dev_write(tas_priv, i, TASDEVICE_REG_SWRESET,
> + TASDEVICE_REG_SWRESET_RESET);
> + dev_info(tas_priv->dev,
> + "%s: chn=%d SWRESET ret=%d\n", __func__, i, ret);
> + usleep_range(1000, 2000);
According the 7.5.3 in the tas2563.pdf, this will place all register
values in their default POR (Power on Reset) state.
So this resets all registers set by the firmware before.
Why is this necessary? Should that vendor script run here?
I have TAS2563s in my Lenovo 14ARB7 and they work fine already.
You wrote that it worked well with 6.16.
Could you bisect the culprit commit instead?
Based on your dmesg something else can be wrong:
snd_hda_codec_alc269 hdaudioC1D0: bound i2c-INT8866:00 (ops
tas2781_hda_i2c_driver_exit [snd_hda_scodec_tas2781_i2c])
This sould be:
snd_hda_codec_alc269 hdaudioC1D0: bound i2c-INT8866:00 (ops
tas2781_hda_comp_ops [snd_hda_scodec_tas2781_i2c])
> +
> + /* Step 2: ASI configuration registers */
> + ret = tasdevice_dev_write(tas_priv, i, TAS2563_ASI_CFG_REG, 0x09);
> + dev_info(tas_priv->dev, "%s: chn=%d ASI_CFG=0x09 ret=%d\n", __func__, i, ret);
> +
> + ret = tasdevice_dev_write(tas_priv, i, TAS2563_ASI_SR_REG, 0x02);
> + dev_info(tas_priv->dev, "%s: chn=%d ASI_SR=0x02 ret=%d\n", __func__, i, ret);
> +
> + ret = tasdevice_dev_write(tas_priv, i, TAS2563_ASI_DA_REG, 0xf1);
> + dev_info(tas_priv->dev, "%s: chn=%d ASI_DA=0xf1 ret=%d\n", __func__, i, ret);
> +
> + ret = tasdevice_dev_write(tas_priv, i, TAS2563_ASI_TDM_REG, 0x02);
> + dev_info(tas_priv->dev, "%s: chn=%d ASI_TDM=0x02 ret=%d\n", __func__, i, ret);
> +
> + ret = tasdevice_dev_write(tas_priv, i, TAS2563_ASI_DL_REG, 0x00);
> + dev_info(tas_priv->dev, "%s: chn=%d ASI_DL=0x00 ret=%d\n", __func__, i, ret);
> +
> + ret = tasdevice_dev_write(tas_priv, i, TAS2563_ASI_SLOT_REG, 0x99);
> + dev_info(tas_priv->dev, "%s: chn=%d ASI_SLOT=0x99 ret=%d\n", __func__, i, ret);
> +
> + ret = tasdevice_dev_write(tas_priv, i, TAS2781_PRM_CHNL_0_REG, 0x02);
> + dev_info(tas_priv->dev, "%s: chn=%d CHNL_0=0x02 ret=%d\n", __func__, i, ret);
> +
TAS2781_PRM_CHNL_0_REG is misleading.
It is TASDEVICE_REG(0x00, 0x00, 0x03) which is the PB_CFG1 on the
TAS2563.
Writing 0x02 into sets the AMP_LEVEL to the minimum.
AMP_LEVEL=0x01 -> 8.5 dBV (3.76Vpk).
The default is 0x20 for this register.
AMP_LEVEL=0x10 -> 16.0 dBV (8.92Vpk).
Why should it be quieter?
Thanks,
Gergo