summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/tas2781.h10
-rw-r--r--sound/pci/hda/tas2781_hda.c179
-rw-r--r--sound/pci/hda/tas2781_hda.h12
-rw-r--r--sound/pci/hda/tas2781_hda_i2c.c245
-rw-r--r--sound/pci/hda/tas2781_hda_spi.c167
-rw-r--r--sound/soc/codecs/tas2781-comlib.c15
6 files changed, 272 insertions, 356 deletions
diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h
index 8192a94d783a..979cdaa12522 100644
--- a/include/sound/tas2781.h
+++ b/include/sound/tas2781.h
@@ -121,11 +121,6 @@ enum dspbin_type {
TASDEV_BETA,
};
-enum device_catlog_id {
- LENOVO = 0,
- OTHERS
-};
-
struct bulk_reg_val {
int reg;
unsigned char val[4];
@@ -172,7 +167,6 @@ struct tasdevice_priv {
struct regmap *regmap;
struct device *dev;
- enum device_catlog_id catlog_id;
unsigned char cal_binaryname[TASDEVICE_MAX_CHANNELS][64];
unsigned char crc8_lkp_tbl[CRC8_TABLE_SIZE];
unsigned char coef_binaryname[64];
@@ -223,8 +217,6 @@ struct tasdevice_priv {
int (*dev_bulk_read)(struct tasdevice_priv *tas_priv,
unsigned short chn, unsigned int reg, unsigned char *p_data,
unsigned int n_length);
- int (*save_calibration)(struct tasdevice_priv *tas_priv);
- void (*apply_calibration)(struct tasdevice_priv *tas_priv);
};
int tasdevice_dev_read(struct tasdevice_priv *tas_priv,
@@ -238,6 +230,4 @@ int tasdevice_dev_bulk_write(
struct tasdevice_priv *tas_priv, unsigned short chn,
unsigned int reg, unsigned char *p_data, unsigned int n_length);
void tasdevice_remove(struct tasdevice_priv *tas_priv);
-int tasdevice_save_calibration(struct tasdevice_priv *tas_priv);
-void tasdevice_apply_calibration(struct tasdevice_priv *tas_priv);
#endif /* __TAS2781_H__ */
diff --git a/sound/pci/hda/tas2781_hda.c b/sound/pci/hda/tas2781_hda.c
index 9d8e0d938d5a..5f1d4b3e9688 100644
--- a/sound/pci/hda/tas2781_hda.c
+++ b/sound/pci/hda/tas2781_hda.c
@@ -18,6 +18,185 @@
#include "tas2781_hda.h"
+const efi_guid_t tasdev_fct_efi_guid[] = {
+ /* DELL */
+ EFI_GUID(0xcc92382d, 0x6337, 0x41cb, 0xa8, 0x8b, 0x8e, 0xce, 0x74,
+ 0x91, 0xea, 0x9f),
+ /* HP */
+ EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a,
+ 0xa3, 0x5d, 0xb3),
+ /* LENOVO & OTHERS */
+ EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09, 0x43, 0xa3, 0xf4,
+ 0x31, 0x0a, 0x92),
+};
+EXPORT_SYMBOL_NS_GPL(tasdev_fct_efi_guid, "SND_HDA_SCODEC_TAS2781");
+
+static void tas2781_apply_calib(struct tasdevice_priv *p)
+{
+ struct calidata *cali_data = &p->cali_data;
+ struct cali_reg *r = &cali_data->cali_reg_array;
+ unsigned char *data = cali_data->data;
+ unsigned int *tmp_val = (unsigned int *)data;
+ unsigned int cali_reg[TASDEV_CALIB_N] = {
+ TASDEVICE_REG(0, 0x17, 0x74),
+ TASDEVICE_REG(0, 0x18, 0x0c),
+ TASDEVICE_REG(0, 0x18, 0x14),
+ TASDEVICE_REG(0, 0x13, 0x70),
+ TASDEVICE_REG(0, 0x18, 0x7c),
+ };
+ unsigned int crc, oft;
+ unsigned char *buf;
+ int i, j, k, l;
+
+ if (tmp_val[0] == 2781) {
+ /*
+ * New features were added in calibrated Data V3:
+ * 1. Added calibration registers address define in
+ * a node, marked as Device id == 0x80.
+ * New features were added in calibrated Data V2:
+ * 1. Added some the fields to store the link_id and
+ * uniqie_id for multi-link solutions
+ * 2. Support flexible number of devices instead of
+ * fixed one in V1.
+ * Layout of calibrated data V2 in UEFI(total 256 bytes):
+ * ChipID (2781, 4 bytes)
+ * Data-Group-Sum (4 bytes)
+ * TimeStamp of Calibration (4 bytes)
+ * for (i = 0; i < Data-Group-Sum; i++) {
+ * if (Data type != 0x80) (4 bytes)
+ * Calibrated Data of Device #i (20 bytes)
+ * else
+ * Calibration registers address (5*4 = 20 bytes)
+ * # V2: No reg addr in data grp section.
+ * # V3: Normally the last grp is the reg addr.
+ * }
+ * CRC (4 bytes)
+ * Reserved (the rest)
+ */
+ crc = crc32(~0, data, (3 + tmp_val[1] * 6) * 4) ^ ~0;
+
+ if (crc != tmp_val[3 + tmp_val[1] * 6]) {
+ cali_data->total_sz = 0;
+ dev_err(p->dev, "%s: CRC error\n", __func__);
+ return;
+ }
+
+ for (j = 0, k = 0; j < tmp_val[1]; j++) {
+ oft = j * 6 + 3;
+ if (tmp_val[oft] == TASDEV_UEFI_CALI_REG_ADDR_FLG) {
+ for (i = 0; i < TASDEV_CALIB_N; i++) {
+ buf = &data[(oft + i + 1) * 4];
+ cali_reg[i] = TASDEVICE_REG(buf[1],
+ buf[2], buf[3]);
+ }
+ } else {
+ l = j * (cali_data->cali_dat_sz_per_dev + 1);
+ if (k >= p->ndev || l > oft * 4) {
+ dev_err(p->dev, "%s: dev sum error\n",
+ __func__);
+ cali_data->total_sz = 0;
+ return;
+ }
+
+ data[l] = k;
+ for (i = 0; i < TASDEV_CALIB_N * 4; i++)
+ data[l + i] = data[4 * oft + i];
+ k++;
+ }
+ }
+ } else {
+ /*
+ * Calibration data is in V1 format.
+ * struct cali_data {
+ * char cali_data[20];
+ * }
+ *
+ * struct {
+ * struct cali_data cali_data[4];
+ * int TimeStamp of Calibration (4 bytes)
+ * int CRC (4 bytes)
+ * } ueft;
+ */
+ crc = crc32(~0, data, 84) ^ ~0;
+ if (crc != tmp_val[21]) {
+ cali_data->total_sz = 0;
+ dev_err(p->dev, "%s: V1 CRC error\n", __func__);
+ return;
+ }
+
+ for (j = p->ndev - 1; j >= 0; j--) {
+ l = j * (cali_data->cali_dat_sz_per_dev + 1);
+ for (i = TASDEV_CALIB_N * 4; i > 0 ; i--)
+ data[l + i] = data[p->index * 5 + i];
+ data[l+i] = j;
+ }
+ }
+
+ if (p->dspbin_typ == TASDEV_BASIC) {
+ r->r0_reg = cali_reg[0];
+ r->invr0_reg = cali_reg[1];
+ r->r0_low_reg = cali_reg[2];
+ r->pow_reg = cali_reg[3];
+ r->tlimit_reg = cali_reg[4];
+ }
+
+ p->is_user_space_calidata = true;
+ cali_data->total_sz = p->ndev * (cali_data->cali_dat_sz_per_dev + 1);
+}
+
+/*
+ * Update the calibration data, including speaker impedance, f0, etc,
+ * into algo. Calibrate data is done by manufacturer in the factory.
+ * The data is used by Algo for calculating the speaker temperature,
+ * speaker membrane excursion and f0 in real time during playback.
+ * Calibration data format in EFI is V2, since 2024.
+ */
+int tas2781_save_calibration(struct tas2781_hda *hda)
+{
+ /*
+ * GUID was used for data access in BIOS, it was provided by board
+ * manufactory.
+ */
+ efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO];
+ static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME;
+ struct tasdevice_priv *p = hda->priv;
+ struct calidata *cali_data = &p->cali_data;
+ unsigned long total_sz = 0;
+ unsigned int attr, size;
+ unsigned char *data;
+ efi_status_t status;
+
+ if (hda->catlog_id < LENOVO)
+ efi_guid = tasdev_fct_efi_guid[hda->catlog_id];
+
+ cali_data->cali_dat_sz_per_dev = 20;
+ size = p->ndev * (cali_data->cali_dat_sz_per_dev + 1);
+ /* Get real size of UEFI variable */
+ status = efi.get_variable(efi_name, &efi_guid, &attr, &total_sz, NULL);
+ cali_data->total_sz = total_sz > size ? total_sz : size;
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ /* Allocate data buffer of data_size bytes */
+ data = p->cali_data.data = devm_kzalloc(p->dev,
+ p->cali_data.total_sz, GFP_KERNEL);
+ if (!data) {
+ p->cali_data.total_sz = 0;
+ return -ENOMEM;
+ }
+ /* Get variable contents into buffer */
+ status = efi.get_variable(efi_name, &efi_guid, &attr,
+ &p->cali_data.total_sz, data);
+ }
+ if (status != EFI_SUCCESS) {
+ p->cali_data.total_sz = 0;
+ return status;
+ }
+
+ tas2781_apply_calib(p);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(tas2781_save_calibration, "SND_HDA_SCODEC_TAS2781");
+
void tas2781_hda_remove(struct device *dev,
const struct component_ops *ops)
{
diff --git a/sound/pci/hda/tas2781_hda.h b/sound/pci/hda/tas2781_hda.h
index 95229083ce6a..575a701c8dfb 100644
--- a/sound/pci/hda/tas2781_hda.h
+++ b/sound/pci/hda/tas2781_hda.h
@@ -9,6 +9,8 @@
#include <sound/asound.h>
+/* Flag of calibration registers address. */
+#define TASDEV_UEFI_CALI_REG_ADDR_FLG BIT(7)
#define TASDEVICE_CALIBRATION_DATA_NAME L"CALI_DATA"
#define TASDEV_CALIB_N 5
@@ -44,6 +46,13 @@
.private_value = xdata, \
}
+enum device_catlog_id {
+ DELL = 0,
+ HP,
+ LENOVO,
+ OTHERS
+};
+
struct tas2781_hda {
struct device *dev;
struct tasdevice_priv *priv;
@@ -54,6 +63,9 @@ struct tas2781_hda {
void *hda_priv;
};
+extern const efi_guid_t tasdev_fct_efi_guid[];
+
+int tas2781_save_calibration(struct tas2781_hda *p);
void tas2781_hda_remove(struct device *dev,
const struct component_ops *ops);
int tasdevice_info_profile(struct snd_kcontrol *kctl,
diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
index 0e51b07dbd05..d91eed9f7804 100644
--- a/sound/pci/hda/tas2781_hda_i2c.c
+++ b/sound/pci/hda/tas2781_hda_i2c.c
@@ -33,26 +33,21 @@
#include "hda_generic.h"
#include "tas2781_hda.h"
-#define TASDEVICE_SPEAKER_CALIBRATION_SIZE 20
-
-#define TAS2563_MAX_CHANNELS 4
-
-#define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c)
-#define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34)
-#define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40)
-#define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48)
-#define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14)
-#define TAS2563_CAL_DATA_SIZE 4
-#define TAS2563_CAL_CH_SIZE 20
-#define TAS2563_CAL_ARRAY_SIZE 80
-
-static unsigned int cal_regs[TASDEV_CALIB_N] = {
- TAS2563_CAL_POWER, TAS2563_CAL_R0, TAS2563_CAL_INVR0,
- TAS2563_CAL_R0_LOW, TAS2563_CAL_TLIM,
-};
+#define TAS2563_CAL_VAR_NAME_MAX 16
+#define TAS2563_CAL_ARRAY_SIZE 80
+#define TAS2563_CAL_DATA_SIZE 4
+#define TAS2563_MAX_CHANNELS 4
+#define TAS2563_CAL_CH_SIZE 20
+
+#define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48)
+#define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c)
+#define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40)
+#define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14)
+#define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34)
struct tas2781_hda_i2c_priv {
struct snd_kcontrol *snd_ctls[2];
+ int (*save_calibration)(struct tas2781_hda *h);
};
static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data)
@@ -283,157 +278,89 @@ static const struct snd_kcontrol_new tas2781_dsp_conf_ctrl = {
.put = tasdevice_config_put,
};
-static void tas2563_apply_calib(struct tasdevice_priv *tas_priv)
+static int tas2563_save_calibration(struct tas2781_hda *h)
{
- int offset = 0;
- __be32 data;
- int ret;
-
- for (int i = 0; i < tas_priv->ndev; i++) {
- for (int j = 0; j < TASDEV_CALIB_N; ++j) {
- data = cpu_to_be32(
- *(uint32_t *)&tas_priv->cali_data.data[offset]);
- ret = tasdevice_dev_bulk_write(tas_priv, i, cal_regs[j],
- (unsigned char *)&data, TAS2563_CAL_DATA_SIZE);
- if (ret)
- dev_err(tas_priv->dev,
- "Error writing calib regs\n");
- offset += TAS2563_CAL_DATA_SIZE;
- }
- }
-}
-
-static int tas2563_save_calibration(struct tasdevice_priv *tas_priv)
-{
- static efi_guid_t efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc,
- 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92);
-
- static efi_char16_t *efi_vars[TAS2563_MAX_CHANNELS][TASDEV_CALIB_N] = {
- { L"Power_1", L"R0_1", L"InvR0_1", L"R0_Low_1", L"TLim_1" },
- { L"Power_2", L"R0_2", L"InvR0_2", L"R0_Low_2", L"TLim_2" },
- { L"Power_3", L"R0_3", L"InvR0_3", L"R0_Low_3", L"TLim_3" },
- { L"Power_4", L"R0_4", L"InvR0_4", L"R0_Low_4", L"TLim_4" },
+ efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO];
+ char *vars[TASDEV_CALIB_N] = {
+ "R0_%d", "InvR0_%d", "R0_Low_%d", "Power_%d", "TLim_%d"
};
-
+ efi_char16_t efi_name[TAS2563_CAL_VAR_NAME_MAX];
unsigned long max_size = TAS2563_CAL_DATA_SIZE;
+ unsigned char var8[TAS2563_CAL_VAR_NAME_MAX];
+ struct tasdevice_priv *p = h->hda_priv;
+ struct calidata *cd = &p->cali_data;
+ struct cali_reg *r = &cd->cali_reg_array;
unsigned int offset = 0;
+ unsigned char *data;
efi_status_t status;
unsigned int attr;
+ int ret, i, j, k;
+
+ cd->cali_dat_sz_per_dev = TAS2563_CAL_DATA_SIZE * TASDEV_CALIB_N;
- tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev,
- TAS2563_CAL_ARRAY_SIZE, GFP_KERNEL);
- if (!tas_priv->cali_data.data)
+ /* extra byte for each device is the device number */
+ cd->total_sz = (cd->cali_dat_sz_per_dev + 1) * p->ndev;
+ data = cd->data = devm_kzalloc(p->dev, cd->total_sz,
+ GFP_KERNEL);
+ if (!data)
return -ENOMEM;
- for (int i = 0; i < tas_priv->ndev; ++i) {
- for (int j = 0; j < TASDEV_CALIB_N; ++j) {
- status = efi.get_variable(efi_vars[i][j],
+ for (i = 0; i < p->ndev; ++i) {
+ data[offset] = i;
+ offset++;
+ for (j = 0; j < TASDEV_CALIB_N; ++j) {
+ ret = snprintf(var8, sizeof(var8), vars[j], i);
+
+ if (ret < 0 || ret >= sizeof(var8) - 1) {
+ dev_err(p->dev, "%s: Read %s failed\n",
+ __func__, var8);
+ return -EINVAL;
+ }
+ /*
+ * Our variable names are ASCII by construction, but
+ * EFI names are wide chars. Convert and zero-pad.
+ */
+ memset(efi_name, 0, sizeof(efi_name));
+ for (k = 0; k < sizeof(var8) && var8[k]; k++)
+ efi_name[k] = var8[k];
+ status = efi.get_variable(efi_name,
&efi_guid, &attr, &max_size,
- &tas_priv->cali_data.data[offset]);
+ &data[offset]);
if (status != EFI_SUCCESS ||
max_size != TAS2563_CAL_DATA_SIZE) {
- dev_warn(tas_priv->dev,
- "Calibration data read failed %ld\n", status);
+ dev_warn(p->dev,
+ "Dev %d: Caldat[%d] read failed %ld\n",
+ i, j, status);
return -EINVAL;
}
offset += TAS2563_CAL_DATA_SIZE;
}
}
- tas_priv->cali_data.total_sz = offset;
- tasdevice_apply_calibration(tas_priv);
-
- return 0;
-}
-
-static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)
-{
- struct calidata *cali_data = &tas_priv->cali_data;
- struct cali_reg *r = &cali_data->cali_reg_array;
- unsigned int cali_reg[TASDEV_CALIB_N] = {
- TASDEVICE_REG(0, 0x17, 0x74),
- TASDEVICE_REG(0, 0x18, 0x0c),
- TASDEVICE_REG(0, 0x18, 0x14),
- TASDEVICE_REG(0, 0x13, 0x70),
- TASDEVICE_REG(0, 0x18, 0x7c),
- };
- int i, j, rc;
- int oft = 0;
- __be32 data;
-
- if (tas_priv->dspbin_typ != TASDEV_BASIC) {
- cali_reg[0] = r->r0_reg;
- cali_reg[1] = r->invr0_reg;
- cali_reg[2] = r->r0_low_reg;
- cali_reg[3] = r->pow_reg;
- cali_reg[4] = r->tlimit_reg;
- }
-
- for (i = 0; i < tas_priv->ndev; i++) {
- for (j = 0; j < TASDEV_CALIB_N; j++) {
- data = cpu_to_be32(
- *(uint32_t *)&tas_priv->cali_data.data[oft]);
- rc = tasdevice_dev_bulk_write(tas_priv, i,
- cali_reg[j], (unsigned char *)&data, 4);
- if (rc < 0)
- dev_err(tas_priv->dev,
- "chn %d calib %d bulk_wr err = %d\n",
- i, j, rc);
- oft += 4;
- }
- }
-}
-
-/* Update the calibration data, including speaker impedance, f0, etc, into algo.
- * Calibrate data is done by manufacturer in the factory. These data are used
- * by Algo for calculating the speaker temperature, speaker membrane excursion
- * and f0 in real time during playback.
- */
-static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
-{
- efi_guid_t efi_guid = EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d,
- 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3);
- static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME;
- unsigned int attr, crc;
- unsigned int *tmp_val;
- efi_status_t status;
-
- /* Lenovo devices */
- if (tas_priv->catlog_id == LENOVO)
- efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09,
- 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92);
-
- tas_priv->cali_data.total_sz = 0;
- /* Get real size of UEFI variable */
- status = efi.get_variable(efi_name, &efi_guid, &attr,
- &tas_priv->cali_data.total_sz, tas_priv->cali_data.data);
- if (status == EFI_BUFFER_TOO_SMALL) {
- /* Allocate data buffer of data_size bytes */
- tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev,
- tas_priv->cali_data.total_sz, GFP_KERNEL);
- if (!tas_priv->cali_data.data)
- return -ENOMEM;
- /* Get variable contents into buffer */
- status = efi.get_variable(efi_name, &efi_guid, &attr,
- &tas_priv->cali_data.total_sz,
- tas_priv->cali_data.data);
- }
- if (status != EFI_SUCCESS)
+ if (cd->total_sz != offset) {
+ dev_err(p->dev, "%s: tot_size(%lu) and offset(%u) dismatch\n",
+ __func__, cd->total_sz, offset);
return -EINVAL;
+ }
- tmp_val = (unsigned int *)tas_priv->cali_data.data;
-
- crc = crc32(~0, tas_priv->cali_data.data, 84) ^ ~0;
- dev_dbg(tas_priv->dev, "cali crc 0x%08x PK tmp_val 0x%08x\n",
- crc, tmp_val[21]);
-
- if (crc == tmp_val[21]) {
- time64_t seconds = tmp_val[20];
+ r->r0_reg = TAS2563_CAL_R0;
+ r->invr0_reg = TAS2563_CAL_INVR0;
+ r->r0_low_reg = TAS2563_CAL_R0_LOW;
+ r->pow_reg = TAS2563_CAL_POWER;
+ r->tlimit_reg = TAS2563_CAL_TLIM;
- dev_dbg(tas_priv->dev, "%ptTsr\n", &seconds);
- tasdevice_apply_calibration(tas_priv);
- } else
- tas_priv->cali_data.total_sz = 0;
+ /*
+ * TAS2781_FMWLIB supports two solutions of calibrated data. One is
+ * from the driver itself: driver reads the calibrated files directly
+ * during probe; The other 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. For hda
+ * device, calibrated data are usunally saved into UEFI. So Hda side
+ * codec driver use the mixture of these two solutions, driver reads
+ * the data from UEFI, then store this data in "struct calidata" for
+ * use.
+ */
+ p->is_user_space_calidata = true;
return 0;
}
@@ -548,7 +475,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
/* If calibrated data occurs error, dsp will still works with default
* calibrated data inside algo.
*/
- tasdevice_save_calibration(tas_priv);
+ hda_priv->save_calibration(tas_hda);
tasdevice_tuning_switch(tas_hda->priv, 0);
tas_hda->priv->playback_started = true;
@@ -581,11 +508,11 @@ static int tas2781_hda_bind(struct device *dev, struct device *master,
subid = codec->core.subsystem_id >> 16;
switch (subid) {
- case 0x17aa:
- tas_hda->priv->catlog_id = LENOVO;
+ case 0x1028:
+ tas_hda->catlog_id = DELL;
break;
default:
- tas_hda->priv->catlog_id = OTHERS;
+ tas_hda->catlog_id = LENOVO;
break;
}
@@ -658,13 +585,11 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
if (strstr(dev_name(&clt->dev), "TIAS2781")) {
device_name = "TIAS2781";
- tas_hda->priv->save_calibration = tas2781_save_calibration;
- tas_hda->priv->apply_calibration = tas2781_apply_calib;
+ hda_priv->save_calibration = tas2781_save_calibration;
tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR;
} else if (strstr(dev_name(&clt->dev), "INT8866")) {
device_name = "INT8866";
- tas_hda->priv->save_calibration = tas2563_save_calibration;
- tas_hda->priv->apply_calibration = tas2563_apply_calib;
+ hda_priv->save_calibration = tas2563_save_calibration;
tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR;
} else
return -ENODEV;
@@ -735,11 +660,6 @@ static int tas2781_runtime_resume(struct device *dev)
tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);
- /* If calibrated data occurs error, dsp will still works with default
- * calibrated data inside algo.
- */
- tasdevice_apply_calibration(tas_hda->priv);
-
mutex_unlock(&tas_hda->priv->codec_lock);
return 0;
@@ -783,11 +703,6 @@ static int tas2781_system_resume(struct device *dev)
tasdevice_reset(tas_hda->priv);
tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);
- /* If calibrated data occurs error, dsp will still work with default
- * calibrated data inside algo.
- */
- tasdevice_apply_calibration(tas_hda->priv);
-
if (tas_hda->priv->playback_started)
tasdevice_tuning_switch(tas_hda->priv, 0);
diff --git a/sound/pci/hda/tas2781_hda_spi.c b/sound/pci/hda/tas2781_hda_spi.c
index e0f8603c4854..5c03e9d2283a 100644
--- a/sound/pci/hda/tas2781_hda_spi.c
+++ b/sound/pci/hda/tas2781_hda_spi.c
@@ -526,169 +526,6 @@ static struct snd_kcontrol_new tas2781_dsp_ctls[] = {
},
};
-static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)
-{
- struct calidata *cali_data = &tas_priv->cali_data;
- struct cali_reg *r = &cali_data->cali_reg_array;
- unsigned char *data = cali_data->data;
- unsigned int *tmp_val = (unsigned int *)data;
- unsigned int cali_reg[TASDEV_CALIB_N] = {
- TASDEVICE_REG(0, 0x17, 0x74),
- TASDEVICE_REG(0, 0x18, 0x0c),
- TASDEVICE_REG(0, 0x18, 0x14),
- TASDEVICE_REG(0, 0x13, 0x70),
- TASDEVICE_REG(0, 0x18, 0x7c),
- };
- unsigned int crc, oft;
- unsigned char *buf;
- int i, j, k, l;
-
- if (tmp_val[0] == 2781) {
- /*
- * New features were added in calibrated Data V3:
- * 1. Added calibration registers address define in
- * a node, marked as Device id == 0x80.
- * New features were added in calibrated Data V2:
- * 1. Added some the fields to store the link_id and
- * uniqie_id for multi-link solutions
- * 2. Support flexible number of devices instead of
- * fixed one in V1.
- * Layout of calibrated data V2 in UEFI(total 256 bytes):
- * ChipID (2781, 4 bytes)
- * Data-Group-Sum (4 bytes)
- * TimeStamp of Calibration (4 bytes)
- * for (i = 0; i < Data-Group-Sum; i++) {
- * if (Data type != 0x80) (4 bytes)
- * Calibrated Data of Device #i (20 bytes)
- * else
- * Calibration registers address (5*4 = 20 bytes)
- * # V2: No reg addr in data grp section.
- * # V3: Normally the last grp is the reg addr.
- * }
- * CRC (4 bytes)
- * Reserved (the rest)
- */
- crc = crc32(~0, data, (3 + tmp_val[1] * 6) * 4) ^ ~0;
-
- if (crc != tmp_val[3 + tmp_val[1] * 6]) {
- cali_data->total_sz = 0;
- dev_err(tas_priv->dev, "%s: CRC error\n", __func__);
- return;
- }
-
- for (j = 0, k = 0; j < tmp_val[1]; j++) {
- oft = j * 6 + 3;
- if (tmp_val[oft] == TASDEV_UEFI_CALI_REG_ADDR_FLG) {
- for (i = 0; i < TASDEV_CALIB_N; i++) {
- buf = &data[(oft + i + 1) * 4];
- cali_reg[i] = TASDEVICE_REG(buf[1],
- buf[2], buf[3]);
- }
- } else {
- l = j * (cali_data->cali_dat_sz_per_dev + 1);
- if (k >= tas_priv->ndev || l > oft * 4) {
- dev_err(tas_priv->dev,
- "%s: dev sum error\n",
- __func__);
- cali_data->total_sz = 0;
- return;
- }
-
- data[l] = k;
- for (i = 0; i < TASDEV_CALIB_N * 4; i++)
- data[l + i] = data[4 * oft + i];
- k++;
- }
- }
- } else {
- /*
- * Calibration data is in V1 format.
- * struct cali_data {
- * char cali_data[20];
- * }
- *
- * struct {
- * struct cali_data cali_data[4];
- * int TimeStamp of Calibration (4 bytes)
- * int CRC (4 bytes)
- * } ueft;
- */
- crc = crc32(~0, data, 84) ^ ~0;
- if (crc != tmp_val[21]) {
- cali_data->total_sz = 0;
- dev_err(tas_priv->dev, "%s: V1 CRC error\n", __func__);
- return;
- }
-
- for (j = tas_priv->ndev - 1; j >= 0; j--) {
- l = j * (cali_data->cali_dat_sz_per_dev + 1);
- for (i = TASDEV_CALIB_N * 4; i > 0 ; i--)
- data[l + i] = data[tas_priv->index * 5 + i];
- data[l+i] = j;
- }
- }
-
- if (tas_priv->dspbin_typ == TASDEV_BASIC) {
- r->r0_reg = cali_reg[0];
- r->invr0_reg = cali_reg[1];
- r->r0_low_reg = cali_reg[2];
- r->pow_reg = cali_reg[3];
- r->tlimit_reg = cali_reg[4];
- }
-
- tas_priv->is_user_space_calidata = true;
- cali_data->total_sz =
- tas_priv->ndev * (cali_data->cali_dat_sz_per_dev + 1);
-}
-
-/*
- * Update the calibration data, including speaker impedance, f0, etc,
- * into algo. Calibrate data is done by manufacturer in the factory.
- * These data are used by Algo for calculating the speaker temperature,
- * speaker membrane excursion and f0 in real time during playback.
- * Calibration data format in EFI is V2, since 2024.
- */
-static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
-{
- /*
- * GUID was used for data access in BIOS, it was provided by board
- * manufactory, like HP: "{02f9af02-7734-4233-b43d-93fe5aa35db3}"
- */
- efi_guid_t efi_guid =
- EFI_GUID(0x02f9af02, 0x7734, 0x4233,
- 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3);
- static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME;
- struct calidata *cali_data = &tas_priv->cali_data;
- unsigned long total_sz = 0;
- unsigned int attr, size;
- efi_status_t status;
- unsigned char *data;
-
- cali_data->cali_dat_sz_per_dev = 20;
- size = tas_priv->ndev * (cali_data->cali_dat_sz_per_dev + 1);
- status = efi.get_variable(efi_name, &efi_guid, &attr, &total_sz, NULL);
- cali_data->total_sz = total_sz > size ? total_sz : size;
- if (status == EFI_BUFFER_TOO_SMALL) {
- /* Allocate data buffer of data_size bytes */
- data = tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev,
- tas_priv->cali_data.total_sz, GFP_KERNEL);
- if (!data) {
- tas_priv->cali_data.total_sz = 0;
- return -ENOMEM;
- }
- /* Get variable contents into buffer */
- status = efi.get_variable(efi_name, &efi_guid, &attr,
- &tas_priv->cali_data.total_sz, data);
- }
- if (status != EFI_SUCCESS) {
- tas_priv->cali_data.total_sz = 0;
- return status;
- }
-
- tas_priv->apply_calibration(tas_priv);
- return 0;
-}
-
static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda)
{
struct hda_codec *codec = tas_hda->priv->codec;
@@ -858,7 +695,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
* If calibrated data occurs error, dsp will still works with default
* calibrated data inside algo.
*/
- tas2781_save_calibration(tas_priv);
+ tas2781_save_calibration(tas_hda);
out:
release_firmware(fmw);
pm_runtime_mark_last_busy(tas_hda->priv->dev);
@@ -961,8 +798,6 @@ static int tas2781_hda_spi_probe(struct spi_device *spi)
}
if (strstr(dev_name(&spi->dev), "TXNW2781")) {
device_name = "TXNW2781";
- tas_priv->save_calibration = tas2781_save_calibration;
- tas_priv->apply_calibration = tas2781_apply_calib;
} else {
dev_err(tas_priv->dev, "Unmatched spi dev %s\n",
dev_name(&spi->dev));
diff --git a/sound/soc/codecs/tas2781-comlib.c b/sound/soc/codecs/tas2781-comlib.c
index 076c1d955972..4cec9f8a00af 100644
--- a/sound/soc/codecs/tas2781-comlib.c
+++ b/sound/soc/codecs/tas2781-comlib.c
@@ -130,21 +130,6 @@ out:
}
EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_write);
-int tasdevice_save_calibration(struct tasdevice_priv *tas_priv)
-{
- if (tas_priv->save_calibration)
- return tas_priv->save_calibration(tas_priv);
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(tasdevice_save_calibration);
-
-void tasdevice_apply_calibration(struct tasdevice_priv *tas_priv)
-{
- if (tas_priv->apply_calibration && tas_priv->cali_data.total_sz)
- tas_priv->apply_calibration(tas_priv);
-}
-EXPORT_SYMBOL_GPL(tasdevice_apply_calibration);
-
static void tasdev_dsp_prog_blk_remove(struct tasdevice_prog *prog)
{
struct tasdevice_data *tas_dt;