Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Shenghao Ding and committed by
Mark Brown
55137f5a e50de21f

+121 -53
+1 -2
include/sound/tas2781.h
··· 2 2 // 3 3 // ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier 4 4 // 5 - // Copyright (C) 2022 - 2025 Texas Instruments Incorporated 5 + // Copyright (C) 2022 - 2026 Texas Instruments Incorporated 6 6 // https://www.ti.com 7 7 // 8 8 // The TAS2563/TAS2781 driver implements a flexible and configurable ··· 233 233 bool playback_started; 234 234 bool isacpi; 235 235 bool isspi; 236 - bool is_user_space_calidata; 237 236 unsigned int global_addr; 238 237 239 238 int (*fw_parse_variable_header)(struct tasdevice_priv *tas_priv,
+7 -2
sound/hda/codecs/side-codecs/tas2781_hda.c
··· 2 2 // 3 3 // TAS2781 HDA Shared Lib for I2C&SPI driver 4 4 // 5 - // Copyright 2025 Texas Instruments, Inc. 5 + // Copyright 2025 - 2026 Texas Instruments, Inc. 6 6 // 7 7 // Author: Shenghao Ding <shenghao-ding@ti.com> 8 8 ··· 159 159 r->tlimit_reg = cali_reg[4]; 160 160 } 161 161 162 - p->is_user_space_calidata = true; 163 162 cali_data->total_sz = p->ndev * (cali_data->cali_dat_sz_per_dev + 1); 164 163 } 165 164 ··· 215 216 status = -ENOMEM; 216 217 continue; 217 218 } 219 + /* 220 + * Set to an invalid value before the calibrated data 221 + * is stored into it, for the default value is 0, which 222 + * means the first device. 223 + */ 224 + data[0] = 0xff; 218 225 /* Get variable contents into buffer */ 219 226 status = efi.get_variable(efi_name[i], &efi_guid, 220 227 &attr, &cali_data->total_sz, data);
-13
sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
··· 393 393 r->pow_reg = TAS2563_CAL_POWER; 394 394 r->tlimit_reg = TAS2563_CAL_TLIM; 395 395 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 - 409 396 return 0; 410 397 } 411 398
+107 -31
sound/soc/codecs/tas2781-fmwlib.c
··· 2 2 // 3 3 // tas2781-fmwlib.c -- TASDEVICE firmware support 4 4 // 5 - // Copyright 2023 - 2025 Texas Instruments, Inc. 5 + // Copyright 2023 - 2026 Texas Instruments, Inc. 6 6 // 7 7 // Author: Shenghao Ding <shenghao-ding@ti.com> 8 8 // Author: Baojun Xu <baojun.xu@ti.com> ··· 79 79 #define POST_SOFTWARE_RESET_DEVICE_B 0x46 80 80 #define POST_SOFTWARE_RESET_DEVICE_C 0x47 81 81 #define POST_SOFTWARE_RESET_DEVICE_D 0x48 82 + 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) 82 90 83 91 struct tas_crc { 84 92 unsigned char offset; ··· 1960 1952 return rc; 1961 1953 } 1962 1954 1963 - static int load_calib_data(struct tasdevice_priv *tas_priv, 1964 - struct tasdevice_data *dev_data) 1965 - { 1966 - struct tasdev_blk *block; 1967 - unsigned int i; 1968 - int ret = 0; 1969 - 1970 - for (i = 0; i < dev_data->nr_blk; i++) { 1971 - block = &(dev_data->dev_blks[i]); 1972 - ret = tasdevice_load_block(tas_priv, block); 1973 - if (ret < 0) 1974 - break; 1975 - } 1976 - 1977 - return ret; 1978 - } 1979 - 1980 1955 static int fw_parse_header(struct tasdevice_priv *tas_priv, 1981 1956 struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset) 1982 1957 { ··· 2020 2029 return offset; 2021 2030 } 2022 2031 2032 + static inline int check_cal_bin_data(struct device *dev, 2033 + const unsigned char *data, const char *name) 2034 + { 2035 + if (data[2] != 0x85 || data[1] != 4) { 2036 + dev_err(dev, "Invalid cal bin file in %s\n", name); 2037 + return -1; 2038 + } 2039 + return 0; 2040 + } 2041 + 2042 + static void calbin_conversion(struct tasdevice_priv *priv, 2043 + struct tasdevice_fw *tas_fmw) 2044 + { 2045 + struct calidata *cali_data = &priv->cali_data; 2046 + unsigned char *calbin_data = cali_data->data; 2047 + struct cali_reg *p = &cali_data->cali_reg_array; 2048 + struct tasdevice_calibration *calibration; 2049 + struct tasdevice_data *img_data; 2050 + struct tasdev_blk *blk; 2051 + unsigned char *data; 2052 + int chn, k; 2053 + 2054 + if (cali_data->total_sz != priv->ndev * 2055 + (cali_data->cali_dat_sz_per_dev + 1)) { 2056 + dev_err(priv->dev, "%s: cali_data size err\n", 2057 + __func__); 2058 + return; 2059 + } 2060 + calibration = &(tas_fmw->calibrations[0]); 2061 + img_data = &(calibration->dev_data); 2062 + 2063 + if (img_data->nr_blk != 1) { 2064 + dev_err(priv->dev, "%s: Invalid nr_blk, wrong cal bin\n", 2065 + __func__); 2066 + return; 2067 + } 2068 + 2069 + blk = &(img_data->dev_blks[0]); 2070 + if (blk->nr_cmds != 15) { 2071 + dev_err(priv->dev, "%s: Invalid nr_cmds, wrong cal bin\n", 2072 + __func__); 2073 + return; 2074 + } 2075 + 2076 + switch (blk->type) { 2077 + case COEFF_DEVICE_A: 2078 + chn = 0; 2079 + break; 2080 + case COEFF_DEVICE_B: 2081 + chn = 1; 2082 + break; 2083 + case COEFF_DEVICE_C: 2084 + chn = 2; 2085 + break; 2086 + case COEFF_DEVICE_D: 2087 + chn = 3; 2088 + break; 2089 + default: 2090 + dev_err(priv->dev, "%s: Other Type = 0x%02x\n", 2091 + __func__, blk->type); 2092 + return; 2093 + } 2094 + k = chn * (cali_data->cali_dat_sz_per_dev + 1); 2095 + 2096 + data = blk->data; 2097 + if (check_cal_bin_data(priv->dev, data, "r0_reg") < 0) 2098 + return; 2099 + p->r0_reg = TASDEVICE_REG(data[4], data[5], data[6]); 2100 + COPY_CAL_DATA(k); 2101 + 2102 + data = blk->data + 12; 2103 + if (check_cal_bin_data(priv->dev, data, "r0_low_reg") < 0) 2104 + return; 2105 + p->r0_low_reg = TASDEVICE_REG(data[4], data[5], data[6]); 2106 + COPY_CAL_DATA(k + 4); 2107 + 2108 + data = blk->data + 24; 2109 + if (check_cal_bin_data(priv->dev, data, "invr0_reg") < 0) 2110 + return; 2111 + p->invr0_reg = TASDEVICE_REG(data[4], data[5], data[6]); 2112 + COPY_CAL_DATA(k + 8); 2113 + 2114 + data = blk->data + 36; 2115 + if (check_cal_bin_data(priv->dev, data, "pow_reg") < 0) 2116 + return; 2117 + p->pow_reg = TASDEVICE_REG(data[4], data[5], data[6]); 2118 + COPY_CAL_DATA(k + 12); 2119 + 2120 + data = blk->data + 48; 2121 + if (check_cal_bin_data(priv->dev, data, "tlimit_reg") < 0) 2122 + return; 2123 + p->tlimit_reg = TASDEVICE_REG(data[4], data[5], data[6]); 2124 + COPY_CAL_DATA(k + 16); 2125 + 2126 + calbin_data[k] = chn; 2127 + } 2128 + 2023 2129 /* When calibrated data parsing error occurs, DSP can still work with default 2024 2130 * calibrated data, memory resource related to calibrated data will be 2025 2131 * released in the tasdevice_codec_remove. ··· 2174 2086 goto out; 2175 2087 } 2176 2088 2089 + calbin_conversion(tas_priv, tas_fmw); 2177 2090 out: 2178 2091 return offset; 2179 2092 } ··· 2460 2371 2461 2372 static void tasdev_load_calibrated_data(struct tasdevice_priv *priv, int i) 2462 2373 { 2463 - struct tasdevice_fw *cal_fmw = priv->tasdevice[i].cali_data_fmw; 2464 2374 struct calidata *cali_data = &priv->cali_data; 2465 2375 struct cali_reg *p = &cali_data->cali_reg_array; 2466 2376 unsigned char *data = cali_data->data; 2467 - struct tasdevice_calibration *cal; 2468 2377 int k = i * (cali_data->cali_dat_sz_per_dev + 1); 2469 2378 int rc; 2470 2379 2471 - /* Load the calibrated data from cal bin file */ 2472 - if (!priv->is_user_space_calidata && cal_fmw) { 2473 - cal = cal_fmw->calibrations; 2474 - 2475 - if (cal) 2476 - load_calib_data(priv, &cal->dev_data); 2477 - return; 2478 - } 2479 - if (!priv->is_user_space_calidata) 2480 - return; 2481 - /* load calibrated data from user space */ 2482 2380 if (data[k] != i) { 2483 2381 dev_err(priv->dev, "%s: no cal-data for dev %d from usr-spc\n", 2484 2382 __func__, i);
+6 -5
sound/soc/codecs/tas2781-i2c.c
··· 2 2 // 3 3 // ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier 4 4 // 5 - // Copyright (C) 2022 - 2025 Texas Instruments Incorporated 5 + // Copyright (C) 2022 - 2026 Texas Instruments Incorporated 6 6 // https://www.ti.com 7 7 // 8 8 // The TAS2563/TAS2781 driver implements a flexible and configurable ··· 255 255 int rc; 256 256 257 257 guard(mutex)(&priv->codec_lock); 258 - if (!priv->is_user_space_calidata) 259 - return -1; 260 258 261 259 if (!p->r0_reg) 262 260 return -1; ··· 652 654 } 653 655 } 654 656 i += 2; 655 - priv->is_user_space_calidata = true; 656 657 657 658 if (priv->dspbin_typ == TASDEV_BASIC) { 658 659 p->r0_reg = TASDEVICE_REG(src[i], src[i + 1], src[i + 2]); ··· 1441 1444 GFP_KERNEL); 1442 1445 if (!cali_data->data) 1443 1446 return -ENOMEM; 1444 - 1447 + /* 1448 + * Set to an invalid value before the calibrated data is stored into 1449 + * it, for the default value is 0, which means the first device. 1450 + */ 1451 + cali_data->data[0] = 0xff; 1445 1452 if (priv->chip_id == TAS2781) { 1446 1453 struct soc_bytes_ext *ext_cali_start; 1447 1454 char *cali_start_name;