From: Shenghao Ding <shenghao-ding@ti.com>
To: <broonie@kernel.org>
Cc: <tiwai@suse.de>, <13916275206@139.com>, <perex@perex.cz>,
<lgirdwood@gmail.com>, <linux-sound@vger.kernel.org>,
<baojun.xu@ti.com>, <k-lu@ti.com>,
Shenghao Ding <shenghao-ding@ti.com>
Subject: [PATCH v3] ASoC: tas2781: Add TAS2573 calibration support
Date: Tue, 15 Sep 2026 12:47:35 +0800 [thread overview]
Message-ID: <20260915044735.1305-1-shenghao-ding@ti.com> (raw)
This patch adds complete calibration workflow support for TAS2573.
Signed-off-by: Shenghao Ding <shenghao-ding@ti.com>
---
v3:
- Our customer requests to follow the feedback from the Linux Community. When there is no
dedicated special configuration for the calibration feature, the corresponding parameter
should be set to -1, so that redundant duplicate configuration work can be completely avoided.
v2:
- Add comments for tasdevice_rca::calibration_profile_id, which is primarily designed for speaker
calibration scenarios with special requirements. For use cases without specific calibration
demands, it can directly reuse the standard music playback configuration, and its default value
is set to 0.
- Correct some logs.
- Use proper kernel error code and WARN_ON_ONCE in the tas2573 calib_start_put control.
v1:
- Add TAS2573 dedicated calibration register definitions
- Extend firmware parser to auto detect and store "calib" tagged profile and config IDs
- Implement TAS2573 calibration start/stop control handlers
- Add dedicated kcontrols for real-time speaker impedance readout and full calibration status dump
- Refactor calibration control creation logic with per-chip switch-case branches for better scalability
- Extend firmware ready check to register TAS2573 calibration controls properly.
---
include/sound/tas2781-dsp.h | 9 +
include/sound/tas2781.h | 24 +++
sound/soc/codecs/tas2781-fmwlib.c | 36 +++-
sound/soc/codecs/tas2781-i2c.c | 320 +++++++++++++++++++++++++++---
4 files changed, 361 insertions(+), 28 deletions(-)
diff --git a/include/sound/tas2781-dsp.h b/include/sound/tas2781-dsp.h
index de087f4ca13f..3380dfd526de 100644
--- a/include/sound/tas2781-dsp.h
+++ b/include/sound/tas2781-dsp.h
@@ -146,6 +146,7 @@ struct tasdevice_fw {
struct tasdevice_calibration *calibrations;
struct fct_param_address fct_par_addr;
struct device *dev;
+ int calibration_config_id;
};
enum tasdevice_fw_state {
@@ -210,6 +211,14 @@ struct tasdevice_rca {
* capture.
*/
int capture_profile_id;
+ /*
+ * Primarily designed for speaker calibration scenarios with special
+ * requirements. For regular use cases, when the default value -1 is
+ * set, calibration will directly reuse the current playback
+ * configuration; non-negative values can be customized for special
+ * calibration demands.
+ */
+ int calibration_profile_id;
/*
* Since version 0x105, the keyword 'init' was introduced into the
* profile, which is used for chip initialization, particularly to
diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h
index b763da613769..7367c76959aa 100644
--- a/include/sound/tas2781.h
+++ b/include/sound/tas2781.h
@@ -91,6 +91,30 @@
/* prm_TE_1_Beta1 */
#define TAS2563_TE_DT_REG TASDEVICE_REG(0x00, 0x0f, 0x70)
+#define TAS2573_FCT_INT_LATCH TASDEVICE_REG(0x00, 0x00, 0x67)
+/* YM57 */
+#define TAS2573_FCT_OUTPUT_R0 TASDEVICE_REG(0x00, 0x65, 0x74)
+/* YM58 */
+#define TAS2573_FCT_OUTPUT_R0_LOW TASDEVICE_REG(0x00, 0x65, 0x78)
+/* YM59 */
+#define TAS2573_FCT_OUTPUT_INV_R0 TASDEVICE_REG(0x00, 0x65, 0x7C)
+/* YM61 */
+#define TAS2573_FCT_OUTPUT_POWERTOT TASDEVICE_REG(0x00, 0x66, 0x0C)
+/* YM64 */
+#define TAS2573_FCT_OUTPUT_F0 TASDEVICE_REG(0x00, 0x65, 0x18)
+/* YM147 */
+#define TAS2573_FCT_STATUS_CTRL TASDEVICE_REG(0x00, 0x68, 0x74)
+/* YM148 */
+#define TAS2573_FCT_STATUS_BINNING TASDEVICE_REG(0x00, 0x68, 0x78)
+/* YM664 */
+#define TAS2573_RE_OUT TASDEVICE_REG(0x00, 0x7A, 0x18)
+/* YM952 */
+#define TAS2573_SILENCE_DETECTED TASDEVICE_REG(0x00, 0x83, 0x60)
+/* YM954 */
+#define TAS2573_OPEN_CIRCUIT TASDEVICE_REG(0x00, 0x83, 0x68)
+/* YM955 */
+#define TAS2573_SHORTCKT TASDEVICE_REG(0x00, 0x83, 0x6C)
+
#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/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index dc1c552206f8..e8ceeb027e1b 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -199,15 +199,22 @@ static struct tasdevice_config_info *tasdevice_add_config(
dev_err(tas_priv->dev, "add conf: Out of boundary\n");
goto out;
}
- /* If in the RCA bin file are several profiles with the
- * keyword "init", init_profile_id only store the last
- * init profile id.
+ /*
+ * If in the RCA bin file are several profiles with the
+ * keyword "init"/"calib", init_profile_id only store the last
+ * init profile id, and same as calibration_profile_id.
*/
if (strnstr(&config_data[config_offset], "init", 64)) {
tas_priv->rcabin.init_profile_id =
tas_priv->rcabin.ncfgs - 1;
dev_dbg(tas_priv->dev, "%s: init profile id = %d\n",
__func__, tas_priv->rcabin.init_profile_id);
+ } else if (strnstr(&config_data[config_offset], "calib", 64)) {
+ tas_priv->rcabin.calibration_profile_id =
+ tas_priv->rcabin.ncfgs - 1;
+ dev_dbg(tas_priv->dev, "%s: calib profile id = %d\n",
+ __func__,
+ tas_priv->rcabin.calibration_profile_id);
}
config_offset += 64;
}
@@ -314,6 +321,7 @@ int tasdevice_rca_parser(void *context, const struct firmware *fmw)
rca = &(tas_priv->rcabin);
/* Initialize to none */
rca->init_profile_id = -1;
+ rca->calibration_profile_id = -1;
fw_hdr = &(rca->fw_hdr);
if (!fmw || !fmw->data) {
dev_err(tas_priv->dev, "Failed to read %s\n",
@@ -632,6 +640,17 @@ static int fw_parse_configuration_data_kernel(
goto out;
}
memcpy(config->name, &data[offset], 64);
+
+ /*
+ * If in the coef bin file are several configs with the
+ * keyword "calib", calibration_config_id only store the last
+ * calibration profile id.
+ */
+ if (strnstr(config->name, "calib", 64)) {
+ tas_fmw->calibration_config_id = i;
+ dev_dbg(tas_priv->dev, "%s: calib cofig = %d\n",
+ __func__, tas_fmw->calibration_config_id);
+ }
/*skip extra 16 bytes*/
offset += 80;
@@ -1412,6 +1431,17 @@ static int fw_parse_configuration_data(
memcpy(config->name, &data[offset], 64);
offset += 64;
+ /*
+ * If in the coef bin file are several configs with the
+ * keyword "calib", calibration_config_id only store the last
+ * calibration profile id.
+ */
+ if (strnstr(config->name, "calib", 64)) {
+ tas_fmw->calibration_config_id = i;
+ dev_dbg(tas_priv->dev, "%s: calib cofig id = %d\n",
+ __func__, tas_fmw->calibration_config_id);
+ }
+
n = tasdevice_fw_strnlen(fmw, offset);
if (n < 0) {
dev_err(tas_priv->dev, "Description err\n");
diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c
index 6f349f88f194..995bfd52f5fc 100644
--- a/sound/soc/codecs/tas2781-i2c.c
+++ b/sound/soc/codecs/tas2781-i2c.c
@@ -613,6 +613,39 @@ static void tas2563_calib_stop_put(struct tasdevice_priv *tas_priv)
}
}
+static void tas2573_calib_stop_put(struct tasdevice_priv *tas_priv)
+{
+ int cal_prof_id = tas_priv->rcabin.calibration_profile_id;
+
+ if (cal_prof_id >= 0)
+ tasdevice_select_cfg_blk(tas_priv, cal_prof_id,
+ TASDEVICE_BIN_BLK_PRE_SHUTDOWN);
+}
+
+static int tas2573_calib_start_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ int cal_prof_id = tas_priv->rcabin.calibration_profile_id;
+ int cal_conf_id = tas_priv->fmw->calibration_config_id;
+
+ guard(mutex)(&tas_priv->codec_lock);
+ if (tas_priv->chip_id != TAS2573) {
+ WARN_ON_ONCE(1);
+ return -ENODEV;
+ }
+
+ if (cal_prof_id >= 0)
+ tasdevice_select_cfg_blk(tas_priv, cal_prof_id,
+ TASDEVICE_BIN_BLK_PRE_POWER_UP);
+
+ tasdevice_select_tuningprm_cfg(tas_priv, tas_priv->cur_prog,
+ cal_conf_id, cal_prof_id);
+
+ return 1;
+}
+
static int tasdev_calib_stop_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -621,10 +654,22 @@ static int tasdev_calib_stop_put(struct snd_kcontrol *kcontrol,
int i;
guard(mutex)(&priv->codec_lock);
- if (priv->chip_id == TAS2563)
+
+ switch (priv->chip_id) {
+ case TAS2563:
tas2563_calib_stop_put(priv);
- else
+ break;
+ case TAS2573:
+ tas2573_calib_stop_put(priv);
+ break;
+ case TAS2781:
tas2781_calib_stop_put(priv);
+ break;
+ default:
+ dev_err(priv->dev, "%s: Chip(%d) unsupports calibration\n",
+ __func__, priv->chip_id);
+ return -1;
+ }
/*
* Set reloading-firmware flag after calibration, the flag will work
@@ -983,6 +1028,13 @@ static const struct snd_kcontrol_new tas2563_cali_controls[] = {
tasdev_nop_get, tas2563_calib_start_put),
};
+static const struct snd_kcontrol_new tas2573_cali_controls[] = {
+ SOC_SINGLE_EXT("Calibration Start", SND_SOC_NOPM, 0, 1, 0,
+ tasdev_nop_get, tas2573_calib_start_put),
+ SOC_SINGLE_EXT("Calibration Stop", SND_SOC_NOPM, 0, 1, 0,
+ tasdev_nop_get, tasdev_calib_stop_put),
+};
+
static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1493,6 +1545,182 @@ static int create_tas2781_cali_start_ktrl(struct tasdevice_priv
return 0;
}
+static int tas2573_re_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct tasdevice_priv *priv = snd_soc_component_get_drvdata(comp);
+ unsigned char *dst = ucontrol->value.bytes.data;
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ unsigned int i = 0;
+ unsigned int j;
+ int rc;
+
+ guard(mutex)(&priv->codec_lock);
+ dst[i++] = bytes_ext->max;
+ dst[i++] = 'r';
+
+ dst[i++] = TASDEVICE_BOOK_ID(TAS2573_RE_OUT);
+ dst[i++] = TASDEVICE_PAGE_ID(TAS2573_RE_OUT);
+ dst[i++] = TASDEVICE_PAGE_REG(TAS2573_RE_OUT);
+
+ dst[i++] = 'D';
+
+ for (j = 0; j < priv->ndev; j++) {
+ dst[i++] = j;
+
+ rc = tasdevice_dev_bulk_read(priv, j, TAS2573_RE_OUT,
+ &dst[i], 4);
+ if (rc < 0)
+ dev_err(priv->dev, "chn %d bulk_rd err = %d\n", j, rc);
+
+ i += 4;
+ }
+
+ return 0;
+}
+
+static int tas2573_calib_status_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct tasdevice_priv *priv = snd_soc_component_get_drvdata(comp);
+ unsigned char *dst = ucontrol->value.bytes.data;
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ unsigned int fct_status_regs[] = {
+ TAS2573_FCT_INT_LATCH,
+ TAS2573_FCT_STATUS_CTRL,
+ TAS2573_FCT_STATUS_BINNING,
+ TAS2573_SILENCE_DETECTED,
+ TAS2573_OPEN_CIRCUIT,
+ TAS2573_SHORTCKT,
+ TAS2573_FCT_OUTPUT_R0,
+ TAS2573_FCT_OUTPUT_R0_LOW,
+ TAS2573_FCT_OUTPUT_INV_R0,
+ TAS2573_FCT_OUTPUT_POWERTOT,
+ TAS2573_FCT_OUTPUT_F0,
+ TAS2573_RE_OUT,
+ };
+ unsigned int j, k, val;
+ unsigned int i = 0;
+ int rc;
+
+ guard(mutex)(&priv->codec_lock);
+ dst[i++] = bytes_ext->max;
+ dst[i++] = 'r';
+
+ for (j = 0; j < ARRAY_SIZE(fct_status_regs); j++) {
+ dst[i++] = TASDEVICE_BOOK_ID(fct_status_regs[j]);
+ dst[i++] = TASDEVICE_PAGE_ID(fct_status_regs[j]);
+ dst[i++] = TASDEVICE_PAGE_REG(fct_status_regs[j]);
+ }
+ dst[i++] = 'D';
+
+ for (j = 0; j < priv->ndev; j++) {
+ dst[i++] = j;
+ dst[i++] = 0;
+ dst[i++] = 0;
+ dst[i++] = 0;
+
+ rc = tasdevice_dev_read(priv, j, fct_status_regs[0], &val);
+ if (rc < 0)
+ dev_err(priv->dev,
+ "chn %d fct_status_regs[0] rd err = %d\n",
+ j, rc);
+ else
+ dst[i++] = val;
+
+ for (k = 1; k < ARRAY_SIZE(fct_status_regs); k++, i += 4) {
+ rc = tasdevice_dev_bulk_read(priv, j,
+ fct_status_regs[k], &dst[i], 4);
+ if (rc < 0) {
+ dev_err(priv->dev,
+ "chn %d regs[%u] bulk_rd err = %d\n",
+ j, k, rc);
+ }
+ }
+
+ }
+
+ return 0;
+}
+
+static int create_tas2573_cali_status_ktrl(struct tasdevice_priv
+ *priv, struct snd_kcontrol_new *cali_ctrl)
+{
+ struct soc_bytes_ext *ext_cali_start;
+ char *cali_start_name;
+
+ ext_cali_start = devm_kzalloc(priv->dev,
+ sizeof(*ext_cali_start), GFP_KERNEL);
+ if (!ext_cali_start)
+ return -ENOMEM;
+
+ cali_start_name = devm_kstrdup(priv->dev,
+ "Calibration Status", GFP_KERNEL);
+ if (!cali_start_name)
+ return -ENOMEM;
+ /*
+ * package structure for tas2573 fct status:
+ * Pkg len (1 byte)
+ * Reg id (1 byte, constant 'r')
+ * book, page, register for fct status (total 36 bytes)
+ * Data Start Flag (1 byte, constant 'D')
+ * for (i = 0; i < Device-Sum; i++) {
+ * Device #i index_info (1 byte)
+ * Sine gain for Device #i (48 bytes)
+ * }
+ */
+ ext_cali_start->max = 39 + priv->ndev * 49;
+ cali_ctrl->name = cali_start_name;
+ cali_ctrl->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ cali_ctrl->info = snd_soc_bytes_info_ext;
+ cali_ctrl->put = NULL;
+ cali_ctrl->get = tas2573_calib_status_get;
+ cali_ctrl->private_value = (unsigned long)ext_cali_start;
+
+ return 0;
+}
+
+static int create_tas2573_cali_re_ktrl(struct tasdevice_priv
+ *priv, struct snd_kcontrol_new *cali_ctrl)
+{
+ struct soc_bytes_ext *ext_cali_start;
+ char *cali_start_name;
+
+ ext_cali_start = devm_kzalloc(priv->dev,
+ sizeof(*ext_cali_start), GFP_KERNEL);
+ if (!ext_cali_start)
+ return -ENOMEM;
+
+ cali_start_name = devm_kstrdup(priv->dev,
+ "Real-time Speaker Impedance", GFP_KERNEL);
+ if (!cali_start_name)
+ return -ENOMEM;
+ /*
+ * package structure for tas2573 real-time spk impedance:
+ * Pkg len (1 byte)
+ * Reg id (1 byte, constant 'r')
+ * book, page, register for fct status (total 3 bytes)
+ * Data Start Flag (1 byte, constant 'D')
+ * for (i = 0; i < Device-Sum; i++) {
+ * Device #i index_info (1 byte)
+ * Sine gain for Device #i (4 bytes)
+ * }
+ */
+ ext_cali_start->max = 6 + priv->ndev * 5;
+ cali_ctrl->name = cali_start_name;
+ cali_ctrl->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ cali_ctrl->info = snd_soc_bytes_info_ext;
+ cali_ctrl->put = NULL;
+ cali_ctrl->get = tas2573_re_get;
+ cali_ctrl->private_value = (unsigned long)ext_cali_start;
+
+ return 0;
+}
+
static int tasdevice_create_cali_ctrls(struct tasdevice_priv *priv)
{
struct calidata *cali_data = &priv->cali_data;
@@ -1504,17 +1732,43 @@ static int tasdevice_create_cali_ctrls(struct tasdevice_priv *priv)
char *cali_name;
int rc, i;
- rc = snd_soc_add_component_controls(priv->codec,
- tasdevice_cali_controls, ARRAY_SIZE(tasdevice_cali_controls));
- if (rc < 0) {
- dev_err(priv->dev, "%s: Add cali controls err rc = %d",
- __func__, rc);
- return rc;
+ switch (priv->chip_id) {
+ case TAS2563: {
+ rc = snd_soc_add_component_controls(priv->codec,
+ tasdevice_cali_controls,
+ ARRAY_SIZE(tasdevice_cali_controls));
+ if (rc < 0) {
+ dev_err(priv->dev, "%s: Add cali controls err rc = %d",
+ __func__, rc);
+ return rc;
+ }
+ cali_ctrls = (struct snd_kcontrol_new *)tas2563_cali_controls;
+ nctrls = ARRAY_SIZE(tas2563_cali_controls);
+ for (i = 0; i < priv->ndev; i++) {
+ tasdev[i].cali_data_backup =
+ kmemdup(tas2563_cali_start_reg,
+ sizeof(tas2563_cali_start_reg), GFP_KERNEL);
+ if (!tasdev[i].cali_data_backup)
+ return -ENOMEM;
+ }
}
-
- if (priv->chip_id == TAS2781) {
+ break;
+ case TAS2573:
+ cali_ctrls = (struct snd_kcontrol_new *)tas2573_cali_controls;
+ nctrls = ARRAY_SIZE(tas2573_cali_controls);
+ break;
+ case TAS2781: {
struct fct_param_address *t = &(fmw->fct_par_addr);
+ rc = snd_soc_add_component_controls(priv->codec,
+ tasdevice_cali_controls,
+ ARRAY_SIZE(tasdevice_cali_controls));
+ if (rc < 0) {
+ dev_err(priv->dev, "%s: Add cali controls err rc = %d",
+ __func__, rc);
+ return rc;
+ }
+
cali_ctrls = (struct snd_kcontrol_new *)tas2781_cali_controls;
nctrls = ARRAY_SIZE(tas2781_cali_controls);
for (i = 0; i < priv->ndev; i++) {
@@ -1533,16 +1787,12 @@ static int tasdevice_create_cali_ctrls(struct tasdevice_priv *priv)
}
}
}
- } else {
- cali_ctrls = (struct snd_kcontrol_new *)tas2563_cali_controls;
- nctrls = ARRAY_SIZE(tas2563_cali_controls);
- for (i = 0; i < priv->ndev; i++) {
- tasdev[i].cali_data_backup =
- kmemdup(tas2563_cali_start_reg,
- sizeof(tas2563_cali_start_reg), GFP_KERNEL);
- if (!tasdev[i].cali_data_backup)
- return -ENOMEM;
- }
+ }
+ break;
+ default:
+ dev_err(priv->dev, "%s: Wrong chip id = %d", __func__,
+ priv->chip_id);
+ return -EINVAL;
}
rc = snd_soc_add_component_controls(priv->codec, cali_ctrls, nctrls);
@@ -1554,10 +1804,17 @@ static int tasdevice_create_cali_ctrls(struct tasdevice_priv *priv)
/* index for cali_ctrls */
i = 0;
- if (priv->chip_id == TAS2781)
+ switch (priv->chip_id) {
+ case TAS2573:
+ nctrls = 3;
+ break;
+ case TAS2781:
nctrls = 2;
- else
+ break;
+ default:
nctrls = 1;
+ break;
+ }
/*
* Alloc kcontrol via devm_kzalloc(), which don't manually
@@ -1610,12 +1867,24 @@ static int tasdevice_create_cali_ctrls(struct tasdevice_priv *priv)
* it, for the default value is 0, which means the first device.
*/
cali_data->data[0] = 0xff;
- if (priv->chip_id == TAS2781) {
+
+ switch (priv->chip_id) {
+ case TAS2573:
+ rc = create_tas2573_cali_status_ktrl(priv, &cali_ctrls[i]);
+ if (rc != 0)
+ return rc;
+ i++;
+ rc = create_tas2573_cali_re_ktrl(priv, &cali_ctrls[i]);
+ if (rc != 0)
+ return rc;
+ i++;
+ break;
+ case TAS2781:
rc = create_tas2781_cali_start_ktrl(priv, &cali_ctrls[i]);
if (rc != 0)
return rc;
i++;
-
+ break;
}
return snd_soc_add_component_controls(priv->codec, cali_ctrls,
@@ -1822,7 +2091,8 @@ static void tasdevice_fw_ready(const struct firmware *fmw,
tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
/* There is no calibration required for TAS58XX. */
- if (tas_priv->chip_id == TAS2563 || tas_priv->chip_id == TAS2781) {
+ if (tas_priv->chip_id == TAS2563 || tas_priv->chip_id == TAS2573 ||
+ tas_priv->chip_id == TAS2781) {
ret = tasdevice_create_cali_ctrls(tas_priv);
if (ret) {
dev_err(tas_priv->dev, "cali controls error\n");
--
2.43.0
next reply other threads:[~2026-09-15 4:48 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 4:47 Shenghao Ding [this message]
2026-09-15 17:49 ` [PATCH v3] ASoC: tas2781: Add TAS2573 calibration support Mark Brown
2026-09-29 2:08 ` [EXTERNAL] " Ding, Shenghao
2026-09-29 15:24 ` Mark Brown
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=20260915044735.1305-1-shenghao-ding@ti.com \
--to=shenghao-ding@ti.com \
--cc=13916275206@139.com \
--cc=baojun.xu@ti.com \
--cc=broonie@kernel.org \
--cc=k-lu@ti.com \
--cc=lgirdwood@gmail.com \
--cc=linux-sound@vger.kernel.org \
--cc=perex@perex.cz \
--cc=tiwai@suse.de \
/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