[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250810122358.1575-1-baojun.xu@ti.com>
Date: Sun, 10 Aug 2025 20:23:58 +0800
From: Baojun Xu <baojun.xu@...com>
To: <tiwai@...e.de>
CC: <broonie@...nel.org>, <andriy.shevchenko@...ux.intel.com>,
<alsa-devel@...a-project.org>, <shenghao-ding@...com>,
<13916275206@....com>, <linux-sound@...r.kernel.org>,
<linux-kernel@...r.kernel.org>, <baojun.xu@...com>
Subject: [PATCH v1] ALSA: hda: Add TAS5825 support
Add TAS5825 support in TI's HDA driver.
TAS5825 is an on-chip DSP, but no calibration is required,
and no global address support smart amplifier devices.
Signed-off-by: Baojun Xu <baojun.xu@...com>
---
include/sound/tas2781-dsp.h | 3 +
include/sound/tas2781.h | 4 +-
include/sound/tas5825-tlv.h | 24 +++++++
.../hda/codecs/side-codecs/tas2781_hda_i2c.c | 28 ++++++++
sound/soc/codecs/tas2781-fmwlib.c | 67 ++++++++++++++++++-
5 files changed, 121 insertions(+), 5 deletions(-)
create mode 100644 include/sound/tas5825-tlv.h
diff --git a/include/sound/tas2781-dsp.h b/include/sound/tas2781-dsp.h
index c3a9efa73d5d..49bbf24d6559 100644
--- a/include/sound/tas2781-dsp.h
+++ b/include/sound/tas2781-dsp.h
@@ -34,6 +34,7 @@
#define PPC3_VERSION_TAS2781_BASIC_MIN 0x14600
#define PPC3_VERSION_TAS2781_ALPHA_MIN 0x4a00
#define PPC3_VERSION_TAS2781_BETA_MIN 0x19400
+#define PPC3_VERSION_TAS5825_BASE 0x114200
#define TASDEVICE_DEVICE_SUM 8
#define TASDEVICE_CONFIG_SUM 64
@@ -53,6 +54,8 @@ enum tasdevice_dsp_dev_idx {
TASDEVICE_DSP_TAS_2781_DUAL_MONO,
TASDEVICE_DSP_TAS_2781_21,
TASDEVICE_DSP_TAS_2781_QUAD,
+ TASDEVICE_DSP_TAS_5825_MONO,
+ TASDEVICE_DSP_TAS_5825_DUAL,
TASDEVICE_DSP_TAS_MAX_DEVICE
};
diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h
index 3875e92f1ec5..f0aefc04a957 100644
--- a/include/sound/tas2781.h
+++ b/include/sound/tas2781.h
@@ -49,9 +49,9 @@
#define TASDEVICE_REG(book, page, reg) (((book * 256 * 128) + \
(page * 128)) + reg)
-/* Software Reset */
+/* Software Reset, compatble with new device (TAS5825). */
#define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0x0, 0x01)
-#define TASDEVICE_REG_SWRESET_RESET BIT(0)
+#define TASDEVICE_REG_SWRESET_RESET (BIT(0) | BIT(4))
/* Checksum */
#define TASDEVICE_CHECKSUM_REG TASDEVICE_REG(0x0, 0x0, 0x7e)
diff --git a/include/sound/tas5825-tlv.h b/include/sound/tas5825-tlv.h
new file mode 100644
index 000000000000..95f2d3fad120
--- /dev/null
+++ b/include/sound/tas5825-tlv.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+//
+// ALSA SoC Texas Instruments TAS5825 Audio Smart Amplifier
+//
+// Copyright (C) 2025 Texas Instruments Incorporated
+// https://www.ti.com
+//
+// The TAS5825 hda driver implements for one or two TAS5825 chips.
+//
+// Author: Baojun Xu <baojun.xu@...com>
+//
+
+#ifndef __TAS5825_TLV_H__
+#define __TAS5825_TLV_H__
+
+#define TAS5825_DVC_LEVEL TASDEVICE_REG(0x0, 0x0, 0x4c)
+#define TAS5825_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x54)
+
+static const __maybe_unused DECLARE_TLV_DB_SCALE(
+ tas5825_dvc_tlv, -10300, 50, 0);
+static const __maybe_unused DECLARE_TLV_DB_SCALE(
+ tas5825_amp_tlv, -1550, 50, 0);
+
+#endif
diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
index 45ac5e41bd4f..71ee946eb748 100644
--- a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
+++ b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
@@ -26,6 +26,7 @@
#include <sound/tlv.h>
#include <sound/tas2770-tlv.h>
#include <sound/tas2781-tlv.h>
+#include <sound/tas5825-tlv.h>
#include "hda_local.h"
#include "hda_auto_parser.h"
@@ -50,6 +51,7 @@ enum device_chip_id {
HDA_TAS2563,
HDA_TAS2770,
HDA_TAS2781,
+ HDA_TAS5825,
HDA_OTHERS
};
@@ -272,6 +274,17 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = {
tas2781_force_fwload_get, tas2781_force_fwload_put),
};
+static const struct snd_kcontrol_new tas5825_snd_controls[] = {
+ ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS5825_AMP_LEVEL,
+ 0, 0, 31, 1, tas2781_amp_getvol,
+ tas2781_amp_putvol, tas5825_amp_tlv),
+ ACARD_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS5825_DVC_LEVEL,
+ 0, 0, 254, 1, tas2781_amp_getvol,
+ tas2781_amp_putvol, tas5825_dvc_tlv),
+ ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,
+ tas2781_force_fwload_get, tas2781_force_fwload_put),
+};
+
static const struct snd_kcontrol_new tasdevice_prof_ctrl = {
.name = "Speaker Profile Id",
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
@@ -501,6 +514,12 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
ARRAY_SIZE(tas2781_snd_controls));
tasdevice_dspfw_init(context);
break;
+ case HDA_TAS5825:
+ tasdev_add_kcontrols(tas_priv, hda_priv->snd_ctls, codec,
+ &tas5825_snd_controls[0],
+ ARRAY_SIZE(tas5825_snd_controls));
+ tasdevice_dspfw_init(context);
+ break;
case HDA_TAS2563:
tasdevice_dspfw_init(context);
break;
@@ -628,6 +647,7 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
} else if (strstarts(dev_name(&clt->dev),
"i2c-TXNW2781:00-tas2781-hda.0")) {
device_name = "TXNW2781";
+ hda_priv->hda_chip_id = HDA_TAS2781;
hda_priv->save_calibration = tas2781_save_calibration;
tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR;
} else if (strstr(dev_name(&clt->dev), "INT8866")) {
@@ -639,6 +659,13 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
hda_priv->hda_chip_id = HDA_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")) {
+ /*
+ * TAS5825, integrated on-chip DSP without
+ * global I2C address and calibration supported.
+ */
+ device_name = "TXNW5825";
+ hda_priv->hda_chip_id = HDA_TAS5825;
} else {
return -ENODEV;
}
@@ -775,6 +802,7 @@ static const struct acpi_device_id tas2781_acpi_hda_match[] = {
{"TIAS2781", 0 },
{"TXNW2770", 0 },
{"TXNW2781", 0 },
+ {"TXNW5825", 0 },
{}
};
MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match);
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index c9c1e608ddb7..d69faef8a4d7 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -91,7 +91,7 @@ struct blktyp_devidx_map {
};
static const char deviceNumber[TASDEVICE_DSP_TAS_MAX_DEVICE] = {
- 1, 2, 1, 2, 1, 1, 0, 2, 4, 3, 1, 2, 3, 4
+ 1, 2, 1, 2, 1, 1, 0, 2, 4, 3, 1, 2, 3, 4, 1, 2
};
/* fixed m68k compiling issue: mapping table can save code field */
@@ -509,6 +509,56 @@ static int fw_parse_data_kernel(struct tasdevice_fw *tas_fmw,
return offset;
}
+static int fw_parse_tas5825_program_data_kernel(
+ struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw,
+ const struct firmware *fmw, int offset)
+{
+ struct tasdevice_prog *program;
+ unsigned int i;
+
+ for (i = 0; i < tas_fmw->nr_programs; i++) {
+ program = &(tas_fmw->programs[i]);
+ if (offset + 72 > fmw->size) {
+ dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
+ return -EINVAL;
+ }
+ /* Skip 65 unused byts*/
+ offset += 65;
+ offset = fw_parse_data_kernel(tas_fmw, &(program->dev_data),
+ fmw, offset);
+ if (offset < 0)
+ return offset;
+ }
+
+ return offset;
+}
+
+static int fw_parse_tas5825_configuration_data_kernel(
+ struct tasdevice_priv *tas_priv,
+ struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
+{
+ const unsigned char *data = fmw->data;
+ struct tasdevice_config *config;
+ unsigned int i;
+
+ for (i = 0; i < tas_fmw->nr_configurations; i++) {
+ config = &(tas_fmw->configs[i]);
+ if (offset + 80 > fmw->size) {
+ dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
+ return -EINVAL;
+ }
+ memcpy(config->name, &data[offset], 64);
+ /* Skip extra 8 bytes*/
+ offset += 72;
+ offset = fw_parse_data_kernel(tas_fmw, &(config->dev_data),
+ fmw, offset);
+ if (offset < 0)
+ return offset;
+ }
+
+ return offset;
+}
+
static int fw_parse_program_data_kernel(
struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw,
const struct firmware *fmw, int offset)
@@ -1826,7 +1876,8 @@ static void dspbin_type_check(struct tasdevice_priv *tas_priv,
else
tas_priv->dspbin_typ = TASDEV_ALPHA;
}
- if (tas_priv->dspbin_typ != TASDEV_BASIC)
+ if ((tas_priv->dspbin_typ != TASDEV_BASIC) &&
+ (ppcver < PPC3_VERSION_TAS5825_BASE))
tas_priv->fw_parse_fct_param_address =
fw_parse_fct_param_address;
}
@@ -1837,7 +1888,17 @@ static int dspfw_default_callback(struct tasdevice_priv *tas_priv,
int rc = 0;
if (drv_ver == 0x100) {
- if (ppcver >= PPC3_VERSION_BASE) {
+ if (ppcver >= PPC3_VERSION_TAS5825_BASE) {
+ tas_priv->fw_parse_variable_header =
+ fw_parse_variable_header_kernel;
+ tas_priv->fw_parse_program_data =
+ fw_parse_tas5825_program_data_kernel;
+ tas_priv->fw_parse_configuration_data =
+ fw_parse_tas5825_configuration_data_kernel;
+ tas_priv->tasdevice_load_block =
+ tasdevice_load_block_kernel;
+ dspbin_type_check(tas_priv, ppcver);
+ } else if (ppcver >= PPC3_VERSION_BASE) {
tas_priv->fw_parse_variable_header =
fw_parse_variable_header_kernel;
tas_priv->fw_parse_program_data =
--
2.43.0
Powered by blists - more mailing lists