Skip to content

Commit 55137f5

Browse files
Shenghao-Dingbroonie
authored andcommitted
ASoC: tas2781: Put three different calibrated data solution into the same data structure
TAS2781 driver supports three solutions of calibrated data. The first is from the driver itself: driver reads the calibrated files directly during probe; The second is from user space: during init of audio hal, the audio hal will pass the calibrated data via kcontrol interface. Driver will store this data in "struct calidata" for use. The third is from UEFI, mainly used in hda device. These three solutions save the calibrated data into different data structures. It is time to put them together into "struct calidata" for use. Signed-off-by: Shenghao Ding <shenghao-ding@ti.com> Link: https://patch.msgid.link/20260202102757.532-1-shenghao-ding@ti.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent e50de21 commit 55137f5

5 files changed

Lines changed: 121 additions & 53 deletions

File tree

include/sound/tas2781.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier
44
//
5-
// Copyright (C) 2022 - 2025 Texas Instruments Incorporated
5+
// Copyright (C) 2022 - 2026 Texas Instruments Incorporated
66
// https://www.ti.com
77
//
88
// The TAS2563/TAS2781 driver implements a flexible and configurable
@@ -233,7 +233,6 @@ struct tasdevice_priv {
233233
bool playback_started;
234234
bool isacpi;
235235
bool isspi;
236-
bool is_user_space_calidata;
237236
unsigned int global_addr;
238237

239238
int (*fw_parse_variable_header)(struct tasdevice_priv *tas_priv,

sound/hda/codecs/side-codecs/tas2781_hda.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// TAS2781 HDA Shared Lib for I2C&SPI driver
44
//
5-
// Copyright 2025 Texas Instruments, Inc.
5+
// Copyright 2025 - 2026 Texas Instruments, Inc.
66
//
77
// Author: Shenghao Ding <shenghao-ding@ti.com>
88

@@ -159,7 +159,6 @@ static void tas2781_apply_calib(struct tasdevice_priv *p)
159159
r->tlimit_reg = cali_reg[4];
160160
}
161161

162-
p->is_user_space_calidata = true;
163162
cali_data->total_sz = p->ndev * (cali_data->cali_dat_sz_per_dev + 1);
164163
}
165164

@@ -216,6 +215,12 @@ int tas2781_save_calibration(struct tas2781_hda *hda)
216215
status = -ENOMEM;
217216
continue;
218217
}
218+
/*
219+
* Set to an invalid value before the calibrated data
220+
* is stored into it, for the default value is 0, which
221+
* means the first device.
222+
*/
223+
data[0] = 0xff;
219224
/* Get variable contents into buffer */
220225
status = efi.get_variable(efi_name[i], &efi_guid,
221226
&attr, &cali_data->total_sz, data);

sound/hda/codecs/side-codecs/tas2781_hda_i2c.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -393,19 +393,6 @@ static int tas2563_save_calibration(struct tas2781_hda *h)
393393
r->pow_reg = TAS2563_CAL_POWER;
394394
r->tlimit_reg = TAS2563_CAL_TLIM;
395395

396-
/*
397-
* TAS2781_FMWLIB supports two solutions of calibrated data. One is
398-
* from the driver itself: driver reads the calibrated files directly
399-
* during probe; The other from user space: during init of audio hal,
400-
* the audio hal will pass the calibrated data via kcontrol interface.
401-
* Driver will store this data in "struct calidata" for use. For hda
402-
* device, calibrated data are usunally saved into UEFI. So Hda side
403-
* codec driver use the mixture of these two solutions, driver reads
404-
* the data from UEFI, then store this data in "struct calidata" for
405-
* use.
406-
*/
407-
p->is_user_space_calidata = true;
408-
409396
return 0;
410397
}
411398

sound/soc/codecs/tas2781-fmwlib.c

Lines changed: 107 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// tas2781-fmwlib.c -- TASDEVICE firmware support
44
//
5-
// Copyright 2023 - 2025 Texas Instruments, Inc.
5+
// Copyright 2023 - 2026 Texas Instruments, Inc.
66
//
77
// Author: Shenghao Ding <shenghao-ding@ti.com>
88
// Author: Baojun Xu <baojun.xu@ti.com>
@@ -80,6 +80,14 @@
8080
#define POST_SOFTWARE_RESET_DEVICE_C 0x47
8181
#define POST_SOFTWARE_RESET_DEVICE_D 0x48
8282

83+
#define COPY_CAL_DATA(i) \
84+
do { \
85+
calbin_data[i + 1] = data[7]; \
86+
calbin_data[i + 2] = data[8]; \
87+
calbin_data[i + 3] = data[9]; \
88+
calbin_data[i + 4] = data[10]; \
89+
} while (0)
90+
8391
struct tas_crc {
8492
unsigned char offset;
8593
unsigned char len;
@@ -1952,23 +1960,6 @@ static int dspfw_default_callback(struct tasdevice_priv *tas_priv,
19521960
return rc;
19531961
}
19541962

1955-
static int load_calib_data(struct tasdevice_priv *tas_priv,
1956-
struct tasdevice_data *dev_data)
1957-
{
1958-
struct tasdev_blk *block;
1959-
unsigned int i;
1960-
int ret = 0;
1961-
1962-
for (i = 0; i < dev_data->nr_blk; i++) {
1963-
block = &(dev_data->dev_blks[i]);
1964-
ret = tasdevice_load_block(tas_priv, block);
1965-
if (ret < 0)
1966-
break;
1967-
}
1968-
1969-
return ret;
1970-
}
1971-
19721963
static int fw_parse_header(struct tasdevice_priv *tas_priv,
19731964
struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
19741965
{
@@ -2029,6 +2020,103 @@ static int fw_parse_variable_hdr_cal(struct tasdevice_priv *tas_priv,
20292020
return offset;
20302021
}
20312022

2023+
static inline int check_cal_bin_data(struct device *dev,
2024+
const unsigned char *data, const char *name)
2025+
{
2026+
if (data[2] != 0x85 || data[1] != 4) {
2027+
dev_err(dev, "Invalid cal bin file in %s\n", name);
2028+
return -1;
2029+
}
2030+
return 0;
2031+
}
2032+
2033+
static void calbin_conversion(struct tasdevice_priv *priv,
2034+
struct tasdevice_fw *tas_fmw)
2035+
{
2036+
struct calidata *cali_data = &priv->cali_data;
2037+
unsigned char *calbin_data = cali_data->data;
2038+
struct cali_reg *p = &cali_data->cali_reg_array;
2039+
struct tasdevice_calibration *calibration;
2040+
struct tasdevice_data *img_data;
2041+
struct tasdev_blk *blk;
2042+
unsigned char *data;
2043+
int chn, k;
2044+
2045+
if (cali_data->total_sz != priv->ndev *
2046+
(cali_data->cali_dat_sz_per_dev + 1)) {
2047+
dev_err(priv->dev, "%s: cali_data size err\n",
2048+
__func__);
2049+
return;
2050+
}
2051+
calibration = &(tas_fmw->calibrations[0]);
2052+
img_data = &(calibration->dev_data);
2053+
2054+
if (img_data->nr_blk != 1) {
2055+
dev_err(priv->dev, "%s: Invalid nr_blk, wrong cal bin\n",
2056+
__func__);
2057+
return;
2058+
}
2059+
2060+
blk = &(img_data->dev_blks[0]);
2061+
if (blk->nr_cmds != 15) {
2062+
dev_err(priv->dev, "%s: Invalid nr_cmds, wrong cal bin\n",
2063+
__func__);
2064+
return;
2065+
}
2066+
2067+
switch (blk->type) {
2068+
case COEFF_DEVICE_A:
2069+
chn = 0;
2070+
break;
2071+
case COEFF_DEVICE_B:
2072+
chn = 1;
2073+
break;
2074+
case COEFF_DEVICE_C:
2075+
chn = 2;
2076+
break;
2077+
case COEFF_DEVICE_D:
2078+
chn = 3;
2079+
break;
2080+
default:
2081+
dev_err(priv->dev, "%s: Other Type = 0x%02x\n",
2082+
__func__, blk->type);
2083+
return;
2084+
}
2085+
k = chn * (cali_data->cali_dat_sz_per_dev + 1);
2086+
2087+
data = blk->data;
2088+
if (check_cal_bin_data(priv->dev, data, "r0_reg") < 0)
2089+
return;
2090+
p->r0_reg = TASDEVICE_REG(data[4], data[5], data[6]);
2091+
COPY_CAL_DATA(k);
2092+
2093+
data = blk->data + 12;
2094+
if (check_cal_bin_data(priv->dev, data, "r0_low_reg") < 0)
2095+
return;
2096+
p->r0_low_reg = TASDEVICE_REG(data[4], data[5], data[6]);
2097+
COPY_CAL_DATA(k + 4);
2098+
2099+
data = blk->data + 24;
2100+
if (check_cal_bin_data(priv->dev, data, "invr0_reg") < 0)
2101+
return;
2102+
p->invr0_reg = TASDEVICE_REG(data[4], data[5], data[6]);
2103+
COPY_CAL_DATA(k + 8);
2104+
2105+
data = blk->data + 36;
2106+
if (check_cal_bin_data(priv->dev, data, "pow_reg") < 0)
2107+
return;
2108+
p->pow_reg = TASDEVICE_REG(data[4], data[5], data[6]);
2109+
COPY_CAL_DATA(k + 12);
2110+
2111+
data = blk->data + 48;
2112+
if (check_cal_bin_data(priv->dev, data, "tlimit_reg") < 0)
2113+
return;
2114+
p->tlimit_reg = TASDEVICE_REG(data[4], data[5], data[6]);
2115+
COPY_CAL_DATA(k + 16);
2116+
2117+
calbin_data[k] = chn;
2118+
}
2119+
20322120
/* When calibrated data parsing error occurs, DSP can still work with default
20332121
* calibrated data, memory resource related to calibrated data will be
20342122
* released in the tasdevice_codec_remove.
@@ -2086,6 +2174,7 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv,
20862174
goto out;
20872175
}
20882176

2177+
calbin_conversion(tas_priv, tas_fmw);
20892178
out:
20902179
return offset;
20912180
}
@@ -2371,25 +2460,12 @@ static int tasdevice_load_data(struct tasdevice_priv *tas_priv,
23712460

23722461
static void tasdev_load_calibrated_data(struct tasdevice_priv *priv, int i)
23732462
{
2374-
struct tasdevice_fw *cal_fmw = priv->tasdevice[i].cali_data_fmw;
23752463
struct calidata *cali_data = &priv->cali_data;
23762464
struct cali_reg *p = &cali_data->cali_reg_array;
23772465
unsigned char *data = cali_data->data;
2378-
struct tasdevice_calibration *cal;
23792466
int k = i * (cali_data->cali_dat_sz_per_dev + 1);
23802467
int rc;
23812468

2382-
/* Load the calibrated data from cal bin file */
2383-
if (!priv->is_user_space_calidata && cal_fmw) {
2384-
cal = cal_fmw->calibrations;
2385-
2386-
if (cal)
2387-
load_calib_data(priv, &cal->dev_data);
2388-
return;
2389-
}
2390-
if (!priv->is_user_space_calidata)
2391-
return;
2392-
/* load calibrated data from user space */
23932469
if (data[k] != i) {
23942470
dev_err(priv->dev, "%s: no cal-data for dev %d from usr-spc\n",
23952471
__func__, i);

sound/soc/codecs/tas2781-i2c.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier
44
//
5-
// Copyright (C) 2022 - 2025 Texas Instruments Incorporated
5+
// Copyright (C) 2022 - 2026 Texas Instruments Incorporated
66
// https://www.ti.com
77
//
88
// The TAS2563/TAS2781 driver implements a flexible and configurable
@@ -255,8 +255,6 @@ static int tasdev_cali_data_get(struct snd_kcontrol *kcontrol,
255255
int rc;
256256

257257
guard(mutex)(&priv->codec_lock);
258-
if (!priv->is_user_space_calidata)
259-
return -1;
260258

261259
if (!p->r0_reg)
262260
return -1;
@@ -654,7 +652,6 @@ static int tasdev_cali_data_put(struct snd_kcontrol *kcontrol,
654652
}
655653
}
656654
i += 2;
657-
priv->is_user_space_calidata = true;
658655

659656
if (priv->dspbin_typ == TASDEV_BASIC) {
660657
p->r0_reg = TASDEVICE_REG(src[i], src[i + 1], src[i + 2]);
@@ -1444,7 +1441,11 @@ static int tasdevice_create_cali_ctrls(struct tasdevice_priv *priv)
14441441
GFP_KERNEL);
14451442
if (!cali_data->data)
14461443
return -ENOMEM;
1447-
1444+
/*
1445+
* Set to an invalid value before the calibrated data is stored into
1446+
* it, for the default value is 0, which means the first device.
1447+
*/
1448+
cali_data->data[0] = 0xff;
14481449
if (priv->chip_id == TAS2781) {
14491450
struct soc_bytes_ext *ext_cali_start;
14501451
char *cali_start_name;

0 commit comments

Comments
 (0)