1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // TAS2781 HDA Shared Lib for I2C&SPI driver
4 //
5 // Copyright 2025 Texas Instruments, Inc.
6 //
7 // Author: Shenghao Ding <shenghao-ding@ti.com>
8
9 #include <linux/component.h>
10 #include <linux/crc8.h>
11 #include <linux/crc32.h>
12 #include <linux/efi.h>
13 #include <linux/firmware.h>
14 #include <linux/i2c.h>
15 #include <linux/pm_runtime.h>
16 #include <sound/soc.h>
17 #include <sound/tas2781.h>
18
19 #include "tas2781_hda.h"
20
21 #define CALIBRATION_DATA_AREA_NUM 2
22
23 const efi_guid_t tasdev_fct_efi_guid[] = {
24 /* DELL */
25 EFI_GUID(0xcc92382d, 0x6337, 0x41cb, 0xa8, 0x8b, 0x8e, 0xce, 0x74,
26 0x91, 0xea, 0x9f),
27 /* HP */
28 EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a,
29 0xa3, 0x5d, 0xb3),
30 /* LENOVO & OTHERS */
31 EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09, 0x43, 0xa3, 0xf4,
32 0x31, 0x0a, 0x92),
33 };
34 EXPORT_SYMBOL_NS_GPL(tasdev_fct_efi_guid, "SND_HDA_SCODEC_TAS2781");
35
36 /*
37 * The order of calibrated-data writing function is a bit different from the
38 * order in UEFI. Here is the conversion to match the order of calibrated-data
39 * writing function.
40 */
cali_cnv(unsigned char * data,unsigned int base,int offset)41 static void cali_cnv(unsigned char *data, unsigned int base, int offset)
42 {
43 struct cali_reg reg_data;
44
45 memcpy(®_data, &data[base], sizeof(reg_data));
46 /* the data order has to be swapped between r0_low_reg and inv0_reg */
47 swap(reg_data.r0_low_reg, reg_data.invr0_reg);
48
49 cpu_to_be32_array((__force __be32 *)(data + offset + 1),
50 (u32 *)®_data, TASDEV_CALIB_N);
51 }
52
tas2781_apply_calib(struct tasdevice_priv * p)53 static void tas2781_apply_calib(struct tasdevice_priv *p)
54 {
55 struct calidata *cali_data = &p->cali_data;
56 struct cali_reg *r = &cali_data->cali_reg_array;
57 unsigned char *data = cali_data->data;
58 unsigned int *tmp_val = (unsigned int *)data;
59 unsigned int cali_reg[TASDEV_CALIB_N] = {
60 TASDEVICE_REG(0, 0x17, 0x74),
61 TASDEVICE_REG(0, 0x18, 0x0c),
62 TASDEVICE_REG(0, 0x18, 0x14),
63 TASDEVICE_REG(0, 0x13, 0x70),
64 TASDEVICE_REG(0, 0x18, 0x7c),
65 };
66 unsigned int crc, oft, node_num;
67 unsigned char *buf;
68 int i, j, k, l;
69
70 if (tmp_val[0] == 2781) {
71 /*
72 * New features were added in calibrated Data V3:
73 * 1. Added calibration registers address define in
74 * a node, marked as Device id == 0x80.
75 * New features were added in calibrated Data V2:
76 * 1. Added some the fields to store the link_id and
77 * uniqie_id for multi-link solutions
78 * 2. Support flexible number of devices instead of
79 * fixed one in V1.
80 * Layout of calibrated data V2 in UEFI(total 256 bytes):
81 * ChipID (2781, 4 bytes)
82 * Data-Group-Sum (4 bytes)
83 * TimeStamp of Calibration (4 bytes)
84 * for (i = 0; i < Data-Group-Sum; i++) {
85 * if (Data type != 0x80) (4 bytes)
86 * Calibrated Data of Device #i (20 bytes)
87 * else
88 * Calibration registers address (5*4 = 20 bytes)
89 * # V2: No reg addr in data grp section.
90 * # V3: Normally the last grp is the reg addr.
91 * }
92 * CRC (4 bytes)
93 * Reserved (the rest)
94 */
95 crc = crc32(~0, data, (3 + tmp_val[1] * 6) * 4) ^ ~0;
96
97 if (crc != tmp_val[3 + tmp_val[1] * 6]) {
98 cali_data->total_sz = 0;
99 dev_err(p->dev, "%s: CRC error\n", __func__);
100 return;
101 }
102 node_num = tmp_val[1];
103
104 for (j = 0, k = 0; j < node_num; j++) {
105 oft = j * 6 + 3;
106 if (tmp_val[oft] == TASDEV_UEFI_CALI_REG_ADDR_FLG) {
107 for (i = 0; i < TASDEV_CALIB_N; i++) {
108 buf = &data[(oft + i + 1) * 4];
109 cali_reg[i] = TASDEVICE_REG(buf[1],
110 buf[2], buf[3]);
111 }
112 } else {
113 l = j * (cali_data->cali_dat_sz_per_dev + 1);
114 if (k >= p->ndev || l > oft * 4) {
115 dev_err(p->dev, "%s: dev sum error\n",
116 __func__);
117 cali_data->total_sz = 0;
118 return;
119 }
120
121 data[l] = k;
122 oft++;
123 cali_cnv(data, 4 * oft, l);
124 k++;
125 }
126 }
127 } else {
128 /*
129 * Calibration data is in V1 format.
130 * struct cali_data {
131 * char cali_data[20];
132 * }
133 *
134 * struct {
135 * struct cali_data cali_data[4];
136 * int TimeStamp of Calibration (4 bytes)
137 * int CRC (4 bytes)
138 * } ueft;
139 */
140 crc = crc32(~0, data, 84) ^ ~0;
141 if (crc != tmp_val[21]) {
142 cali_data->total_sz = 0;
143 dev_err(p->dev, "%s: V1 CRC error\n", __func__);
144 return;
145 }
146
147 for (j = p->ndev - 1; j >= 0; j--) {
148 l = j * (cali_data->cali_dat_sz_per_dev + 1);
149 cali_cnv(data, cali_data->cali_dat_sz_per_dev * j, l);
150 data[l] = j;
151 }
152 }
153
154 if (p->dspbin_typ == TASDEV_BASIC) {
155 r->r0_reg = cali_reg[0];
156 r->invr0_reg = cali_reg[1];
157 r->r0_low_reg = cali_reg[2];
158 r->pow_reg = cali_reg[3];
159 r->tlimit_reg = cali_reg[4];
160 }
161
162 p->is_user_space_calidata = true;
163 cali_data->total_sz = p->ndev * (cali_data->cali_dat_sz_per_dev + 1);
164 }
165
166 /*
167 * Update the calibration data, including speaker impedance, f0, etc,
168 * into algo. Calibrate data is done by manufacturer in the factory.
169 * The data is used by Algo for calculating the speaker temperature,
170 * speaker membrane excursion and f0 in real time during playback.
171 * Calibration data format in EFI is V2, since 2024.
172 */
tas2781_save_calibration(struct tas2781_hda * hda)173 int tas2781_save_calibration(struct tas2781_hda *hda)
174 {
175 /*
176 * GUID was used for data access in BIOS, it was provided by board
177 * manufactory.
178 */
179 efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO];
180 /*
181 * Some devices save the calibrated data into L"CALI_DATA",
182 * and others into L"SmartAmpCalibrationData".
183 */
184 static efi_char16_t *efi_name[CALIBRATION_DATA_AREA_NUM] = {
185 L"CALI_DATA",
186 L"SmartAmpCalibrationData",
187 };
188 struct tasdevice_priv *p = hda->priv;
189 struct calidata *cali_data = &p->cali_data;
190 unsigned long total_sz = 0;
191 unsigned int attr, size;
192 unsigned char *data;
193 efi_status_t status;
194 int i;
195
196 if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) {
197 dev_err(p->dev, "%s: NO EFI FOUND!\n", __func__);
198 return -EINVAL;
199 }
200
201 if (hda->catlog_id < LENOVO)
202 efi_guid = tasdev_fct_efi_guid[hda->catlog_id];
203
204 cali_data->cali_dat_sz_per_dev = 20;
205 size = p->ndev * (cali_data->cali_dat_sz_per_dev + 1);
206 for (i = 0; i < CALIBRATION_DATA_AREA_NUM; i++) {
207 /* Get real size of UEFI variable */
208 status = efi.get_variable(efi_name[i], &efi_guid, &attr,
209 &total_sz, NULL);
210 cali_data->total_sz = total_sz > size ? total_sz : size;
211 if (status == EFI_BUFFER_TOO_SMALL) {
212 /* Allocate data buffer of data_size bytes */
213 data = cali_data->data = devm_kzalloc(p->dev,
214 cali_data->total_sz, GFP_KERNEL);
215 if (!data) {
216 status = -ENOMEM;
217 continue;
218 }
219 /* Get variable contents into buffer */
220 status = efi.get_variable(efi_name[i], &efi_guid,
221 &attr, &cali_data->total_sz, data);
222 }
223 /* Check whether get the calibrated data */
224 if (status == EFI_SUCCESS)
225 break;
226 }
227
228 if (status != EFI_SUCCESS) {
229 cali_data->total_sz = 0;
230 return status;
231 }
232
233 tas2781_apply_calib(p);
234
235 return 0;
236 }
237 EXPORT_SYMBOL_NS_GPL(tas2781_save_calibration, "SND_HDA_SCODEC_TAS2781");
238
tas2781_hda_remove(struct device * dev,const struct component_ops * ops)239 void tas2781_hda_remove(struct device *dev,
240 const struct component_ops *ops)
241 {
242 struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
243
244 component_del(tas_hda->dev, ops);
245
246 pm_runtime_get_sync(tas_hda->dev);
247 pm_runtime_disable(tas_hda->dev);
248
249 pm_runtime_put_noidle(tas_hda->dev);
250
251 tasdevice_remove(tas_hda->priv);
252 }
253 EXPORT_SYMBOL_NS_GPL(tas2781_hda_remove, "SND_HDA_SCODEC_TAS2781");
254
tasdevice_info_profile(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)255 int tasdevice_info_profile(struct snd_kcontrol *kcontrol,
256 struct snd_ctl_elem_info *uinfo)
257 {
258 struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
259
260 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
261 uinfo->count = 1;
262 uinfo->value.integer.min = 0;
263 uinfo->value.integer.max = tas_priv->rcabin.ncfgs - 1;
264
265 return 0;
266 }
267 EXPORT_SYMBOL_NS_GPL(tasdevice_info_profile, "SND_HDA_SCODEC_TAS2781");
268
tasdevice_info_programs(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)269 int tasdevice_info_programs(struct snd_kcontrol *kcontrol,
270 struct snd_ctl_elem_info *uinfo)
271 {
272 struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
273
274 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
275 uinfo->count = 1;
276 uinfo->value.integer.min = 0;
277 uinfo->value.integer.max = tas_priv->fmw->nr_programs - 1;
278
279 return 0;
280 }
281 EXPORT_SYMBOL_NS_GPL(tasdevice_info_programs, "SND_HDA_SCODEC_TAS2781");
282
tasdevice_info_config(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)283 int tasdevice_info_config(struct snd_kcontrol *kcontrol,
284 struct snd_ctl_elem_info *uinfo)
285 {
286 struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
287 struct tasdevice_fw *tas_fw = tas_priv->fmw;
288
289 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
290 uinfo->count = 1;
291 uinfo->value.integer.min = 0;
292 uinfo->value.integer.max = tas_fw->nr_configurations - 1;
293
294 return 0;
295 }
296 EXPORT_SYMBOL_NS_GPL(tasdevice_info_config, "SND_HDA_SCODEC_TAS2781");
297
tasdevice_get_profile_id(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)298 int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol,
299 struct snd_ctl_elem_value *ucontrol)
300 {
301 struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
302
303 ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id;
304
305 dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", __func__,
306 kcontrol->id.name, tas_priv->rcabin.profile_cfg_id);
307
308 return 0;
309 }
310 EXPORT_SYMBOL_NS_GPL(tasdevice_get_profile_id, "SND_HDA_SCODEC_TAS2781");
311
tasdevice_set_profile_id(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)312 int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
313 struct snd_ctl_elem_value *ucontrol)
314 {
315 struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
316 int profile_id = ucontrol->value.integer.value[0];
317 int max = tas_priv->rcabin.ncfgs - 1;
318 int val, ret = 0;
319
320 val = clamp(profile_id, 0, max);
321
322 guard(mutex)(&tas_priv->codec_lock);
323
324 dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", __func__,
325 kcontrol->id.name, tas_priv->rcabin.profile_cfg_id, val);
326
327 if (tas_priv->rcabin.profile_cfg_id != val) {
328 tas_priv->rcabin.profile_cfg_id = val;
329 ret = 1;
330 }
331
332 return ret;
333 }
334 EXPORT_SYMBOL_NS_GPL(tasdevice_set_profile_id, "SND_HDA_SCODEC_TAS2781");
335
tasdevice_program_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)336 int tasdevice_program_get(struct snd_kcontrol *kcontrol,
337 struct snd_ctl_elem_value *ucontrol)
338 {
339 struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
340
341 ucontrol->value.integer.value[0] = tas_priv->cur_prog;
342
343 dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", __func__,
344 kcontrol->id.name, tas_priv->cur_prog);
345
346 return 0;
347 }
348 EXPORT_SYMBOL_NS_GPL(tasdevice_program_get, "SND_HDA_SCODEC_TAS2781");
349
tasdevice_program_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)350 int tasdevice_program_put(struct snd_kcontrol *kcontrol,
351 struct snd_ctl_elem_value *ucontrol)
352 {
353 struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
354 struct tasdevice_fw *tas_fw = tas_priv->fmw;
355 int nr_program = ucontrol->value.integer.value[0];
356 int max = tas_fw->nr_programs - 1;
357 int val, ret = 0;
358
359 val = clamp(nr_program, 0, max);
360
361 guard(mutex)(&tas_priv->codec_lock);
362
363 dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", __func__,
364 kcontrol->id.name, tas_priv->cur_prog, val);
365
366 if (tas_priv->cur_prog != val) {
367 tas_priv->cur_prog = val;
368 ret = 1;
369 }
370
371 return ret;
372 }
373 EXPORT_SYMBOL_NS_GPL(tasdevice_program_put, "SND_HDA_SCODEC_TAS2781");
374
tasdevice_config_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)375 int tasdevice_config_get(struct snd_kcontrol *kcontrol,
376 struct snd_ctl_elem_value *ucontrol)
377 {
378 struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
379
380 ucontrol->value.integer.value[0] = tas_priv->cur_conf;
381
382 dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", __func__,
383 kcontrol->id.name, tas_priv->cur_conf);
384
385 return 0;
386 }
387 EXPORT_SYMBOL_NS_GPL(tasdevice_config_get, "SND_HDA_SCODEC_TAS2781");
388
tasdevice_config_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)389 int tasdevice_config_put(struct snd_kcontrol *kcontrol,
390 struct snd_ctl_elem_value *ucontrol)
391 {
392 struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
393 struct tasdevice_fw *tas_fw = tas_priv->fmw;
394 int nr_config = ucontrol->value.integer.value[0];
395 int max = tas_fw->nr_configurations - 1;
396 int val, ret = 0;
397
398 val = clamp(nr_config, 0, max);
399
400 guard(mutex)(&tas_priv->codec_lock);
401
402 dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", __func__,
403 kcontrol->id.name, tas_priv->cur_conf, val);
404
405 if (tas_priv->cur_conf != val) {
406 tas_priv->cur_conf = val;
407 ret = 1;
408 }
409
410 return ret;
411 }
412 EXPORT_SYMBOL_NS_GPL(tasdevice_config_put, "SND_HDA_SCODEC_TAS2781");
413
414 MODULE_DESCRIPTION("TAS2781 HDA Driver");
415 MODULE_LICENSE("GPL");
416 MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
417