All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ALSA: hda/tas2781: Enable bass speakers support
@ 2026-09-21 18:18 Georg Wenzel
  2026-09-29  9:39 ` Takashi Iwai
  0 siblings, 1 reply; 6+ messages in thread
From: Georg Wenzel @ 2026-09-21 18:18 UTC (permalink / raw)
  To: shenghao-ding, kevin-lu, baojun.xu, sen
  Cc: perex, tiwai, linux-sound, linux-kernel, Georg Wenzel

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@gmail.com>
---
 include/sound/tas2781.h                       | 12 +++
 .../hda/codecs/side-codecs/tas2781_hda_i2c.c  | 97 +++++++++++++++++++
 2 files changed, 109 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 624db967f17b..101d6cee6da2 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);
+
+		/* 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);
+
+		/* Step 3: Device-specific frame sync (0x1e for dev0, 0x2e for dev1) */
+		fs_val = 0x1e | ((i & 0x01) << 4);
+		ret = tasdevice_dev_write(tas_priv, i, TAS2563_ASI_FS_REG, fs_val);
+		dev_info(tas_priv->dev, "%s: chn=%d ASI_FS=0x%02x ret=%d\n",
+				__func__, i, fs_val, ret);
+
+		/* Step 4: Apply ASI configuration */
+		ret = tasdevice_dev_write(tas_priv, i, TAS2563_ASI_APPLY_REG, 0x00);
+		dev_info(tas_priv->dev, "%s: chn=%d ASI_APPLY ret=%d\n", __func__, i, ret);
+
+		usleep_range(1000, 2000);
+	}
+}
+
 enum device_chip_id {
 	HDA_TAS2563,
 	HDA_TAS2770,
@@ -174,6 +251,12 @@ static void tas2781_hda_playback_hook(struct device *dev, int action)
 		pm_runtime_get_sync(dev);
 		scoped_guard(mutex, &tas_hda->priv->codec_lock) {
 			tasdevice_tuning_switch(tas_hda->priv, 0);
+			/* Re-apply ASI configuration for TAS2563 after
+			 * tuning switch — DSP firmware loading can
+			 * overwrite ASI registers.
+			 */
+			if (tas_hda->priv->chip_id == TAS2563)
+				tas2563_post_fw_init(tas_hda->priv);
 			tas_hda->priv->playback_started = true;
 		}
 		break;
@@ -477,6 +560,12 @@ static void tasdevice_dspfw_init(void *context)
 			tas_priv->rcabin.init_profile_id,
 			TASDEVICE_BIN_BLK_PRE_POWER_UP);
 
+	/* Apply ASI configuration for TAS2563 after firmware load.
+	 * DSP firmware loading can overwrite ASI registers.
+	 */
+	if (tas_hda->priv->chip_id == TAS2563)
+		tas2563_post_fw_init(tas_hda->priv);
+
 	/* If calibrated data occurs error, dsp will still works with default
 	 * calibrated data inside algo.
 	 */
@@ -661,6 +750,7 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
 		 */
 		device_name = "INT8866";
 		hda_priv->hda_chip_id = HDA_TAS2563;
+		tas_hda->priv->chip_id = TAS2563;
 		hda_priv->save_calibration = tas2563_save_calibration;
 		tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR;
 	} else if (strstarts(dev_name(&clt->dev), "i2c-TXNW5825")) {
@@ -784,6 +874,13 @@ static int tas2781_system_resume(struct device *dev)
 			tas_hda->priv->rcabin.init_profile_id,
 			TASDEVICE_BIN_BLK_PRE_POWER_UP);
 
+	/* Re-apply ASI configuration for TAS2563 after system sleep
+	 * resume — amplifiers may lose their register state during
+	 * suspend-to-ram or suspend-to-disk regardless of playback state.
+	 */
+	if (tas_hda->priv->chip_id == TAS2563)
+		tas2563_post_fw_init(tas_hda->priv);
+
 	if (tas_hda->priv->playback_started)
 		tasdevice_tuning_switch(tas_hda->priv, 0);
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] ALSA: hda/tas2781: Enable bass speakers support
  2026-09-21 18:18 [PATCH] ALSA: hda/tas2781: Enable bass speakers support Georg Wenzel
@ 2026-09-29  9:39 ` Takashi Iwai
  2026-10-04  7:12   ` [PATCH v2] " Georg Wenzel
  0 siblings, 1 reply; 6+ messages in thread
From: Takashi Iwai @ 2026-09-29  9:39 UTC (permalink / raw)
  To: Georg Wenzel
  Cc: shenghao-ding, kevin-lu, baojun.xu, sen, perex, tiwai,
	linux-sound, linux-kernel

On Mon, 21 Sep 2026 20:18:44 +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@gmail.com>

The patch doesn't seem applicable to the latest code.
Could you rebase and resubmit?

Also, please avoid non-ASCII letters unless really needed (found in
comments).


thanks,

Takashi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2] ALSA: hda/tas2781: Enable bass speakers support
  2026-09-29  9:39 ` Takashi Iwai
@ 2026-10-04  7:12   ` Georg Wenzel
  2026-10-04 18:39     ` Takashi Iwai
  2026-10-11 19:17     ` Gergo Koteles
  0 siblings, 2 replies; 6+ messages in thread
From: Georg Wenzel @ 2026-10-04  7:12 UTC (permalink / raw)
  To: tiwai; +Cc: alsa-devel, linux-sound, linux-kernel, Georg Wenzel

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@gmail.com>
---
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);
+
+		/* 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);
+
+		/* Step 3: Device-specific frame sync (0x1e for dev0, 0x2e for dev1) */
+		fs_val = 0x1e | ((i & 0x01) << 4);
+		ret = tasdevice_dev_write(tas_priv, i, TAS2563_ASI_FS_REG, fs_val);
+		dev_info(tas_priv->dev, "%s: chn=%d ASI_FS=0x%02x ret=%d\n",
+				__func__, i, fs_val, ret);
+
+		/* Step 4: Apply ASI configuration */
+		ret = tasdevice_dev_write(tas_priv, i, TAS2563_ASI_APPLY_REG, 0x00);
+		dev_info(tas_priv->dev, "%s: chn=%d ASI_APPLY ret=%d\n", __func__, i, ret);
+
+		usleep_range(1000, 2000);
+	}
+}
+
 enum device_chip_id {
 	HDA_TAS2563,
 	HDA_TAS2770,
@@ -172,6 +249,13 @@ static void tas2781_hda_playback_hook(struct device *dev, int action)
 		pm_runtime_get_sync(dev);
 		scoped_guard(mutex, &tas_hda->priv->codec_lock) {
 			tasdevice_tuning_switch(tas_hda->priv, 0, false);
+			/* Re-apply ASI configuration for TAS2563 after
+			 * tuning switch - DSP firmware loading can
+			 * overwrite ASI registers.
+			 */
+			if (tas_hda->priv->chip_id == TAS2563)
+				tas2563_post_fw_init(tas_hda->priv);
+
 			tas_hda->priv->playback_started = true;
 		}
 		break;
@@ -475,6 +559,12 @@ static void tasdevice_dspfw_init(void *context)
 			tas_priv->rcabin.init_profile_id,
 			TASDEVICE_BIN_BLK_PRE_POWER_UP);
 
+	/* Apply ASI configuration for TAS2563 after firmware load.
+	 * DSP firmware loading can overwrite ASI registers.
+	 */
+	if (tas_hda->priv->chip_id == TAS2563)
+		tas2563_post_fw_init(tas_hda->priv);
+
 	/* If calibrated data occurs error, dsp will still works with default
 	 * calibrated data inside algo.
 	 */
@@ -659,6 +749,7 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
 		 */
 		device_name = "INT8866";
 		hda_priv->hda_chip_id = HDA_TAS2563;
+		tas_hda->priv->chip_id = TAS2563;
 		hda_priv->save_calibration = tas2563_save_calibration;
 		tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR;
 	} else if (strstarts(dev_name(&clt->dev), "i2c-TXNW5825")) {
@@ -782,6 +873,13 @@ static int tas2781_system_resume(struct device *dev)
 			tas_hda->priv->rcabin.init_profile_id,
 			TASDEVICE_BIN_BLK_PRE_POWER_UP);
 
+	/* Re-apply ASI configuration for TAS2563 after system sleep
+	 * resume — amplifiers may lose their register state during
+	 * suspend-to-ram or suspend-to-disk regardless of playback state.
+	 */
+	if (tas_hda->priv->chip_id == TAS2563)
+		tas2563_post_fw_init(tas_hda->priv);
+
 	if (tas_hda->priv->playback_started)
 		tasdevice_tuning_switch(tas_hda->priv, 0, false);
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] ALSA: hda/tas2781: Enable bass speakers support
  2026-10-04  7:12   ` [PATCH v2] " Georg Wenzel
@ 2026-10-04 18:39     ` Takashi Iwai
  2026-10-11 19:17     ` Gergo Koteles
  1 sibling, 0 replies; 6+ messages in thread
From: Takashi Iwai @ 2026-10-04 18:39 UTC (permalink / raw)
  To: Georg Wenzel; +Cc: alsa-devel, linux-sound, linux-kernel

On Sun, 04 Oct 2026 09:12:00 +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@gmail.com>

Applied to for-next branch.  Thanks.


Takashi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] ALSA: hda/tas2781: Enable bass speakers support
  2026-10-04  7:12   ` [PATCH v2] " Georg Wenzel
  2026-10-04 18:39     ` Takashi Iwai
@ 2026-10-11 19:17     ` Gergo Koteles
       [not found]       ` <CAKnFnk5ZY1njMkqwLPtOrv817LFfXS7jfh6vaEvqA03s8uorUA@mail.gmail.com>
  1 sibling, 1 reply; 6+ messages in thread
From: Gergo Koteles @ 2026-10-11 19:17 UTC (permalink / raw)
  To: Georg Wenzel, tiwai; +Cc: alsa-devel, linux-sound, linux-kernel

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@gmail.com>
> ---
> 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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] ALSA: hda/tas2781: Enable bass speakers support
       [not found]       ` <CAKnFnk5ZY1njMkqwLPtOrv817LFfXS7jfh6vaEvqA03s8uorUA@mail.gmail.com>
@ 2026-10-12 10:58         ` Gergo Koteles
  0 siblings, 0 replies; 6+ messages in thread
From: Gergo Koteles @ 2026-10-12 10:58 UTC (permalink / raw)
  To: Georg Wenzel; +Cc: tiwai, alsa-devel, linux-sound, linux-kernel

Hi Georg,

On Mon, 2026-10-12 at 10:47 +0200, Georg Wenzel wrote:
> Hi Gergo,
> I'm not very familiar with kernel development.
> My problem is that the subwoofer doesn't work without the patch, but it
> does work with the patch.
> So I figured others might be having the same problem, which is why I
> submitted the patch.
> 

My problem is that this simplifies down the TAS2563 part of the driver
to setting just these few registers, bypassing the firmware and the
machine-specific calibration values.

Could there be a problem with your kernel config or your hardware?
Have you tried it with a distro kernel? If you live boot into a Fedora
it should work.

Best regards,
Gergo

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-10-12 10:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-21 18:18 [PATCH] ALSA: hda/tas2781: Enable bass speakers support Georg Wenzel
2026-09-29  9:39 ` Takashi Iwai
2026-10-04  7:12   ` [PATCH v2] " Georg Wenzel
2026-10-04 18:39     ` Takashi Iwai
2026-10-11 19:17     ` Gergo Koteles
     [not found]       ` <CAKnFnk5ZY1njMkqwLPtOrv817LFfXS7jfh6vaEvqA03s8uorUA@mail.gmail.com>
2026-10-12 10:58         ` Gergo Koteles

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.