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

ALSA: hda/tas2781: Move and unified the calibrated-data getting function for SPI and I2C into the tas2781_hda lib

Calibration data getting function for SPI and I2C HDA drivers are almost
same, which read the calibration data from UEFI. To put them into
tas2781_hda lib for code cleanup is more reasonable than to still keep
them in the codec driver. For tas2781 codec driver, there're two different
sources for calibrated data, one is from bin file, generated in factory
test, requested and read in codec driver side; the other is from user
space during device bootup.

Signed-off-by: Shenghao Ding <shenghao-ding@ti.com>

Link: https://patch.msgid.link/20250522014347.1163-1-shenghao-ding@ti.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Shenghao Ding and committed by
Takashi Iwai
4fe23851 c597ce56

+271 -355
-10
include/sound/tas2781.h
··· 121 121 TASDEV_BETA, 122 122 }; 123 123 124 - enum device_catlog_id { 125 - LENOVO = 0, 126 - OTHERS 127 - }; 128 - 129 124 struct bulk_reg_val { 130 125 int reg; 131 126 unsigned char val[4]; ··· 167 172 struct regmap *regmap; 168 173 struct device *dev; 169 174 170 - enum device_catlog_id catlog_id; 171 175 unsigned char cal_binaryname[TASDEVICE_MAX_CHANNELS][64]; 172 176 unsigned char crc8_lkp_tbl[CRC8_TABLE_SIZE]; 173 177 unsigned char coef_binaryname[64]; ··· 217 223 int (*dev_bulk_read)(struct tasdevice_priv *tas_priv, 218 224 unsigned short chn, unsigned int reg, unsigned char *p_data, 219 225 unsigned int n_length); 220 - int (*save_calibration)(struct tasdevice_priv *tas_priv); 221 - void (*apply_calibration)(struct tasdevice_priv *tas_priv); 222 226 }; 223 227 224 228 int tasdevice_dev_read(struct tasdevice_priv *tas_priv, ··· 230 238 struct tasdevice_priv *tas_priv, unsigned short chn, 231 239 unsigned int reg, unsigned char *p_data, unsigned int n_length); 232 240 void tasdevice_remove(struct tasdevice_priv *tas_priv); 233 - int tasdevice_save_calibration(struct tasdevice_priv *tas_priv); 234 - void tasdevice_apply_calibration(struct tasdevice_priv *tas_priv); 235 241 #endif /* __TAS2781_H__ */
+179
sound/pci/hda/tas2781_hda.c
··· 18 18 19 19 #include "tas2781_hda.h" 20 20 21 + const efi_guid_t tasdev_fct_efi_guid[] = { 22 + /* DELL */ 23 + EFI_GUID(0xcc92382d, 0x6337, 0x41cb, 0xa8, 0x8b, 0x8e, 0xce, 0x74, 24 + 0x91, 0xea, 0x9f), 25 + /* HP */ 26 + EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 27 + 0xa3, 0x5d, 0xb3), 28 + /* LENOVO & OTHERS */ 29 + EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09, 0x43, 0xa3, 0xf4, 30 + 0x31, 0x0a, 0x92), 31 + }; 32 + EXPORT_SYMBOL_NS_GPL(tasdev_fct_efi_guid, "SND_HDA_SCODEC_TAS2781"); 33 + 34 + static void tas2781_apply_calib(struct tasdevice_priv *p) 35 + { 36 + struct calidata *cali_data = &p->cali_data; 37 + struct cali_reg *r = &cali_data->cali_reg_array; 38 + unsigned char *data = cali_data->data; 39 + unsigned int *tmp_val = (unsigned int *)data; 40 + unsigned int cali_reg[TASDEV_CALIB_N] = { 41 + TASDEVICE_REG(0, 0x17, 0x74), 42 + TASDEVICE_REG(0, 0x18, 0x0c), 43 + TASDEVICE_REG(0, 0x18, 0x14), 44 + TASDEVICE_REG(0, 0x13, 0x70), 45 + TASDEVICE_REG(0, 0x18, 0x7c), 46 + }; 47 + unsigned int crc, oft; 48 + unsigned char *buf; 49 + int i, j, k, l; 50 + 51 + if (tmp_val[0] == 2781) { 52 + /* 53 + * New features were added in calibrated Data V3: 54 + * 1. Added calibration registers address define in 55 + * a node, marked as Device id == 0x80. 56 + * New features were added in calibrated Data V2: 57 + * 1. Added some the fields to store the link_id and 58 + * uniqie_id for multi-link solutions 59 + * 2. Support flexible number of devices instead of 60 + * fixed one in V1. 61 + * Layout of calibrated data V2 in UEFI(total 256 bytes): 62 + * ChipID (2781, 4 bytes) 63 + * Data-Group-Sum (4 bytes) 64 + * TimeStamp of Calibration (4 bytes) 65 + * for (i = 0; i < Data-Group-Sum; i++) { 66 + * if (Data type != 0x80) (4 bytes) 67 + * Calibrated Data of Device #i (20 bytes) 68 + * else 69 + * Calibration registers address (5*4 = 20 bytes) 70 + * # V2: No reg addr in data grp section. 71 + * # V3: Normally the last grp is the reg addr. 72 + * } 73 + * CRC (4 bytes) 74 + * Reserved (the rest) 75 + */ 76 + crc = crc32(~0, data, (3 + tmp_val[1] * 6) * 4) ^ ~0; 77 + 78 + if (crc != tmp_val[3 + tmp_val[1] * 6]) { 79 + cali_data->total_sz = 0; 80 + dev_err(p->dev, "%s: CRC error\n", __func__); 81 + return; 82 + } 83 + 84 + for (j = 0, k = 0; j < tmp_val[1]; j++) { 85 + oft = j * 6 + 3; 86 + if (tmp_val[oft] == TASDEV_UEFI_CALI_REG_ADDR_FLG) { 87 + for (i = 0; i < TASDEV_CALIB_N; i++) { 88 + buf = &data[(oft + i + 1) * 4]; 89 + cali_reg[i] = TASDEVICE_REG(buf[1], 90 + buf[2], buf[3]); 91 + } 92 + } else { 93 + l = j * (cali_data->cali_dat_sz_per_dev + 1); 94 + if (k >= p->ndev || l > oft * 4) { 95 + dev_err(p->dev, "%s: dev sum error\n", 96 + __func__); 97 + cali_data->total_sz = 0; 98 + return; 99 + } 100 + 101 + data[l] = k; 102 + for (i = 0; i < TASDEV_CALIB_N * 4; i++) 103 + data[l + i] = data[4 * oft + i]; 104 + k++; 105 + } 106 + } 107 + } else { 108 + /* 109 + * Calibration data is in V1 format. 110 + * struct cali_data { 111 + * char cali_data[20]; 112 + * } 113 + * 114 + * struct { 115 + * struct cali_data cali_data[4]; 116 + * int TimeStamp of Calibration (4 bytes) 117 + * int CRC (4 bytes) 118 + * } ueft; 119 + */ 120 + crc = crc32(~0, data, 84) ^ ~0; 121 + if (crc != tmp_val[21]) { 122 + cali_data->total_sz = 0; 123 + dev_err(p->dev, "%s: V1 CRC error\n", __func__); 124 + return; 125 + } 126 + 127 + for (j = p->ndev - 1; j >= 0; j--) { 128 + l = j * (cali_data->cali_dat_sz_per_dev + 1); 129 + for (i = TASDEV_CALIB_N * 4; i > 0 ; i--) 130 + data[l + i] = data[p->index * 5 + i]; 131 + data[l+i] = j; 132 + } 133 + } 134 + 135 + if (p->dspbin_typ == TASDEV_BASIC) { 136 + r->r0_reg = cali_reg[0]; 137 + r->invr0_reg = cali_reg[1]; 138 + r->r0_low_reg = cali_reg[2]; 139 + r->pow_reg = cali_reg[3]; 140 + r->tlimit_reg = cali_reg[4]; 141 + } 142 + 143 + p->is_user_space_calidata = true; 144 + cali_data->total_sz = p->ndev * (cali_data->cali_dat_sz_per_dev + 1); 145 + } 146 + 147 + /* 148 + * Update the calibration data, including speaker impedance, f0, etc, 149 + * into algo. Calibrate data is done by manufacturer in the factory. 150 + * The data is used by Algo for calculating the speaker temperature, 151 + * speaker membrane excursion and f0 in real time during playback. 152 + * Calibration data format in EFI is V2, since 2024. 153 + */ 154 + int tas2781_save_calibration(struct tas2781_hda *hda) 155 + { 156 + /* 157 + * GUID was used for data access in BIOS, it was provided by board 158 + * manufactory. 159 + */ 160 + efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO]; 161 + static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME; 162 + struct tasdevice_priv *p = hda->priv; 163 + struct calidata *cali_data = &p->cali_data; 164 + unsigned long total_sz = 0; 165 + unsigned int attr, size; 166 + unsigned char *data; 167 + efi_status_t status; 168 + 169 + if (hda->catlog_id < LENOVO) 170 + efi_guid = tasdev_fct_efi_guid[hda->catlog_id]; 171 + 172 + cali_data->cali_dat_sz_per_dev = 20; 173 + size = p->ndev * (cali_data->cali_dat_sz_per_dev + 1); 174 + /* Get real size of UEFI variable */ 175 + status = efi.get_variable(efi_name, &efi_guid, &attr, &total_sz, NULL); 176 + cali_data->total_sz = total_sz > size ? total_sz : size; 177 + if (status == EFI_BUFFER_TOO_SMALL) { 178 + /* Allocate data buffer of data_size bytes */ 179 + data = p->cali_data.data = devm_kzalloc(p->dev, 180 + p->cali_data.total_sz, GFP_KERNEL); 181 + if (!data) { 182 + p->cali_data.total_sz = 0; 183 + return -ENOMEM; 184 + } 185 + /* Get variable contents into buffer */ 186 + status = efi.get_variable(efi_name, &efi_guid, &attr, 187 + &p->cali_data.total_sz, data); 188 + } 189 + if (status != EFI_SUCCESS) { 190 + p->cali_data.total_sz = 0; 191 + return status; 192 + } 193 + 194 + tas2781_apply_calib(p); 195 + 196 + return 0; 197 + } 198 + EXPORT_SYMBOL_NS_GPL(tas2781_save_calibration, "SND_HDA_SCODEC_TAS2781"); 199 + 21 200 void tas2781_hda_remove(struct device *dev, 22 201 const struct component_ops *ops) 23 202 {
+12
sound/pci/hda/tas2781_hda.h
··· 9 9 10 10 #include <sound/asound.h> 11 11 12 + /* Flag of calibration registers address. */ 13 + #define TASDEV_UEFI_CALI_REG_ADDR_FLG BIT(7) 12 14 #define TASDEVICE_CALIBRATION_DATA_NAME L"CALI_DATA" 13 15 #define TASDEV_CALIB_N 5 14 16 ··· 46 44 .private_value = xdata, \ 47 45 } 48 46 47 + enum device_catlog_id { 48 + DELL = 0, 49 + HP, 50 + LENOVO, 51 + OTHERS 52 + }; 53 + 49 54 struct tas2781_hda { 50 55 struct device *dev; 51 56 struct tasdevice_priv *priv; ··· 63 54 void *hda_priv; 64 55 }; 65 56 57 + extern const efi_guid_t tasdev_fct_efi_guid[]; 58 + 59 + int tas2781_save_calibration(struct tas2781_hda *p); 66 60 void tas2781_hda_remove(struct device *dev, 67 61 const struct component_ops *ops); 68 62 int tasdevice_info_profile(struct snd_kcontrol *kctl,
+79 -164
sound/pci/hda/tas2781_hda_i2c.c
··· 33 33 #include "hda_generic.h" 34 34 #include "tas2781_hda.h" 35 35 36 - #define TASDEVICE_SPEAKER_CALIBRATION_SIZE 20 36 + #define TAS2563_CAL_VAR_NAME_MAX 16 37 + #define TAS2563_CAL_ARRAY_SIZE 80 38 + #define TAS2563_CAL_DATA_SIZE 4 39 + #define TAS2563_MAX_CHANNELS 4 40 + #define TAS2563_CAL_CH_SIZE 20 37 41 38 - #define TAS2563_MAX_CHANNELS 4 39 - 40 - #define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c) 41 - #define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34) 42 - #define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40) 43 - #define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48) 44 - #define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14) 45 - #define TAS2563_CAL_DATA_SIZE 4 46 - #define TAS2563_CAL_CH_SIZE 20 47 - #define TAS2563_CAL_ARRAY_SIZE 80 48 - 49 - static unsigned int cal_regs[TASDEV_CALIB_N] = { 50 - TAS2563_CAL_POWER, TAS2563_CAL_R0, TAS2563_CAL_INVR0, 51 - TAS2563_CAL_R0_LOW, TAS2563_CAL_TLIM, 52 - }; 42 + #define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48) 43 + #define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c) 44 + #define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40) 45 + #define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14) 46 + #define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34) 53 47 54 48 struct tas2781_hda_i2c_priv { 55 49 struct snd_kcontrol *snd_ctls[2]; 50 + int (*save_calibration)(struct tas2781_hda *h); 56 51 }; 57 52 58 53 static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data) ··· 278 283 .put = tasdevice_config_put, 279 284 }; 280 285 281 - static void tas2563_apply_calib(struct tasdevice_priv *tas_priv) 286 + static int tas2563_save_calibration(struct tas2781_hda *h) 282 287 { 283 - int offset = 0; 284 - __be32 data; 285 - int ret; 286 - 287 - for (int i = 0; i < tas_priv->ndev; i++) { 288 - for (int j = 0; j < TASDEV_CALIB_N; ++j) { 289 - data = cpu_to_be32( 290 - *(uint32_t *)&tas_priv->cali_data.data[offset]); 291 - ret = tasdevice_dev_bulk_write(tas_priv, i, cal_regs[j], 292 - (unsigned char *)&data, TAS2563_CAL_DATA_SIZE); 293 - if (ret) 294 - dev_err(tas_priv->dev, 295 - "Error writing calib regs\n"); 296 - offset += TAS2563_CAL_DATA_SIZE; 297 - } 298 - } 299 - } 300 - 301 - static int tas2563_save_calibration(struct tasdevice_priv *tas_priv) 302 - { 303 - static efi_guid_t efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 304 - 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92); 305 - 306 - static efi_char16_t *efi_vars[TAS2563_MAX_CHANNELS][TASDEV_CALIB_N] = { 307 - { L"Power_1", L"R0_1", L"InvR0_1", L"R0_Low_1", L"TLim_1" }, 308 - { L"Power_2", L"R0_2", L"InvR0_2", L"R0_Low_2", L"TLim_2" }, 309 - { L"Power_3", L"R0_3", L"InvR0_3", L"R0_Low_3", L"TLim_3" }, 310 - { L"Power_4", L"R0_4", L"InvR0_4", L"R0_Low_4", L"TLim_4" }, 288 + efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO]; 289 + char *vars[TASDEV_CALIB_N] = { 290 + "R0_%d", "InvR0_%d", "R0_Low_%d", "Power_%d", "TLim_%d" 311 291 }; 312 - 292 + efi_char16_t efi_name[TAS2563_CAL_VAR_NAME_MAX]; 313 293 unsigned long max_size = TAS2563_CAL_DATA_SIZE; 294 + unsigned char var8[TAS2563_CAL_VAR_NAME_MAX]; 295 + struct tasdevice_priv *p = h->hda_priv; 296 + struct calidata *cd = &p->cali_data; 297 + struct cali_reg *r = &cd->cali_reg_array; 314 298 unsigned int offset = 0; 299 + unsigned char *data; 315 300 efi_status_t status; 316 301 unsigned int attr; 302 + int ret, i, j, k; 317 303 318 - tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev, 319 - TAS2563_CAL_ARRAY_SIZE, GFP_KERNEL); 320 - if (!tas_priv->cali_data.data) 304 + cd->cali_dat_sz_per_dev = TAS2563_CAL_DATA_SIZE * TASDEV_CALIB_N; 305 + 306 + /* extra byte for each device is the device number */ 307 + cd->total_sz = (cd->cali_dat_sz_per_dev + 1) * p->ndev; 308 + data = cd->data = devm_kzalloc(p->dev, cd->total_sz, 309 + GFP_KERNEL); 310 + if (!data) 321 311 return -ENOMEM; 322 312 323 - for (int i = 0; i < tas_priv->ndev; ++i) { 324 - for (int j = 0; j < TASDEV_CALIB_N; ++j) { 325 - status = efi.get_variable(efi_vars[i][j], 313 + for (i = 0; i < p->ndev; ++i) { 314 + data[offset] = i; 315 + offset++; 316 + for (j = 0; j < TASDEV_CALIB_N; ++j) { 317 + ret = snprintf(var8, sizeof(var8), vars[j], i); 318 + 319 + if (ret < 0 || ret >= sizeof(var8) - 1) { 320 + dev_err(p->dev, "%s: Read %s failed\n", 321 + __func__, var8); 322 + return -EINVAL; 323 + } 324 + /* 325 + * Our variable names are ASCII by construction, but 326 + * EFI names are wide chars. Convert and zero-pad. 327 + */ 328 + memset(efi_name, 0, sizeof(efi_name)); 329 + for (k = 0; k < sizeof(var8) && var8[k]; k++) 330 + efi_name[k] = var8[k]; 331 + status = efi.get_variable(efi_name, 326 332 &efi_guid, &attr, &max_size, 327 - &tas_priv->cali_data.data[offset]); 333 + &data[offset]); 328 334 if (status != EFI_SUCCESS || 329 335 max_size != TAS2563_CAL_DATA_SIZE) { 330 - dev_warn(tas_priv->dev, 331 - "Calibration data read failed %ld\n", status); 336 + dev_warn(p->dev, 337 + "Dev %d: Caldat[%d] read failed %ld\n", 338 + i, j, status); 332 339 return -EINVAL; 333 340 } 334 341 offset += TAS2563_CAL_DATA_SIZE; 335 342 } 336 343 } 337 344 338 - tas_priv->cali_data.total_sz = offset; 339 - tasdevice_apply_calibration(tas_priv); 340 - 341 - return 0; 342 - } 343 - 344 - static void tas2781_apply_calib(struct tasdevice_priv *tas_priv) 345 - { 346 - struct calidata *cali_data = &tas_priv->cali_data; 347 - struct cali_reg *r = &cali_data->cali_reg_array; 348 - unsigned int cali_reg[TASDEV_CALIB_N] = { 349 - TASDEVICE_REG(0, 0x17, 0x74), 350 - TASDEVICE_REG(0, 0x18, 0x0c), 351 - TASDEVICE_REG(0, 0x18, 0x14), 352 - TASDEVICE_REG(0, 0x13, 0x70), 353 - TASDEVICE_REG(0, 0x18, 0x7c), 354 - }; 355 - int i, j, rc; 356 - int oft = 0; 357 - __be32 data; 358 - 359 - if (tas_priv->dspbin_typ != TASDEV_BASIC) { 360 - cali_reg[0] = r->r0_reg; 361 - cali_reg[1] = r->invr0_reg; 362 - cali_reg[2] = r->r0_low_reg; 363 - cali_reg[3] = r->pow_reg; 364 - cali_reg[4] = r->tlimit_reg; 365 - } 366 - 367 - for (i = 0; i < tas_priv->ndev; i++) { 368 - for (j = 0; j < TASDEV_CALIB_N; j++) { 369 - data = cpu_to_be32( 370 - *(uint32_t *)&tas_priv->cali_data.data[oft]); 371 - rc = tasdevice_dev_bulk_write(tas_priv, i, 372 - cali_reg[j], (unsigned char *)&data, 4); 373 - if (rc < 0) 374 - dev_err(tas_priv->dev, 375 - "chn %d calib %d bulk_wr err = %d\n", 376 - i, j, rc); 377 - oft += 4; 378 - } 379 - } 380 - } 381 - 382 - /* Update the calibration data, including speaker impedance, f0, etc, into algo. 383 - * Calibrate data is done by manufacturer in the factory. These data are used 384 - * by Algo for calculating the speaker temperature, speaker membrane excursion 385 - * and f0 in real time during playback. 386 - */ 387 - static int tas2781_save_calibration(struct tasdevice_priv *tas_priv) 388 - { 389 - efi_guid_t efi_guid = EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 390 - 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3); 391 - static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME; 392 - unsigned int attr, crc; 393 - unsigned int *tmp_val; 394 - efi_status_t status; 395 - 396 - /* Lenovo devices */ 397 - if (tas_priv->catlog_id == LENOVO) 398 - efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09, 399 - 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92); 400 - 401 - tas_priv->cali_data.total_sz = 0; 402 - /* Get real size of UEFI variable */ 403 - status = efi.get_variable(efi_name, &efi_guid, &attr, 404 - &tas_priv->cali_data.total_sz, tas_priv->cali_data.data); 405 - if (status == EFI_BUFFER_TOO_SMALL) { 406 - /* Allocate data buffer of data_size bytes */ 407 - tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev, 408 - tas_priv->cali_data.total_sz, GFP_KERNEL); 409 - if (!tas_priv->cali_data.data) 410 - return -ENOMEM; 411 - /* Get variable contents into buffer */ 412 - status = efi.get_variable(efi_name, &efi_guid, &attr, 413 - &tas_priv->cali_data.total_sz, 414 - tas_priv->cali_data.data); 415 - } 416 - if (status != EFI_SUCCESS) 345 + if (cd->total_sz != offset) { 346 + dev_err(p->dev, "%s: tot_size(%lu) and offset(%u) dismatch\n", 347 + __func__, cd->total_sz, offset); 417 348 return -EINVAL; 349 + } 418 350 419 - tmp_val = (unsigned int *)tas_priv->cali_data.data; 351 + r->r0_reg = TAS2563_CAL_R0; 352 + r->invr0_reg = TAS2563_CAL_INVR0; 353 + r->r0_low_reg = TAS2563_CAL_R0_LOW; 354 + r->pow_reg = TAS2563_CAL_POWER; 355 + r->tlimit_reg = TAS2563_CAL_TLIM; 420 356 421 - crc = crc32(~0, tas_priv->cali_data.data, 84) ^ ~0; 422 - dev_dbg(tas_priv->dev, "cali crc 0x%08x PK tmp_val 0x%08x\n", 423 - crc, tmp_val[21]); 424 - 425 - if (crc == tmp_val[21]) { 426 - time64_t seconds = tmp_val[20]; 427 - 428 - dev_dbg(tas_priv->dev, "%ptTsr\n", &seconds); 429 - tasdevice_apply_calibration(tas_priv); 430 - } else 431 - tas_priv->cali_data.total_sz = 0; 357 + /* 358 + * TAS2781_FMWLIB supports two solutions of calibrated data. One is 359 + * from the driver itself: driver reads the calibrated files directly 360 + * during probe; The other from user space: during init of audio hal, 361 + * the audio hal will pass the calibrated data via kcontrol interface. 362 + * Driver will store this data in "struct calidata" for use. For hda 363 + * device, calibrated data are usunally saved into UEFI. So Hda side 364 + * codec driver use the mixture of these two solutions, driver reads 365 + * the data from UEFI, then store this data in "struct calidata" for 366 + * use. 367 + */ 368 + p->is_user_space_calidata = true; 432 369 433 370 return 0; 434 371 } ··· 475 548 /* If calibrated data occurs error, dsp will still works with default 476 549 * calibrated data inside algo. 477 550 */ 478 - tasdevice_save_calibration(tas_priv); 551 + hda_priv->save_calibration(tas_hda); 479 552 480 553 tasdevice_tuning_switch(tas_hda->priv, 0); 481 554 tas_hda->priv->playback_started = true; ··· 508 581 subid = codec->core.subsystem_id >> 16; 509 582 510 583 switch (subid) { 511 - case 0x17aa: 512 - tas_hda->priv->catlog_id = LENOVO; 584 + case 0x1028: 585 + tas_hda->catlog_id = DELL; 513 586 break; 514 587 default: 515 - tas_hda->priv->catlog_id = OTHERS; 588 + tas_hda->catlog_id = LENOVO; 516 589 break; 517 590 } 518 591 ··· 585 658 586 659 if (strstr(dev_name(&clt->dev), "TIAS2781")) { 587 660 device_name = "TIAS2781"; 588 - tas_hda->priv->save_calibration = tas2781_save_calibration; 589 - tas_hda->priv->apply_calibration = tas2781_apply_calib; 661 + hda_priv->save_calibration = tas2781_save_calibration; 590 662 tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR; 591 663 } else if (strstr(dev_name(&clt->dev), "INT8866")) { 592 664 device_name = "INT8866"; 593 - tas_hda->priv->save_calibration = tas2563_save_calibration; 594 - tas_hda->priv->apply_calibration = tas2563_apply_calib; 665 + hda_priv->save_calibration = tas2563_save_calibration; 595 666 tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR; 596 667 } else 597 668 return -ENODEV; ··· 660 735 661 736 tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog); 662 737 663 - /* If calibrated data occurs error, dsp will still works with default 664 - * calibrated data inside algo. 665 - */ 666 - tasdevice_apply_calibration(tas_hda->priv); 667 - 668 738 mutex_unlock(&tas_hda->priv->codec_lock); 669 739 670 740 return 0; ··· 702 782 } 703 783 tasdevice_reset(tas_hda->priv); 704 784 tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog); 705 - 706 - /* If calibrated data occurs error, dsp will still work with default 707 - * calibrated data inside algo. 708 - */ 709 - tasdevice_apply_calibration(tas_hda->priv); 710 785 711 786 if (tas_hda->priv->playback_started) 712 787 tasdevice_tuning_switch(tas_hda->priv, 0);
+1 -166
sound/pci/hda/tas2781_hda_spi.c
··· 526 526 }, 527 527 }; 528 528 529 - static void tas2781_apply_calib(struct tasdevice_priv *tas_priv) 530 - { 531 - struct calidata *cali_data = &tas_priv->cali_data; 532 - struct cali_reg *r = &cali_data->cali_reg_array; 533 - unsigned char *data = cali_data->data; 534 - unsigned int *tmp_val = (unsigned int *)data; 535 - unsigned int cali_reg[TASDEV_CALIB_N] = { 536 - TASDEVICE_REG(0, 0x17, 0x74), 537 - TASDEVICE_REG(0, 0x18, 0x0c), 538 - TASDEVICE_REG(0, 0x18, 0x14), 539 - TASDEVICE_REG(0, 0x13, 0x70), 540 - TASDEVICE_REG(0, 0x18, 0x7c), 541 - }; 542 - unsigned int crc, oft; 543 - unsigned char *buf; 544 - int i, j, k, l; 545 - 546 - if (tmp_val[0] == 2781) { 547 - /* 548 - * New features were added in calibrated Data V3: 549 - * 1. Added calibration registers address define in 550 - * a node, marked as Device id == 0x80. 551 - * New features were added in calibrated Data V2: 552 - * 1. Added some the fields to store the link_id and 553 - * uniqie_id for multi-link solutions 554 - * 2. Support flexible number of devices instead of 555 - * fixed one in V1. 556 - * Layout of calibrated data V2 in UEFI(total 256 bytes): 557 - * ChipID (2781, 4 bytes) 558 - * Data-Group-Sum (4 bytes) 559 - * TimeStamp of Calibration (4 bytes) 560 - * for (i = 0; i < Data-Group-Sum; i++) { 561 - * if (Data type != 0x80) (4 bytes) 562 - * Calibrated Data of Device #i (20 bytes) 563 - * else 564 - * Calibration registers address (5*4 = 20 bytes) 565 - * # V2: No reg addr in data grp section. 566 - * # V3: Normally the last grp is the reg addr. 567 - * } 568 - * CRC (4 bytes) 569 - * Reserved (the rest) 570 - */ 571 - crc = crc32(~0, data, (3 + tmp_val[1] * 6) * 4) ^ ~0; 572 - 573 - if (crc != tmp_val[3 + tmp_val[1] * 6]) { 574 - cali_data->total_sz = 0; 575 - dev_err(tas_priv->dev, "%s: CRC error\n", __func__); 576 - return; 577 - } 578 - 579 - for (j = 0, k = 0; j < tmp_val[1]; j++) { 580 - oft = j * 6 + 3; 581 - if (tmp_val[oft] == TASDEV_UEFI_CALI_REG_ADDR_FLG) { 582 - for (i = 0; i < TASDEV_CALIB_N; i++) { 583 - buf = &data[(oft + i + 1) * 4]; 584 - cali_reg[i] = TASDEVICE_REG(buf[1], 585 - buf[2], buf[3]); 586 - } 587 - } else { 588 - l = j * (cali_data->cali_dat_sz_per_dev + 1); 589 - if (k >= tas_priv->ndev || l > oft * 4) { 590 - dev_err(tas_priv->dev, 591 - "%s: dev sum error\n", 592 - __func__); 593 - cali_data->total_sz = 0; 594 - return; 595 - } 596 - 597 - data[l] = k; 598 - for (i = 0; i < TASDEV_CALIB_N * 4; i++) 599 - data[l + i] = data[4 * oft + i]; 600 - k++; 601 - } 602 - } 603 - } else { 604 - /* 605 - * Calibration data is in V1 format. 606 - * struct cali_data { 607 - * char cali_data[20]; 608 - * } 609 - * 610 - * struct { 611 - * struct cali_data cali_data[4]; 612 - * int TimeStamp of Calibration (4 bytes) 613 - * int CRC (4 bytes) 614 - * } ueft; 615 - */ 616 - crc = crc32(~0, data, 84) ^ ~0; 617 - if (crc != tmp_val[21]) { 618 - cali_data->total_sz = 0; 619 - dev_err(tas_priv->dev, "%s: V1 CRC error\n", __func__); 620 - return; 621 - } 622 - 623 - for (j = tas_priv->ndev - 1; j >= 0; j--) { 624 - l = j * (cali_data->cali_dat_sz_per_dev + 1); 625 - for (i = TASDEV_CALIB_N * 4; i > 0 ; i--) 626 - data[l + i] = data[tas_priv->index * 5 + i]; 627 - data[l+i] = j; 628 - } 629 - } 630 - 631 - if (tas_priv->dspbin_typ == TASDEV_BASIC) { 632 - r->r0_reg = cali_reg[0]; 633 - r->invr0_reg = cali_reg[1]; 634 - r->r0_low_reg = cali_reg[2]; 635 - r->pow_reg = cali_reg[3]; 636 - r->tlimit_reg = cali_reg[4]; 637 - } 638 - 639 - tas_priv->is_user_space_calidata = true; 640 - cali_data->total_sz = 641 - tas_priv->ndev * (cali_data->cali_dat_sz_per_dev + 1); 642 - } 643 - 644 - /* 645 - * Update the calibration data, including speaker impedance, f0, etc, 646 - * into algo. Calibrate data is done by manufacturer in the factory. 647 - * These data are used by Algo for calculating the speaker temperature, 648 - * speaker membrane excursion and f0 in real time during playback. 649 - * Calibration data format in EFI is V2, since 2024. 650 - */ 651 - static int tas2781_save_calibration(struct tasdevice_priv *tas_priv) 652 - { 653 - /* 654 - * GUID was used for data access in BIOS, it was provided by board 655 - * manufactory, like HP: "{02f9af02-7734-4233-b43d-93fe5aa35db3}" 656 - */ 657 - efi_guid_t efi_guid = 658 - EFI_GUID(0x02f9af02, 0x7734, 0x4233, 659 - 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3); 660 - static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME; 661 - struct calidata *cali_data = &tas_priv->cali_data; 662 - unsigned long total_sz = 0; 663 - unsigned int attr, size; 664 - efi_status_t status; 665 - unsigned char *data; 666 - 667 - cali_data->cali_dat_sz_per_dev = 20; 668 - size = tas_priv->ndev * (cali_data->cali_dat_sz_per_dev + 1); 669 - status = efi.get_variable(efi_name, &efi_guid, &attr, &total_sz, NULL); 670 - cali_data->total_sz = total_sz > size ? total_sz : size; 671 - if (status == EFI_BUFFER_TOO_SMALL) { 672 - /* Allocate data buffer of data_size bytes */ 673 - data = tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev, 674 - tas_priv->cali_data.total_sz, GFP_KERNEL); 675 - if (!data) { 676 - tas_priv->cali_data.total_sz = 0; 677 - return -ENOMEM; 678 - } 679 - /* Get variable contents into buffer */ 680 - status = efi.get_variable(efi_name, &efi_guid, &attr, 681 - &tas_priv->cali_data.total_sz, data); 682 - } 683 - if (status != EFI_SUCCESS) { 684 - tas_priv->cali_data.total_sz = 0; 685 - return status; 686 - } 687 - 688 - tas_priv->apply_calibration(tas_priv); 689 - return 0; 690 - } 691 - 692 529 static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda) 693 530 { 694 531 struct hda_codec *codec = tas_hda->priv->codec; ··· 695 858 * If calibrated data occurs error, dsp will still works with default 696 859 * calibrated data inside algo. 697 860 */ 698 - tas2781_save_calibration(tas_priv); 861 + tas2781_save_calibration(tas_hda); 699 862 out: 700 863 release_firmware(fmw); 701 864 pm_runtime_mark_last_busy(tas_hda->priv->dev); ··· 798 961 } 799 962 if (strstr(dev_name(&spi->dev), "TXNW2781")) { 800 963 device_name = "TXNW2781"; 801 - tas_priv->save_calibration = tas2781_save_calibration; 802 - tas_priv->apply_calibration = tas2781_apply_calib; 803 964 } else { 804 965 dev_err(tas_priv->dev, "Unmatched spi dev %s\n", 805 966 dev_name(&spi->dev));
-15
sound/soc/codecs/tas2781-comlib.c
··· 130 130 } 131 131 EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_write); 132 132 133 - int tasdevice_save_calibration(struct tasdevice_priv *tas_priv) 134 - { 135 - if (tas_priv->save_calibration) 136 - return tas_priv->save_calibration(tas_priv); 137 - return -EINVAL; 138 - } 139 - EXPORT_SYMBOL_GPL(tasdevice_save_calibration); 140 - 141 - void tasdevice_apply_calibration(struct tasdevice_priv *tas_priv) 142 - { 143 - if (tas_priv->apply_calibration && tas_priv->cali_data.total_sz) 144 - tas_priv->apply_calibration(tas_priv); 145 - } 146 - EXPORT_SYMBOL_GPL(tasdevice_apply_calibration); 147 - 148 133 static void tasdev_dsp_prog_blk_remove(struct tasdevice_prog *prog) 149 134 { 150 135 struct tasdevice_data *tas_dt;